Detect if Swift app is being run from Xcode

前端 未结 1 1995
故里飘歌
故里飘歌 2020-12-05 10:23

I would like to programmatically determine if the iOS app is being run directly from XCode (either in the simulator or on a tethered device). I\'ve tried the -D DEBUG soluti

相关标签:
1条回答
  • 2020-12-05 10:37

    Clarification: Your C code (and the Swift version below) checks if the program is run under debugger control, not if it's being run from Xcode. One can debug a program outside of Xcode (by calling lldb or gdb directly) and one can run a program from Xcode without debugging it (if the “Debug Executable” checkbox in the scheme setting is off).


    You could simply keep the C function and call it from Swift. The recipes given in How to call Objective-C code from Swift apply to pure C code as well.

    But it is actually not too complicated to translate that code to 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
    }
    

    Remarks:

    • kinfo_proc() creates a fully initialized structure with all fields set to zero, therefore setting info.kp_proc.p_flag = 0 is not necessary.
    • The C int type is Int32 is Swift.
    • sizeof(info) from the C code has to be strideOfValue(info) in Swift to include the structure padding. With sizeofValue(info) the above code always returned false in the Simulator for 64-bit devices. This was the most difficult part to figure out.

    Update for Swift 3 (Xcode 8):

    strideofValue and the related functions do not exist anymore, they have been replaced by 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
    }
    
    0 讨论(0)
提交回复
热议问题