如何在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/Array
forms。
这可以应用于您创build的任何types的对象。
这3个协议是:
-
Decoder
(用于将字典解码为自定义对象) -
Encoder
(用于将自定义对象编码为字典) -
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