2015-10-16 80 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中使用,沒有任何問題。它如何不「正常工作」? –

相關問題