2015-10-16 6 views
10

Vorrei determinare a livello di programmazione se l'app per iOS viene eseguita direttamente da XCode (nel simulatore o su un dispositivo collegato). Ho provato la soluzione DEBUG descritta come here, ma quando poi disconnetto da Xcode e rieseguo l'app, continua a pensare che sia in modalità di debug. Penso che quello che sto cercando è una versione Swift di this functionRileva se l'app Swift viene eseguita da Xcode

#include <assert.h> 
#include <stdbool.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/sysctl.h> 

static bool AmIBeingDebugged(void) 
    // Returns true if the current process is being debugged (either 
    // running under the debugger or has a debugger attached post facto). 
{ 
    int     junk; 
    int     mib[4]; 
    struct kinfo_proc info; 
    size_t    size; 

    // Initialize the flags so that, if sysctl fails for some bizarre 
    // reason, we get a predictable result. 

    info.kp_proc.p_flag = 0; 

    // Initialize mib, which tells sysctl the info we want, in this case 
    // we're looking for information about a specific process ID. 

    mib[0] = CTL_KERN; 
    mib[1] = KERN_PROC; 
    mib[2] = KERN_PROC_PID; 
    mib[3] = getpid(); 

    // Call sysctl. 
    size = sizeof(info); 
    junk = sysctl(mib, sizeof(mib)/sizeof(*mib), &info, &size, NULL, 0); 
    assert(junk == 0); 

    // We're being debugged if the P_TRACED flag is set. 
    return ((info.kp_proc.p_flag & P_TRACED) != 0); 
} 
+1

È possibile chiamare funzioni C da Swift, quindi non devi davvero tradurlo. –

+0

Martin, questa è la risposta che ho intenzione di mettere, la metto come risposta e la inviterò. – Knight0fDragon

+0

Ecco un rapido tentativo non verificato di convertire il codice in Swift (solo per divertimento): https://gist.github.com/getaaron/8d48489274a873835636. Non ho tempo per giocarci ulteriormente adesso, ma forse ti farà iniziare. –

risposta

33

Si potrebbe semplicemente mantenere la funzione C e chiamare da Swift. Le ricette indicate in How to call Objective-C code from Swift si applicano anche al puro codice C.

Ma in realtà non è troppo complicato da tradurre che il codice a Swift:

func amIBeingDebugged() -> Bool { 

    var info = kinfo_proc() 
    var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()] 
    var size = strideofValue(info) 
    let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0) 
    assert(junk == 0, "sysctl failed") 
    return (info.kp_proc.p_flag & P_TRACED) != 0 
} 

Note:

  • kinfo_proc() crea una struttura completamente inizializzato con tutti campi impostati a zero, quindi, l'impostazione info.kp_proc.p_flag = 0 non è necessaria.
  • Il tipo C int è Int32 è Swift.
  • sizeof(info) dal codice C deve essere strideOfValue(info) in Swift per includere il riempimento della struttura. Con sizeofValue(info) il codice sopra riportato ha sempre restituito false nel simulatore per dispositivi a 64 bit. Questa è stata la parte più difficile da capire.

Aggiornamento per Swift 3 (Xcode 8):

strideofValue e le relative funzioni non esistono più, sono stati sostituiti da MemoryLayout:

func amIBeingDebugged() -> Bool { 

    var info = kinfo_proc() 
    var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()] 
    var size = MemoryLayout<kinfo_proc>.stride 
    let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0) 
    assert(junk == 0, "sysctl failed") 
    return (info.kp_proc.p_flag & P_TRACED) != 0 
} 
+2

Bella ricerca con 'strideOfValue'. Non sapevo della differenza. –

+0

Hey Martin, puoi fornire una versione Obj-C della tua soluzione Xcode 8 per rilevare il debugger? Quello fornito da Apple non sembra funzionare più correttamente. Grazie! :-) –

+0

@HansKnoechel: Il codice nella domanda è puro C e può essere utilizzato da Objective-C senza problemi. Come non "funziona correttamente"? –

Problemi correlati