Reputation: 1019
The code is copied from this blog post: http://matthewpalmer.net/blog/2014/06/21/example-ios-keychain-swift-save-query/
I used to have this code:
// Search for the keychain items
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
// The following line crashes with an EXEC_BAD_ACCESS if dataTypeRef is nil
var opaque = dataTypeRef!.toOpaque()
When I run the above using a new account value in the keychain query the dataTypeRef
will be nil
which leads to an EXEC_BAD_ACCESS
.
I tried to circumvent this by checking if dataTypeRef
is nil
like this:
var opaque = COpaquePointer.null()
if (dataTypeRef != nil) {
opaque = dataTypeRef!.toOpaque() // This line should not be executed.
}
While the debugger shows that dataTypeRef
is nil
it will still enter the if clause and crash.
Could anyone explain what is going on here? I do have experience in Objective-C but I can't figure out what's going on here.
Upvotes: 3
Views: 1377
Reputation: 539685
As far as I know, the toOpaque/fromOpaque
dances are no longer necessary, and you
can simply use optional binding. This can be combined with the cast to NSData
using optional chaining:
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
if let retrievedData = dataTypeRef?.takeRetainedValue() as? NSData {
contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
}
Note also that takeRetainedValue()
is the correct choice here because you "own"
the item returned by SecItemCopyMatching
(it has "Copy" in its name).
But actually you should check the return value first:
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
if status == errSecSuccess {
if let retrievedData = dataTypeRef?.takeRetainedValue() as? NSData {
contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
}
}
Upvotes: 6