钥匙串类不适用于 iPhone 4s/5 和 iPad
Posted
技术标签:
【中文标题】钥匙串类不适用于 iPhone 4s/5 和 iPad【英文标题】:Keychain class doesn't work for iPhone 4s/5 and iPad 【发布时间】:2014-10-18 10:29:42 【问题描述】:我将userId
与keychain
一起保存在我的ios 应用程序的设备上。这适用于 iPhone 5s/6/6 Plus,但不适用于 iPhone 4s/5 和 iPad。在说明我的应用程序时,我检查userId
是否存在于钥匙串中,func tokenExists()
是否存在。但后来我得到一个错误:
fatal error: unexpectedly found nil while unwrapping an Optional value
如下所示:
这是我的钥匙串类,用于保存、加载和删除令牌并检查令牌是否存在:
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
我的问题有什么解决方案吗?
【问题讨论】:
【参考方案1】:从 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
,但后来我开始因为尝试解开零值而出现错误。
希望这可以帮助其他在同一问题上偶然发现此答案的人。
【讨论】:
【参考方案2】:您的问题是您的 tokenExists()
方法没有检查令牌是否存在。相反,它假设 tokenExists(如 let token:NSString = loadToken()!
末尾的 !
所述),然后仅检查它是否为空字符串。
试试这个tokenExists()
方法:
func tokenExists() -> Bool
var result = false
if let token = loadToken()
// the token exists, but is it blank?
if token != ""
// no, the token is not blank
result = true
return result
【讨论】:
如果这是解决方案,请检查绿色标记。很高兴它对你有用。以上是关于钥匙串类不适用于 iPhone 4s/5 和 iPad的主要内容,如果未能解决你的问题,请参考以下文章
UIPageViewController - 以编程方式更改页面在 iPhone 4s/5/5s 上不起作用
AssetCatalog LaunchImage 仅横向 - iPhone 4S/5/5S 未显示
推送通知在 iPhone 3GS 中不起作用。它适用于最新的 IOS 设备,如 iPhone 4、4s、5
如何处理 iPhone 4s、5 和 6 的屏幕尺寸,并使所有内容在所有设备上看起来都一样