2015-08-08 52 views
1

我正在寫一個OS X應用程序,應該保持一個自定義的鑰匙串,我試圖使用安全框架的API來創建鑰匙串,但是,我似乎無法得到它在Swift下編譯。使用從Swift SecKeychainCreate

這裏是我有,假設path包含對可能存在的鑰匙扣的路徑:

let pathName = (path as NSString).UTF8String 
var keychain: Unmanaged<SecKeychain>? 

var status = withUnsafeMutablePointer(&keychain) { pointer in 
    SecKeychainOpen(pathName, pointer) 
} 

if status != errSecSuccess { 
    status = withUnsafeMutablePointer(&keychain) { pointer in 
     SecKeychainCreate(pathName, UInt32(0), nil, false, nil, pointer) 
    } 
} 

編譯器抱怨在SecKeychainCreate呼叫的類型,但是,我不明白我在做什麼錯誤。

Cannot invoke 'withUnsafeMutablePointer' with an argument list of type '(inout Unmanaged<SecKeychain>?, (_) -> _)' 

如果我稍微修改了第二封,我得到這個編譯器錯誤:

Cannot invoke 'SecKeychainCreate' with an argument list of type '(UnsafePointer<Int8>, UInt32, nil, Bool, nil, (UnsafeMutablePointer<Unmanaged<SecKeychain>?>))' 

我感謝所有的建議。

回答

4

SecKeychainCreate()promptUser參數具有類型 Boolean,這是一個「的Mac OS歷史性型」和一個別名UInt8, 所以它在夫特1.2從夫特Bool不同。 (比較Type 'Boolean' does not conform to protocol 'BooleanType'了類似的問題。) 這意味着你必須 通Boolean(0)而不是false

SecKeychainCreate(pathName, UInt32(0), nil, Boolean(0), nil, pointer) 

補充說明:

  • withUnsafeMutablePointer()是不需要的,你可以通過&keychain 到鑰匙串功能。
  • (path as NSString).UTF8String不需要,您可以將Swift 字符串傳遞給預計參數爲const char *的C函數, 比較String value to UnsafePointer<UInt8> function parameter behavior
  • 傳遞nil作爲密碼SecKeychainCreate()只允許 如果promptUserTRUE,否則它會導致 「參數錯誤(-50)」。
  • SecKeychainOpen()成功,即使鑰匙串文件不存在 存在。根據文件,你必須檢查 SecKeychainGetStatus()。或者,您可以嘗試首先創建 鑰匙串文件,例如在Open Local Items Keychain?中。

合:

let path = "/path/to/my.keychain" 
var keychain: Unmanaged<SecKeychain>? 

var status = SecKeychainCreate(path, 0, "", Boolean(0), nil, &keychain) 
if status == OSStatus(errSecDuplicateKeychain) { 
    status = SecKeychainOpen(path, &keychain) 
} 

作爲夫特2/Xcode的7測試5,在Mac類型Boolean映射 到快速作爲Bool,並且鍵鏈函數並不再返回 非託管的對象:

let path = "/path/to/my.keychain" 
var keychain: SecKeychain? 

var status = SecKeychainCreate(path, 0, "", false, nil, &keychain) 
if status == OSStatus(errSecDuplicateKeychain) { 
    status = SecKeychainOpen(path, &keychain) 
} 
+0

感謝您的深入分析,因爲我懷疑這是一件容易遺漏的事情。我希望編譯器能更詳細地瞭解錯誤... –

+0

@亨利諾馬克:不客氣。 - 是的,錯誤的參數類型可能難以檢測,甚至更難以檢測到。 Swift編譯器還有改進的空間!有時可以使用方法的自動完成(或跳轉到定義)並檢查每個參數。 –

+0

你提到文檔描述了你必須使用'SecKeychainGetStatus()',因爲'SecKeychainOpen()'總是成功的。你在哪裏找到這個文檔?我發現這是真實的,但無法找到任何官方提及的這種行爲。 – drootang