2015-10-16 78 views
10

我想以编程方式确定iOS应用程序是否直接从XCode运行(无论是在模拟器中还是在连接的设备上)。 我试过-D DEBUG解决方案描述here,但是当我从Xcode断开连接并重新运行应用程序时,它仍认为它处于调试模式。 我想我正在寻找的是this function检测是否从Xcode运行Swift应用程序

#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

可以调用C函数来自Swift,所以你不需要翻译它。 –

+0

马丁,这是我要说的答案,把它作为答案,我会加快它。 – Knight0fDragon

+0

下面是将代码转换为Swift的快速,未经测试的尝试(仅供趣):https://gist.github.com/getaaron/8d48489274a873835636。我现在没有时间进一步玩,但也许它会让你开始。 –

回答

33

迅捷的版本你可以简单地保持C函数和斯威夫特调用它。 How to call Objective-C code from Swift中给出的配方也适用于纯C代码。

但它其实并不是太复杂,翻译该代码斯威夫特:

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 
} 

注:

  • kinfo_proc()创建一个具有零所有 字段完全初始化结构,因此设置info.kp_proc.p_flag = 0是没有必要的。
  • C int类型是Int32是Swift。
  • ​​来自C代码必须是strideOfValue(info) 在Swift中包含结构填充。使用sizeofValue(info) 以上代码在模拟器中对于64位设备总是返回false。这是弄清楚最困难的部分。

更新斯威夫特3(Xcode中8):

strideofValue和相关功能不存在了, 他们已换成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

用'strideOfValue'很好的发现。我不知道差异。 –

+0

嘿马丁,你能提供一个Obj-C版本的Xcode 8解决方案来检测调试器吗?从苹果提供的一个似乎不能正常工作了。谢谢! :-) –

+0

@HansKnoechel:问题中的代码是纯C,可以从Objective-C中使用,没有任何问题。它如何不“正常工作”? –

相关问题