2015-08-08 24 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