如何将对象保存到 UserDefaults 或钥匙串 - Swift 3
How to save object into UserDefaults or keychain - Swift 3
我正在构建一个 Shopify 应用程序,但首先这不是一个 Shopify SDK 问题,它是关于将客户令牌保存到 userDefaults 或钥匙串中。我试过了,但我试过的大多数钥匙串库只适用于字符串,我需要将令牌作为一个整体保存,如下所示:
BUYCustomerToken(customerID: NSNumber!, accessToken: String!, expiry: Date!)
应用程序访问令牌的共享客户端如下所示:
BUYClient.sharedClient.customerToken
在注册期间,使用令牌成功创建了用户。一旦我退出并返回应用程序
BUYClient.sharedClient.customerToken = ""
所以我的问题是,如何将此对象保存到默认值或钥匙串中,以便稍后在进入应用程序时调用。我不能只保存令牌的一部分,比如只是一个字符串的 accessToken,我需要整个东西。提前致谢!
你可以在UserDefaults中保存多个String类型,你必须将你的令牌存储在多个键中。
https://developer.apple.com/reference/foundation/userdefaults
The NSUserDefaults class provides convenience methods for accessing
common types such as floats, doubles, integers, Booleans, and URLs. A
default object must be a property list—that is, an instance of (or for
collections, a combination of instances of): NSData, NSString,
NSNumber, NSDate, NSArray, or NSDictionary.
如果要存储到期日期
let expiry = UserDefaults.standard.object(forKey: "expiry") as? Date
UserDefaults.standard.set(Date(), forKey: "expiry")
客户ID
let customerID = UserDefaults.standard.object(forKey: "customerID") as? NSNumber
UserDefaults.standard.set(1234, forKey: "customerID")
令牌也一样。
NSUserDefaults.standardUserDefaults().setObject("YourAccessToken", forKey: "accessToken")
let accessToken = NSUserDefaults.standardUserDefaults().stringForKey("accessToken")
用这种方法,你只需要一个一个地获取它们,但是你已经把它们都存储起来了。希望对你有帮助!
您肯定可以将整个对象存储在您的UserDefaults
或钥匙串中,没问题。诀窍是使其符合 NSCoding
协议,然后使用 NSKeyedArchiver
和 NSKeyedUnarchiver
将其与可以存储的 Data
对象相互转换。别担心,这听起来比实际更复杂。
符合NSCoding
推测您的 BUYCustomerToken
class 已经是 NSObject
的后代,所以您已经成功了一半。你只需要添加几个方法来让你的自定义 class 被编码(变成 Data
)并从 NSCoder
自动解码。具体来说,它们是:encode(with coder: NSCoder)
和 init(coder aDecoder:NSCoder)
。然后使用编码器的各种 encode() 和 decode() 函数来完成这些工作。 encode() 和 decode() 适用于任何支持 NSCoding
的对象,其中包括 NSNumber
、String
和 Date
,因此您在这里的工作非常简单。完成的可编码 class 将如下所示:
class BUYCustomerToken : NSObject, NSCoding {
var customerID: NSNumber!
var accessToken: String!
var expiry: Date!
override init() {
}
convenience init(customerID: NSNumber, accessToken: String, expiry: Date) {
self.init()
self.customerID = customerID
self.accessToken = accessToken
self.expiry = expiry
}
required init(coder aDecoder: NSCoder) {
customerID = aDecoder.decodeObject(forKey: "customerID") as! NSNumber
accessToken = aDecoder.decodeObject(forKey: "accessToken") as! String
expiry = aDecoder.decodeObject(forKey: "expiry") as! Date
}
func encode(with aCoder: NSCoder) {
aCoder.encode(customerID, forKey: "customerID")
aCoder.encode(accessToken, forKey: "accessToken")
aCoder.encode(expiry, forKey: "expiry")
}
override var description: String {
return "ID: \(customerID!), Token: \"\(accessToken!)\", Expires: \(expiry!)"
}
}
当然,您可以添加自己的自定义方法。 description
不是必须的,但方便测试。
从 UserDefaults 存储和检索
现在您的 class 支持 NSCoding,您可以将其存档并存储,然后检索它。
要存储它,首先要使用 NSKeyedArchiver.archivedData(withRootObject)
归档(将其转换为 Data
对象)。这是可行的,因为您的 class 符合 NSCoding
标准。获得 Data
对象后,您可以使用 set(value, forKey)
.
将其存储在 UserDefaults
中
当你想取回它时,你可以用另一种方式进行:首先使用 data(forKey)
从 UserDefaults
中获取一个 Data
对象,然后使用 NSKeyedUnarchiver.unarchiveObject(with)
,最后将其转换为您的自定义 class。
这里有一段代码尝试从 UserDefaults
加载 BUYCustomerToken
。如果成功,则打印描述;如果失败,它会创建一个新令牌并存储它。将此代码放入初始 UIViewController
的 viewDidLoad()
以查看其实际效果:
if let customerTokenData = UserDefaults.standard.data(forKey: "myToken") {
let customerToken = NSKeyedUnarchiver.unarchiveObject(with: customerTokenData) as! BUYCustomerToken
print(customerToken)
} else {
print("No token stored. Launch again to see token.")
let customerToken = BUYCustomerToken(customerID: 999, accessToken: "some token", expiry: Date())
let tokenData = NSKeyedArchiver.archivedData(withRootObject: customerToken)
UserDefaults.standard.set(tokenData, forKey: "myToken")
}
第一次 运行 没有存储令牌,所以输出是:
No token stored. Launch again to see token.
第二次,它会找到存储的令牌并输出其描述:
ID: 999, Token: "some token", Expires: 2017-05-31 21:27:25 +0000
我正在构建一个 Shopify 应用程序,但首先这不是一个 Shopify SDK 问题,它是关于将客户令牌保存到 userDefaults 或钥匙串中。我试过了,但我试过的大多数钥匙串库只适用于字符串,我需要将令牌作为一个整体保存,如下所示:
BUYCustomerToken(customerID: NSNumber!, accessToken: String!, expiry: Date!)
应用程序访问令牌的共享客户端如下所示:
BUYClient.sharedClient.customerToken
在注册期间,使用令牌成功创建了用户。一旦我退出并返回应用程序
BUYClient.sharedClient.customerToken = ""
所以我的问题是,如何将此对象保存到默认值或钥匙串中,以便稍后在进入应用程序时调用。我不能只保存令牌的一部分,比如只是一个字符串的 accessToken,我需要整个东西。提前致谢!
你可以在UserDefaults中保存多个String类型,你必须将你的令牌存储在多个键中。
https://developer.apple.com/reference/foundation/userdefaults
The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Booleans, and URLs. A default object must be a property list—that is, an instance of (or for collections, a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.
如果要存储到期日期
let expiry = UserDefaults.standard.object(forKey: "expiry") as? Date
UserDefaults.standard.set(Date(), forKey: "expiry")
客户ID
let customerID = UserDefaults.standard.object(forKey: "customerID") as? NSNumber
UserDefaults.standard.set(1234, forKey: "customerID")
令牌也一样。
NSUserDefaults.standardUserDefaults().setObject("YourAccessToken", forKey: "accessToken")
let accessToken = NSUserDefaults.standardUserDefaults().stringForKey("accessToken")
用这种方法,你只需要一个一个地获取它们,但是你已经把它们都存储起来了。希望对你有帮助!
您肯定可以将整个对象存储在您的UserDefaults
或钥匙串中,没问题。诀窍是使其符合 NSCoding
协议,然后使用 NSKeyedArchiver
和 NSKeyedUnarchiver
将其与可以存储的 Data
对象相互转换。别担心,这听起来比实际更复杂。
符合NSCoding
推测您的 BUYCustomerToken
class 已经是 NSObject
的后代,所以您已经成功了一半。你只需要添加几个方法来让你的自定义 class 被编码(变成 Data
)并从 NSCoder
自动解码。具体来说,它们是:encode(with coder: NSCoder)
和 init(coder aDecoder:NSCoder)
。然后使用编码器的各种 encode() 和 decode() 函数来完成这些工作。 encode() 和 decode() 适用于任何支持 NSCoding
的对象,其中包括 NSNumber
、String
和 Date
,因此您在这里的工作非常简单。完成的可编码 class 将如下所示:
class BUYCustomerToken : NSObject, NSCoding {
var customerID: NSNumber!
var accessToken: String!
var expiry: Date!
override init() {
}
convenience init(customerID: NSNumber, accessToken: String, expiry: Date) {
self.init()
self.customerID = customerID
self.accessToken = accessToken
self.expiry = expiry
}
required init(coder aDecoder: NSCoder) {
customerID = aDecoder.decodeObject(forKey: "customerID") as! NSNumber
accessToken = aDecoder.decodeObject(forKey: "accessToken") as! String
expiry = aDecoder.decodeObject(forKey: "expiry") as! Date
}
func encode(with aCoder: NSCoder) {
aCoder.encode(customerID, forKey: "customerID")
aCoder.encode(accessToken, forKey: "accessToken")
aCoder.encode(expiry, forKey: "expiry")
}
override var description: String {
return "ID: \(customerID!), Token: \"\(accessToken!)\", Expires: \(expiry!)"
}
}
当然,您可以添加自己的自定义方法。 description
不是必须的,但方便测试。
从 UserDefaults 存储和检索
现在您的 class 支持 NSCoding,您可以将其存档并存储,然后检索它。
要存储它,首先要使用 NSKeyedArchiver.archivedData(withRootObject)
归档(将其转换为 Data
对象)。这是可行的,因为您的 class 符合 NSCoding
标准。获得 Data
对象后,您可以使用 set(value, forKey)
.
UserDefaults
中
当你想取回它时,你可以用另一种方式进行:首先使用 data(forKey)
从 UserDefaults
中获取一个 Data
对象,然后使用 NSKeyedUnarchiver.unarchiveObject(with)
,最后将其转换为您的自定义 class。
这里有一段代码尝试从 UserDefaults
加载 BUYCustomerToken
。如果成功,则打印描述;如果失败,它会创建一个新令牌并存储它。将此代码放入初始 UIViewController
的 viewDidLoad()
以查看其实际效果:
if let customerTokenData = UserDefaults.standard.data(forKey: "myToken") {
let customerToken = NSKeyedUnarchiver.unarchiveObject(with: customerTokenData) as! BUYCustomerToken
print(customerToken)
} else {
print("No token stored. Launch again to see token.")
let customerToken = BUYCustomerToken(customerID: 999, accessToken: "some token", expiry: Date())
let tokenData = NSKeyedArchiver.archivedData(withRootObject: customerToken)
UserDefaults.standard.set(tokenData, forKey: "myToken")
}
第一次 运行 没有存储令牌,所以输出是:
No token stored. Launch again to see token.
第二次,它会找到存储的令牌并输出其描述:
ID: 999, Token: "some token", Expires: 2017-05-31 21:27:25 +0000