ios - Keychain 类不适用于 iPhone 4s/5 和 iPad

标签 ios iphone ipad swift keychain

我在 iOS 应用程序的设备上将 userId 保存为带有 keychain 的 token 。这适用于 iPhone 5s/6/6 Plus,但不适用于 iPhone 4s/5 和 iPad。在声明我的应用程序时,我使用 func tokenExists() 检查钥匙串(keychain)中是否存在 userId 。但后来我得到一个错误:

fatal error: unexpectedly found nil while unwrapping an Optional value 

如下所示:

error message

这是我的钥匙串(keychain)类,用于保存、加载和删除 token 并检查 token 是否存在:

import UIKit
import Security

// Identifiers
let userAccount:String = "userAccount"

class KeychainService: NSObject {

/*
save token to keychain
*/
func deleteToken() {
    self.delete("userId")
}

/*
save token to keychain
*/
func saveToken(token: NSString) {
    self.save("userId", data: token)
}

/*
load keychain token
*/
func loadToken() -> NSString? {
    var token: AnyObject? = self.load("userId")

    return token as? NSString
}

func tokenExists() -> Bool {

    let token:NSString = loadToken()!

    if (token == "") {
        return false
    }
    else {
        return true
    }
}

private func delete(service: NSString) {
    //var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    // Instantiate a new default keychain query
    var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, userAccount], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount])

    // Delete any existing items
    SecItemDelete(keychainQuery as CFDictionaryRef)

    // Check that it worked ok
    //println("Token deleted")
}

private func save(service: NSString, data: NSString) {
    var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    // Instantiate a new default keychain query
    var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, userAccount, dataFromString], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecValueData])

    // Delete any existing items
    SecItemDelete(keychainQuery as CFDictionaryRef)

    // Add the new keychain item
    var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil)

    // Check that it worked ok
    //println("Saving status code is: \(status)")
}

private func load(service: NSString) -> AnyObject? {
    // Instantiate a new default keychain query
    // Tell the query to return a result
    // Limit our results to one item
    var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, userAccount, kCFBooleanTrue, kSecMatchLimitOne], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecReturnData, kSecMatchLimit])

    // I'm not too sure what's happening here...
    var dataTypeRef :Unmanaged<AnyObject>?

    // Search for the keychain items
    let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)

    //println("Loading status code is: \(status)")

    // I'm not too sure what's happening here...
    let opaque = dataTypeRef?.toOpaque()
    var contentsOfKeychain: NSString?

    if let op = opaque? {
        let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()
        //println("Retrieved the following data from the keychain: \(retrievedData)")
        var str = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
        contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
        //println("The decoded string is \(str)")
    } else {
        //println("Nothing was retrieved from the keychain.")
    }

    return contentsOfKeychain
}
}

我的问题有什么解决方案吗?

最佳答案

随着 XCode 6.1 中包含的更新,我现在必须将状态与 errSecItemNotFound 进行比较:

var dataTypeRef: Unmanaged<AnyObject>?
let status: OSStatus = SecItemCopyMatching(keychainQuery as CFDictionaryRef, &dataTypeRef)
if (status != errSecItemNotFound) {
    if let dataType = dataTypeRef? {
        ...
    }
}

直到这次更新,我还在做 if let op = opaque? {,它正确地捕捉到它是 nil,但后来我开始收到尝试解包 nil 值的错误。

希望这可以帮助其他遇到同样问题的人。

关于ios - Keychain 类不适用于 iPhone 4s/5 和 iPad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26438767/

相关文章:

ios - 解析 UniMag II 加密刷卡数据以获得 Track1 和 Track 2?

objective-c - 将单词列表字典加载到数组中的最快方法?

iphone - 如何在 UiWebView 中仅垂直而非水平捏合/缩放

iphone - 委托(delegate)对象未调用协议(protocol)方法

ios - 当 iPhone 家庭设置时,appstore 上的应用程序是否支持 iPad?

iphone - 在 CCParticleSystemQuad 中弹跳粒子

objective-c - 我是否需要为 NSObject 调用 [super init] 或 [super initWithCoder] 等

ios - GMSMapView 跟踪模式标题

iphone - 循环访问数据库中的坐标数组时出现问题

ipad - 如何在越狱的iPad上编译objc(c++, c)源代码?