使用Swift查询iOS钥匙串

我坚持使用Swift转换Keychain查询结果。

我的请求似乎正在工作:

let queryAttributes = NSDictionary(objects: [kSecClassGenericPassword, "MyService", "MyAccount", true], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecReturnData]) dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { var dataTypeRef : Unmanaged<AnyObject>? let status = SecItemCopyMatching(queryAttributes, &dataTypeRef); let retrievedData : NSData = dataTypeRef!.takeRetainedValue() as NSData *** ^^^^can't compile this line^^^^ }) 

我的问题是,代码不会编译:

 Bitcast requires both operands to be pointer or neither %114 = bitcast %objc_object* %113 to %PSs9AnyObject_, !dbg !487 Bitcast requires both operands to be pointer or neither %115 = bitcast %PSs9AnyObject_ %114 to i8*, !dbg !487 LLVM ERROR: Broken function found, compilation aborted! 

我不知道如何将Unmanaged<AnyObject>转换为NSData

有任何想法吗?

使用withUnsafeMutablePointer函数和UnsafeMutablePointer结构来检索数据,如下所示:

 var result: AnyObject? var status = withUnsafeMutablePointer(&result) { SecItemCopyMatching(queryAttributes, UnsafeMutablePointer($0)) } if status == errSecSuccess { if let data = result as NSData? { if let string = NSString(data: data, encoding: NSUTF8StringEncoding) { // ... } } } 

它可以很好地发布(最快的[-O])版本。

看起来像你遇到了一个编译器错误,你应该报告。 您可以采用不同的path来检索值,如下所示:

  var dataTypeRef :Unmanaged<AnyObject>? let status = SecItemCopyMatching(queryAttributes, &dataTypeRef); let opaque = dataTypeRef?.toOpaque() if let op = opaque? { let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue() } 

使用AnyObject作为Unmanaged<T>的types参数T时,会出现错误。 下面的代码片段编译没有问题,它使用更具体的typesCFError

  let url = NSURL(string:"dummy") var errorRef: Unmanaged<CFError>? let succeeded = CTFontManagerRegisterFontsForURL(url, .Process, &errorRef) if errorRef { let error = errorRef!.takeRetainedValue() } 

由于Keychain API根据查询属性返回不同的结果,因此需要使用AnyObject

为了得到这个工作,你需要首先访问每个keychain常量的保留值。 例如:

 let kSecClassValue = kSecClass.takeRetainedValue() as NSString let kSecAttrAccountValue = kSecAttrAccount.takeRetainedValue() as NSString let kSecValueDataValue = kSecValueData.takeRetainedValue() as NSString let kSecClassGenericPasswordValue = kSecClassGenericPassword.takeRetainedValue() as NSString let kSecAttrServiceValue = kSecAttrService.takeRetainedValue() as NSString let kSecMatchLimitValue = kSecMatchLimit.takeRetainedValue() as NSString let kSecReturnDataValue = kSecReturnData.takeRetainedValue() as NSString let kSecMatchLimitOneValue = kSecMatchLimitOne.takeRetainedValue() as NSString 

然后你需要引用在Keychain字典对象中创build的常量,如下所示。

 var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, userAccount, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue]) 

我写了一篇关于它的博客文章: http : //rshelby.com/2014/08/using-swift-to-save-and-query-ios-keychain-in-xcode-beta-4/

希望这可以帮助!

rshelby