如何将对象保存到UserDefaults或keychain - Swift 3

时间:2017-05-30 22:35:43

标签: swift nsuserdefaults keychain

我正在构建Shopify应用程序,但首先这不是Shopify SDK问题,而是将客户令牌保存到userDefaults或Keychain中。我已经尝试了但是我尝试过的大多数Keychain库只能使用字符串,我需要将令牌保存为整体,如下所示:

BUYCustomerToken(customerID: NSNumber!, accessToken: String!, expiry: Date!)

访问令牌的应用程序的共享客户端如下所示:

BUYClient.sharedClient.customerToken

在注册过程中,用户可以使用令牌成功创建用户。一旦我退出并返回应用程序

BUYClient.sharedClient.customerToken = ""

所以我的问题是,如何将此对象保存为默认值或Keychain以便稍后在进入应用程序时进行调用。我不能只保存部分令牌,就像accessToken只是一个字符串,我需要整个事情。提前谢谢!

2 个答案:

答案 0 :(得分:0)

您可以在UserDefaults中保存多于String类型,您必须将令牌存储在多个键中。

https://developer.apple.com/reference/foundation/userdefaults

  

NSUserDefaults类提供了便于访问的方法   常见类型,例如浮点数,双精度数,整数,布尔值和URL。一个   默认对象必须是属性列表 - 即(或for的实例)   集合,实例的组合):NSData,NSString,   NSNumber,NSDate,NSArray或NSDictionary。

如果您想存储有效期

let expiry = UserDefaults.standard.object(forKey: "expiry") as? Date
UserDefaults.standard.set(Date(), forKey: "expiry")

CustomerID

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")

通过这种方式,您只需要逐个获取它们,但是您已经存储了所有这些内容。我希望它可以帮到你!

答案 1 :(得分:0)

你绝对可以将整个对象存储在UserDefaults或钥匙串中,没问题。诀窍是使其符合NSCoding协议,然后使用NSKeyedArchiverNSKeyedUnarchiver将其转换为可以存储的Data对象。别担心,这听起来比现在复杂得多。

符合NSCoding

据推测,您的BUYCustomerToken课程已经是NSObject的后代,所以您已经到了中途。您只需添加几种方法即可对自定义类进行编码(转换为Data)并自动从NSCoder解码。具体来说,这些是:encode(with coder: NSCoder)init(coder aDecoder:NSCoder)。然后,您可以使用编码器的各种encode()和decode()函数来实现这些功能。 encode()和decode()适用于支持NSCoding的任何对象,其中包括NSNumberStringDate,因此您的工作非常简单。完成的可编码类将如下所示:

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存储和检索

现在您的类支持NSCoding,您可以将其存档并存储,然后检索它。

要存储它,请先使用Data 归档(将其转换为NSKeyedArchiver.archivedData(withRootObject)对象)。这是有效的,因为您的班级符合NSCoding。获得Data对象后,您可以使用UserDefaults将其存储在set(value, forKey)中。

当您想要检索它时,您可以采用另一种方式:首先使用DataUserDefaults获取data(forKey)对象,然后使用{{1}将其转换回对象最后把它投射到你的自定义类。

以下是尝试从NSKeyedUnarchiver.unarchiveObject(with)加载BUYCustomerToken的一些代码。如果成功,则打印描述;如果失败,它会创建一个新令牌并存储它。将此代码放在您的初始UserDefaults的{​​{1}}中,以查看其实际效果:

viewDidLoad()

第一次运行它时,没有存储的令牌,因此输出为:

  

没有存储令牌。再次启动以查看令牌。

第二次,它会找到存储的令牌并输出其描述:

  

ID:999,Token:" some token",Expires:2017-05-31 21:27:25 +0000