2017-05-30 144 views
1

我正在构建Shopify应用程序,但首先并非Shopify SDK问题,它是关于将客户令牌保存到userDefaults或Keychain中的。我试过,但最钥匙扣库我只试过用字符串的工作,我需要令牌保存为一个整体,看起来像这样:如何将对象保存到UserDefaults或钥匙串中 - Swift 3

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

应用的共享客户端访问令牌的样子这个:

BUYClient.sharedClient.customerToken 

注册过程中,用户通过令牌成功创建。有一次,我退出并返回到应用程序的

BUYClient.sharedClient.customerToken = "" 

所以我的问题是,我怎么这个对象保存到默认设置或钥匙扣进入应用程序时,后来回忆。我不能保存部分令牌,就像accessToken,它只是一个字符串,我需要整个事情。提前致谢!

回答

0

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

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

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

,如果你想存储的到期日

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

在客户

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

用这种方法,你只需要一一得到它们,但你已经全部存储了它们。我希望它能帮助你!

+0

谢谢你很好的答案!在我看到这个之前就想出了它,并且非常使用你的方法!感谢您的明确答案! –

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,你可以归档并保存,然后进行检索。

要存储它,你需要使用NSKeyedArchiver.archivedData(withRootObject)来启动存档它(将其转换为Data对象)。这是有效的,因为你的课程符合NSCoding。获得Data对象后,可以使用set(value, forKey)将其存储在UserDefaults中。

当你想找回它,你做它的其他方式:先取从UserDefaults使用data(forKey)一个Data对象,然后将其放回使用NSKeyedUnarchiver.unarchiveObject(with)的对象,并最终将其转换为您的自定义类。

这里有一段代码试图从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") 
} 

你运行它第一次没有保持令牌,所以输出:

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

第二时间时,会发现所存储的令牌,并且输出它的描述:

ID:999,令牌: “一些令牌”,过期日期:2017年5月31日二十一点27分25秒+0000

+0

感谢您的详细解答,我使用了以前的答案,但肯定会给这个镜头,看看它是如何工作的。 –

+0

@ManuelAlonzo如果你需要做的只是保存一些字符串,那就太过分了。如果您有更复杂的对象,或者如果您保存多个对象或将它们保存到多个位置,这很有用。 – Robert

+0

是的,我想Shopify只会要求我保存包含这3项内容的令牌。但是我还没有进入购物车的结构,如果你想回忆保存的购物车,它也有代币,所以这仍然可能是有用的! –