如何在NSUserDefaults中使用(多种types)保存数组

这很简单,但似乎无法find正确的信息来解决在用户默认值中保存这样的数组。

它说这不是一个属性,NSUser默认Excepts。

码:

var notificationList: [(type: String,imageName: String, text: String, date: String, seen: Bool)] = [(type: "Default",imageName: "ClearPartioned", text: "", date: "", seen: true)] if (UserDefaults.standard.object(forKey: "notificationList")) == nil { // first time launching print("making notification list") UserDefaults.standard.set(notificationList, forKey: "notificationList") UserDefaults.standard.synchronize() print("\(notificationList)") } else { print("getting saved array") notificationList = (UserDefaults.standard.object(forKey: "notificationList") as! [(type: String, imageName: String, text: String, date: String, seen: Bool)]) print("\(notificationList)") } 

在这里输入图像说明

更新:

这是更接近,但在这个问题在这里发现错误。 这些是我已经能够find的最近的答案,那里或者过时或者崩溃了系统。

码:

  if (UserDefaults.standard.object(forKey: "notificationList")) == nil { // first time launching print("making notification list") let encodedData = NSKeyedArchiver.archivedData(withRootObject: notificationList) UserDefaults.standard.set(encodedData, forKey: "notificationList") UserDefaults.standard.synchronize() } else { print("getting saved array") notificationList = (UserDefaults.standard.object(forKey: "notificationList") as! [(type: String, imageName: String, text: String, date: String, seen: Bool)]) print("\(notificationList)") } 

更新2:这是最好的答案从Dhiru实施

码:

  if (UserDefaults.standard.object(forKey: "notificationList")) == nil { // first time launching print("making notification list") let notificationData = NSKeyedArchiver.archivedData(withRootObject: notificationList) UserDefaults.standard.set(notificationData, forKey: "notificationList") UserDefaults.standard.synchronize() } else { print("getting saved array") let decodedData = UserDefaults.standard.object(forKey: "notificationList") as! Data let notificationList = NSKeyedUnarchiver.unarchiveObject(with: decodedData) as AnyObject print("\(notificationList)") } 

它给我一个崩溃系统的错误

  *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x1c011f380' libc++abi.dylib: terminating with uncaught exception of type NSException 

我确定这段代码会解决这个问题,但是由于我不知道如何使用这段代码,所以这个代码很可怕地实现了下面的多个错误。

码:

  func (coder aDecoder: NSCoder) { if let notificationList = aDecoder.decodeObjectForKey("notificationList") { self.notificationList = notificationList } } func encodeWithCoder(aCoder: NSCoder) { if let notificationList = notificationList { aCoder.encodeObject(notificationList, forKey: "notificationList") } } 

这就是我实际上保存Swift 4中的应用程序中创build的自定义对象。

首先,我们创build了3个协议,用于保存UserDefaults的自定义对象。 背后的逻辑是将Custom Object转换为规范化的Dictionary/Arrayforms。

这可以应用于您创build的任何types的对象。

这3个协议是:

  1. Decoder (用于将字典解码为自定义对象)
  2. Encoder (用于将自定义对象编码为字典)
  3. UserDefaultsProtocol (用于从UserDefault保存,删除,更新和检索自定义对象)

解码器协议

 protocol Decoder { associatedtype T static func decode(dictionary: [String: Any]) -> T } 

编码器协议

 protocol Encoder { func encode() -> [String: Any] } 

UserDefaultsProtocol

 protocol UserDefaultsDelegate: class { associatedtype T func saveToUserDefaults() static func removeFromUserDefaults() static func retrieveFromUserDefaults() -> T? } 

根据你的问题, NotificationList对象看起来像这样

 class NotificationList { var type: String = "" var imageName: String = "" var text: String = "" var date: String = "" var seen: Bool = false } 

现在,您需要确认所有3个提到的协议到NotificationList 。 (Swift最佳实践:扩展和协议的使用)

 class NotificationList { private struct Constants { static let RootKey = "notification_list" static let TypeKey = "type" static let ImageNameKey = "image_name" static let TextKey = "text" static let DateKey = "date" static let SeenKey = "seen" } var type: String = "" var imageName: String = "" var text: String = "" var date: String = "" var seen: Bool = false typealias T = NotificationList } extension NotificationList: Encoder { func encode() -> [String : Any] { return [ Constants.TypeKey: type, Constants.ImageNameKey: imageName, Constants.TextKey: text, Constants.DateKey: date, Constants.SeenKey: seen ] } } extension NotificationList: Decoder { static func decode(dictionary: [String: Any]) -> NotificationList { let type = dictionary[Constants.TypeKey] as! String let imageName = dictionary[Constants.ImageNameKey] as! String let text = dictionary[Constants.TextKey] as! String let date = dictionary[Constants.DateKey] as! String let seen = dictionary[Constants.SeenKey] as! Bool let notificationList = NotificationList() notificationList.type = type notificationList.imageName = imageName notificationList.text = text notificationList.date = date notificationList.seen = seen return notificationList } } extension NotificationList: UserDefaultsDelegate { func saveToUserDefaults() { UserDefaults.standard.setValue(encode(), forKey: Constants.RootKey) } static func retrieveFromUserDefaults() -> NotificationList? { guard let encodedNotificationList = UserDefaults.standard.dictionary(forKey: Constants.RootKey) else { return nil } return NotificationList.decode(dictionary: encodedNotificationList) } static func removeFromUserDefaults() { UserDefaults.standard.removeObject(forKey: Constants.RootKey) } } 

如何将NotificationList保存到UserDefaults?

 var notificationList = NotificationList() notificationList.type = "Default" notificationList.imageName = "ClearPartioned" notificationList.text = "" notificationList.date = "" notificationList.seen = true 

保存到UserDefaults

 notificationList.saveToUserDefaults() 

从UserDefaults中检索

 if let notificationList = NotificationList.retrieveFromUserDefaults() { // You will get the instance of notification list saved in UserDefaults } 

如何保存通知单列表?

notificationLists包含notificationList对象的数组。

 var notificationListsArray = [[String: Any]]() notificationLists.forEach { notificationListsArray.append($0.encode()) } 

将该字典数组保存到UserDefaults

 UserDefaults.standard.setValue(notificationListsArray, forValue: "notificationLists") 

你必须存储你的对象forms的Data转换成数据使用NSKeyedArchiver.archivedData(withRootObject:)

使用NSKeyedUnarchiver.unarchiveObject(with:)转换回Object

为UserDefaults保存数据

 let notificationData = NSKeyedArchiver.archivedData(withRootObject: notificationList) UserDefaults.standard.set(notificationData, forKey: "notificationList") 

从用户UserDefaults返回数据

 let decodedData = UserDefaults.standard.object(forKey: "notificationList") as! Data let notificationList = NSKeyedUnarchiver.unarchiveObject(with: decodedData) as! AnyObject