Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if Swift app is being run from Xcode

Tags:

xcode

ios

swift

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 solution described here, but when I then disconnect from Xcode and re-run the app, it still thinks it's in debug mode. I think what I'm looking for is a Swift version of this function

#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 ); } 
like image 946
Mike Hedman Avatar asked Oct 16 '15 18:10

Mike Hedman


People also ask

Does swift run on Xcode?

Moreover, binary builds of open-source Swift integrate with the Xcode developer tools, including complete support for the Xcode build system, code completion in the editor, and integrated debugging, allowing anyone to experiment with the latest Swift developments in a familiar Cocoa and Cocoa Touch development ...

How do you check if app is in background iOS Swift?

To detect if an iOS application is in background or foreground we can simply use the UIApplication just like we can use it to detect many other things like battery state, status etc. The shared. application state is an enum of type State, which consists of the following as per apple documentation.

What is compilation conditions in Swift?

From the Xcode 8 release notes: Active Compilation Conditions is a new build setting for passing conditional compilation flags to the Swift compiler. Each element of the value of this setting passes to swiftc prefixed with -D , in the same way that elements of Preprocessor Macros pass to clang with the same prefix. (


1 Answers

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 do I 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 {     // Buffer for "sysctl(...)" call's result.     var info = kinfo_proc()     // Counts buffer's size in bytes (like C/C++'s `sizeof`).     var size = MemoryLayout.stride(ofValue: info)     // Tells we want info about own process.     var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]     // Call the API (and assert success).     let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)     assert(junk == 0, "sysctl failed")     // Finally, checks if debugger's flag is present yet.     return (info.kp_proc.p_flag & P_TRACED) != 0 } 

Update for Swift 5 (Xcode 10.7): strideofValue and the related functions do not exist anymore, they have been replaced by MemoryLayout.stride(ofValue:).

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.

Swift 2 logic:

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 } 
like image 127
Martin R Avatar answered Oct 08 '22 00:10

Martin R