如何将对象保存到 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 协议,然后使用 NSKeyedArchiverNSKeyedUnarchiver 将其与可以存储的 Data 对象相互转换。别担心,这听起来比实际更复杂。

符合NSCoding

推测您的 BUYCustomerToken class 已经是 NSObject 的后代,所以您已经成功了一半。你只需要添加几个方法来让你的自定义 class 被编码(变成 Data)并从 NSCoder 自动解码。具体来说,它们是:encode(with coder: NSCoder)init(coder aDecoder:NSCoder)。然后使用编码器的各种 encode() 和 decode() 函数来完成这些工作。 encode() 和 decode() 适用于任何支持 NSCoding 的对象,其中包括 NSNumberStringDate,因此您在这里的工作非常简单。完成的可编码 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。如果成功,则打印描述;如果失败,它会创建一个新令牌并存储它。将此代码放入初始 UIViewControllerviewDidLoad() 以查看其实际效果:

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