swift 2.0 keychain type errors for SecItemCopyMatching
Asked Answered
P

2

7

We had this snippet of code with the previous version of Swift

    var retrievedData: NSData?
    var extractedData: Unmanaged<AnyObject>? = nil
    let status = SecItemCopyMatching(keyChainQuery, &extractedData)

    if (status == errSecSuccess) {
        if let validExtractedData = extractedData {
            let opaque = validExtractedData.toOpaque()
            retrievedData = Unmanaged<NSData>.fromOpaque(opaque).takeUnretainedValue()
        }
    }

However this now gives us the following error:

Cannot convert value of type 'inout Unmanaged?' (aka 'inout Optional>') to expected argument type 'UnsafeMutablePointer' (aka 'UnsafeMutablePointer>')

I'm a bit lost on how to fix it. I presume I have to allocate some memory, make an UnsafeMutablePointer to it and then supply this to SecItemCopyMatching?

I tried this:

    let sizeOfKey = 32
    var store = NSMutableData(capacity: sizeOfKey)!
    let status = SecItemCopyMatching(keyChainQuery, store.bytes)

But this gave me an:

Cannot convert value of type 'UnsafePointer' (aka 'UnsafePointer<()>') to expected argument type 'UnsafeMutablePointer' (aka 'UnsafeMutablePointer>') error

Anyone an idea?

Pavel answered 3/9, 2015 at 14:10 Comment(0)
Z
26

It seems, we don't need Unmanaged<> work anymore.

Try:

var retrievedData: NSData?
var extractedData: AnyObject?
let status = SecItemCopyMatching(keyChainQuery, &extractedData)

if (status == errSecSuccess) {
    retrievedData = extractedData as? NSData
}
Zeal answered 3/9, 2015 at 14:25 Comment(2)
Seems to compile fine! Can you explain how you came to this solution? The compiler wants a: UnsafeMutablePointer<Optional<AnyObject>> yet apparently AnyObject? is fine as well?Pavel
see this document. We can pass in-out(&) expression to UnsafeMutablePointer<T> parameter. When it accept UnsafeMutablePointer<Optional<AnyObject>>, we can pass &result if result is a Optional<AnyObject> a.k.a. AnyObject? variable.Zeal
P
0

After puzzling some more I've come up with this solution:

    var retrievedData: NSData?
    let sizeOfKey = 32
    let store = UnsafeMutablePointer<AnyObject?>.alloc(sizeof(AnyObject?) * sizeOfKey)
    let status = SecItemCopyMatching(keyChainQuery, store)

    if (status == errSecSuccess) {
        retrievedData = NSData(bytesNoCopy: store, length: sizeOfKey, freeWhenDone: true)
    }

Which compiles. I'm not sure if it actually works yet. If it does I'll update this post. In the meantime if people in the know can comment on it that would be great!

Pavel answered 3/9, 2015 at 14:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.