唉,我整个下午都在做这个.这是我的噩梦:
我正在尝试使用苹果制造的KeychainItemWrapper。但是我把它的目标-C代码翻译成Swift:
import Foundation
import Security
class MyKeychainItemWrapper: NSObject {
var keychainItemData: NSMutableDictionary?
var genericPasswordQuery: NSMutableDictionary = NSMutableDictionary()
init(identifier: String, accessGroup: String?) {
super.init()
// Begin Keychain search setup. The genericPasswordQuery leverages the special user
// defined attribute kSecAttrGeneric to distinguish itself between other generic Keychain
// items which may be included by the same application.
genericPasswordQuery.setObject(kSecClassGenericPassword, forKey: kSecClass)
genericPasswordQuery.setObject(identifier, forKey: kSecAttrGeneric)
// The keychain access group attribute determines if this item can be shared
// amongst multiple apps whose code signing entitlements contain the same keychain access group.
println(accessGroup)
if (!(accessGroup == nil)) {
genericPasswordQuery.setObject(accessGroup!, forKey: kSecAttrAccessGroup)
}
// Use the proper search constants, return only the attributes of the first match.
genericPasswordQuery.setObject(kSecMatchLimitOne, forKey: kSecMatchLimit)
genericPasswordQuery.setObject(kCFBooleanTrue, forKey: kSecReturnAttributes)
var tempQuery: NSDictionary = NSDictionary(dictionary: genericPasswordQuery)
var outDictionary: Unmanaged<AnyObject>? = nil
var status: OSStatus = SecItemCopyMatching(tempQuery as CFDictionaryRef, &outDictionary)
println(status == noErr)
if (status == noErr) {
// Stick these default values into keychain item if nothing found.
resetKeychainItem()
// Add the generic attribute and the keychain access group.
keychainItemData!.setObject(identifier, forKey: kSecAttrGeneric)
if (!(accessGroup == nil)) {
keychainItemData!.setObject(accessGroup!, forKey: kSecAttrAccessGroup)
}
} else {
// load the saved data from Keychain.
keychainItemData = secItemFormatToDictionary(outDictionary?.takeRetainedValue() as NSDictionary)
}
}然后在我的应用程序的AppDelegate.swift中,我试图通过以下方式来使用它:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var passwordItem: MyKeychainItemWrapper = MyKeychainItemWrapper(identifier: "Password", accessGroup: nil)
...所以,初始化程序被调用,但是不知怎么的,我总是,总是
线程1: EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT,subcode=0xe7ffdefe)

我试着注释出问题行,然后在另一个if()中得到这个错误:

我甚至试过:
var mmm: Bool = (accessGroup == nil)
if (!mmm) {
genericPasswordQuery.setObject(accessGroup!, forKey: kSecAttrAccessGroup)
}但同一地点的错误相同,即如果(.)
我现在很困惑。我是不是漏掉了什么?
环境: Xcode6-beta6,iOS 8 beta 5上的非越狱iPhone 5。
发布于 2014-09-21 10:58:18
Swift 3
import UIKit
import Security
let kSecClassGenericPasswordValue = String(format: kSecClassGenericPassword as String)
let kSecClassValue = String(format: kSecClass as String)
let kSecAttrServiceValue = String(format: kSecAttrService as String)
let kSecValueDataValue = String(format: kSecValueData as String)
let kSecMatchLimitValue = String(format: kSecMatchLimit as String)
let kSecReturnDataValue = String(format: kSecReturnData as String)
let kSecMatchLimitOneValue = String(format: kSecMatchLimitOne as String)
let kSecAttrAccountValue = String(format: kSecAttrAccount as String)
struct KeychainAccess {
func setPasscode(identifier: String, passcode: String) {
if let dataFromString = passcode.data(using: String.Encoding.utf8) {
let keychainQuery = [
kSecClassValue: kSecClassGenericPasswordValue,
kSecAttrServiceValue: identifier,
kSecValueDataValue: dataFromString
] as CFDictionary
SecItemDelete(keychainQuery)
print(SecItemAdd(keychainQuery, nil))
}
}
func getPasscode(identifier: String) -> String? {
let keychainQuery = [
kSecClassValue: kSecClassGenericPasswordValue,
kSecAttrServiceValue: identifier,
kSecReturnDataValue: kCFBooleanTrue,
kSecMatchLimitValue: kSecMatchLimitOneValue
] as CFDictionary
var dataTypeRef: AnyObject?
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
var passcode: String?
if (status == errSecSuccess) {
if let retrievedData = dataTypeRef as? Data,
let result = String(data: retrievedData, encoding: String.Encoding.utf8) {
passcode = result as String
}
}
else {
print("Nothing was retrieved from the keychain. Status code \(status)")
}
return passcode
}
}Swift 2
import UIKit;
import Security;
let kSecClassGenericPasswordValue = NSString(format: kSecClassGenericPassword);
let kSecClassValue = NSString(format: kSecClass);
let kSecAttrServiceValue = NSString(format: kSecAttrService);
let kSecValueDataValue = NSString(format: kSecValueData);
let kSecMatchLimitValue = NSString(format: kSecMatchLimit);
let kSecReturnDataValue = NSString(format: kSecReturnData);
let kSecMatchLimitOneValue = NSString(format: kSecMatchLimitOne);
let kSecAttrAccountValue = NSString(format: kSecAttrAccount);
class KeychainAccess: NSObject {
func setPasscode(identifier: String, passcode: String) {
let dataFromString: NSData = passcode.dataUsingEncoding(NSUTF8StringEncoding)!;
let keychainQuery = NSDictionary(
objects: [kSecClassGenericPasswordValue, identifier, dataFromString],
forKeys: [kSecClassValue, kSecAttrServiceValue, kSecValueDataValue]);
SecItemDelete(keychainQuery as CFDictionaryRef);
let status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil);
}
func getPasscode(identifier: String) -> NSString? {
let keychainQuery = NSDictionary(
objects: [kSecClassGenericPasswordValue, identifier, kCFBooleanTrue, kSecMatchLimitOneValue],
forKeys: [kSecClassValue, kSecAttrServiceValue, kSecReturnDataValue, kSecMatchLimitValue]);
var dataTypeRef: AnyObject?
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
var passcode: NSString?;
if (status == errSecSuccess) {
let retrievedData: NSData? = dataTypeRef as? NSData
if let result = NSString(data: retrievedData!, encoding: NSUTF8StringEncoding) {
passcode = result as String
}
}
else {
print("Nothing was retrieved from the keychain. Status code \(status)")
}
return passcode;
}
}然后从任何地方打电话:
func setPasscode(passcode: String) {
let keychainAccess = KeychainAccess();
keychainAccess.setPasscode("YourAppIdentifier", passcode:passcode);
}
func getPasscode() -> NSString {
let keychainAccess = KeychainAccess();
return keychainAccess.getPasscode("YourAppIdentifier")!;
}
func deletePasscode() {
let keychainAccess = KeychainAccess();
keychainAccess.setPasscode("YourAppIdentifier", passcode:"");
}发布于 2015-11-18 07:36:17
现有的几个快速版本,最好的一个是:
jrendel/SwiftKeychainWrapper·GitHub
如何使用:
发布于 2014-08-26 19:01:54
Swift 2的更新。
下面是一个可能有所帮助的示例实现。
import Security
class ZLKeychainService: NSObject {
var service = "Service"
var keychainQuery :[NSString: AnyObject]! = nil
func save(name name: NSString, value: NSString) -> OSStatus? {
let statusAdd :OSStatus?
guard let dataFromString: NSData = value.dataUsingEncoding(NSUTF8StringEncoding) else {
return nil
}
keychainQuery = [
kSecClass : kSecClassGenericPassword,
kSecAttrService : service,
kSecAttrAccount : name,
kSecValueData : dataFromString]
if keychainQuery == nil {
return nil
}
SecItemDelete(keychainQuery as CFDictionaryRef)
statusAdd = SecItemAdd(keychainQuery! as CFDictionaryRef, nil)
return statusAdd;
}
func load(name name: NSString) -> String? {
var contentsOfKeychain :String?
keychainQuery = [
kSecClass : kSecClassGenericPassword,
kSecAttrService : service,
kSecAttrAccount : name,
kSecReturnData : kCFBooleanTrue,
kSecMatchLimit : kSecMatchLimitOne]
if keychainQuery == nil {
return nil
}
var dataTypeRef: AnyObject?
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
if (status == errSecSuccess) {
let retrievedData: NSData? = dataTypeRef as? NSData
if let result = NSString(data: retrievedData!, encoding: NSUTF8StringEncoding) {
contentsOfKeychain = result as String
}
}
else {
print("Nothing was retrieved from the keychain. Status code \(status)")
}
return contentsOfKeychain
}
}
//Test:
let userName = "TestUser"
let userValue: NSString = "TestValue"
print("userName: '\(userName)'")
print("userValue: '\(userValue)'")
let kcs = ZLKeychainService()
kcs.save(name:userName, value: userValue)
print("Keychain Query \(kcs.keychainQuery)")
if let recoveredToken = kcs.load(name:userName) {
print("Recovered Value: '\(recoveredToken)'")
}输出:
userName:'TestUser‘ userValue:'TestValue‘ 密钥链查询会计: TestUser,v_Data:<54657374 56616c75 65>,svce: 65>,class: genp 回收价值:“TestValue”
https://stackoverflow.com/questions/25513106
复制相似问题