Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Keychain services et Swift 3

heliohelio FrancePosts: 32New Users @
Hi, I have an issue with one of my application since Xcode 8 and Swift 3.
i use Keychain service and this code recover from a blog to store username and password :
import UIKit
import Security

// Identifiers
let serviceIdentifier = "MyService"
let userAccount = "authenticatedUser"
let accessGroup = "MyService"

// Arguments for the keychain queries
let kSecClassValue = NSString(format: kSecClass) as NSString
let kSecAttrAccountValue = NSString(format: kSecAttrAccount) as NSString
let kSecValueDataValue = NSString(format: kSecValueData) as NSString
let kSecClassGenericPasswordValue = NSString(format: kSecClassGenericPassword) as NSString
let kSecAttrServiceValue = NSString(format: kSecAttrService) as NSString
let kSecMatchLimitValue = NSString(format: kSecMatchLimit) as NSString
let kSecReturnDataValue = NSString(format: kSecReturnData) as NSString
let kSecMatchLimitOneValue = NSString(format: kSecMatchLimitOne) as NSString

class KeychainService: NSObject {
    
    /**
    * Exposed methods to perform queries.
    * Note: feel free to play around with the arguments
    * for these if you want to be able to customise the
    * service identifier, user accounts, access groups, etc.
    */
    class func saveToken(_ token: NSString) {
        self.save(serviceIdentifier as NSString, data: token)
    }
    
    class func loadToken() -> NSString? {
        let token = self.load(service: serviceIdentifier as NSString)
        return token as! NSString?
    }
    
    class func deleteToken(_ token: String) {
        self.delete(token)
    }
    
    class func clearToken() {
        self.clear()
    }
    
    fileprivate class func delete(_ key: String) -> Bool
    {
        let query = [
            (kSecClass as String)       : kSecClassGenericPassword,
            (kSecAttrAccount as String) : key
            ] as [String : Any]

        return SecItemDelete(query as CFDictionary) == noErr
    }
    
    fileprivate class func clear() -> Bool
    {
        let query = [
            (kSecClass as String): kSecClassGenericPassword
        ]
        
        return SecItemDelete(query as CFDictionary) == noErr
    }
    
    fileprivate class func save(_ service: NSString, data: NSString) {
        let dataFromString: Data = data.data(using: String.Encoding.utf8.rawValue, allowLossyConversion: false)!
        
        // Instantiate a new default keychain query
        let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, userAccount, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue])
        
        // Delete any existing items
        SecItemDelete(keychainQuery as CFDictionary)
        
        // Add the new keychain item
        // var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil)
        SecItemAdd(keychainQuery as CFDictionary, nil)
    }
    
    fileprivate class func load(service: NSString) -> AnyObject? {
    
        // Instantiate a new default keychain query
        // Tell the query to return a result
        // Limit our results to one item
        let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, userAccount, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])
        
        var dataTypeRef :Unmanaged<AnyObject>?
        
        // Search for the keychain items
        // let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
        let status: OSStatus = withUnsafeMutablePointer(to: &dataTypeRef) { SecItemCopyMatching(keychainQuery as CFDictionary, UnsafeMutablePointer($0)) }
        
        let opaque = dataTypeRef?.toOpaque()
        
        var contentsOfKeychain: NSString?
        
        if let op = opaque {
            let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()
            
            // Convert the data retrieved from the keychain into a string
            contentsOfKeychain = NSString(data: retrievedData as Data, encoding: String.Encoding.utf8.rawValue)
            
        } else {
            print("Nothing was retrieved from the keychain. Status code \(status)")
        }
        
        return contentsOfKeychain
        
    }
}

In this instruction :
let status: OSStatus = withUnsafeMutablePointer(to: &dataTypeRef) { SecItemCopyMatching(keychainQuery as CFDictionary, UnsafeMutablePointer($0)) }

I have an error :
'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.

Is anyone have the solution ? thank you.
Tagged:

Replies

Sign In or Register to comment.