添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm attempting to call SecItemCopyMatching in my keychain utility class in order to get data out of the keychain, yet I'm running into a problem with getting the result argument, UnsafeMutablePointer<CFTypeRef?> .

The original statement (in Swift 2, before migrating to Swift 3) was

// query is a dictionary of [String : AnyObject]
var result: Data?
let status = withUnsafeMutablePointer(to: &result) {
    SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))

But in Swift 3, you are now required to call .withMemoryRebound in order to view memory. Based on what Xcode tells you to do, I tried this

var result: Data?
let status = withUnsafeMutablePointer(to: &result){
    $0.withMemoryRebound(to: Data.self, capacity: 1){
        SecItemCopyMatching(query as CFDictionary, UnsafePointer($0))

Yet doing this, I get an error

Cannot convert value of type 'UnsafePointer<_>' to expected argument type 'UnsafeMutablePointer<CFTypeRef?>?'

So, I tried using CFTypeRef instead of Data

var result: CFTypeRef?
let status = withUnsafeMutablePointer(to: &result){
    $0.withMemoryRebound(to: CFTypeRef.self, capacity: 1){
        SecItemCopyMatching(query as CFDictionary, UnsafePointer($0))

Replacing UnsafePointer($0) with simply $0 results in the same error message.

How can I get an UnsafeMutablePointer<CFTypeRef?> for getting data from keychain?

Please would you post how you're creating your query. I was previously doing just this and casting from a swift Dictionary to CFDictionary, but that no longer works for me in Swift 3. If I could see just a little more of the code I can apply this solution. – Tim Spears Sep 19, 2016 at 22:37 @TimSpears the problem with your code would probably be that the dictionary has to be a [String : AnyObject] - the auto-migrator (for me) changed this to [String : Any]. I updated my answer to the question to include the code I use – Jojodmo Sep 19, 2016 at 22:53

In your case, you do not need to use withMemoryRebound or withUnsafeMutablePointer(to:).

Instead, you can just use

var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
if status == noErr, let data = result as? Data {
    //use data...

Generally, when you need to pass an UnsafeMutablePointer<T> to a function, declare a variable of type T and pass it as an inout argument &variable. In your case, T is CFTypeRef?, and in Swift 3, CFTypeRef is just a typealias of AnyObject.

Even in Swift 2.2, you did not need to use withUnsafeMutablePointer

var result: AnyObject?  
let status = SecItemCopyMatching(query, &result)  
                Your solution is working for me. My result variable (defined using var, not let) is a SecKey, which is easily cast to CFTypeRef. Using just the ampersand results in the error Cannot pass immutable value of type 'CFTypeRef?' as inout argument
– Matthew Barker
                Jun 16, 2017 at 15:27

The error message is somewhat misleading - the actual problem is that result has to be an AnyObject? - withMemoryRebound doesn't need to be used.

var result: AnyObject?
let status = withUnsafeMutablePointer(to: &result){
    SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))

Works as expected and gets the correct result from keychain - it just needs to be casted to Data. In fact, withUnsafeMutablePointer doesn't even have to be used.

So, my new code is

var query: [String : AnyObject] = [:]
//set up the query
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
var data: Data?
if status == noErr{
    data = result as? Data
                I tried your solution and the one by @OOPer, and neither seem to work for me, see my comment there. Any idea what's up?
– Matthew Barker
                Jun 16, 2017 at 15:30
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.