如何在 NSUserDefaults 中使用(多种类型)保存数组
How to save a Array with (Multiple Types) in NSUserDefaults
这很简单,但似乎找不到正确的信息来解决在用户默认值中保存这样的数组的问题。
它说它不是 NSUser Defaults 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)")
}
更新:
这更接近,但给出了在这个问题 here 中发现的错误。这些是我能够找到的最隐秘的答案,它们要么已经过时,要么会导致系统崩溃。
代码:
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")
}
}
您必须以 Data
的形式存储您的对象
转换成数据使用
NSKeyedArchiver.archivedData(withRootObject:)
转换回对象使用
NSKeyedUnarchiver.unarchiveObject(with:)
为 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
这就是我在 Swift 4.
中实际保存在应用程序中创建的自定义对象的方式
首先,我们创建了 3 个协议,用于将自定义对象保存在 UserDefaults
中。背后的逻辑是将 Custom Object
转换为规范化的 Dictionary/Array
形式。
This can be applied to any kind of Object which you have created.
这 3 个协议是:
Decoder
(用于将字典解码为自定义对象)
Encoder
(用于将自定义对象编码成字典)
UserDefaultsProtocol
(用于保存、删除、更新和检索来自 UserDefault
的自定义对象)
解码协议
protocol Decoder {
associatedtype T
static func decode(dictionary: [String: Any]) -> T
}
编码器协议
protocol Encoder {
func encode() -> [String: Any]
}
用户默认协议
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
}
现在,您需要向 NotificationList
确认所有提到的 3 个协议。 (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
保存到用户默认值
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([=18=].encode())
}
将该字典数组保存到 UserDefaults
UserDefaults.standard.setValue(notificationListsArray, forValue: "notificationLists")
这很简单,但似乎找不到正确的信息来解决在用户默认值中保存这样的数组的问题。
它说它不是 NSUser Defaults 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)")
}
更新:
这更接近,但给出了在这个问题 here 中发现的错误。这些是我能够找到的最隐秘的答案,它们要么已经过时,要么会导致系统崩溃。
代码:
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")
}
}
您必须以 Data
的形式存储您的对象
转换成数据使用
NSKeyedArchiver.archivedData(withRootObject:)
转换回对象使用
NSKeyedUnarchiver.unarchiveObject(with:)
为 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
这就是我在 Swift 4.
中实际保存在应用程序中创建的自定义对象的方式首先,我们创建了 3 个协议,用于将自定义对象保存在 UserDefaults
中。背后的逻辑是将 Custom Object
转换为规范化的 Dictionary/Array
形式。
This can be applied to any kind of Object which you have created.
这 3 个协议是:
Decoder
(用于将字典解码为自定义对象)Encoder
(用于将自定义对象编码成字典)UserDefaultsProtocol
(用于保存、删除、更新和检索来自UserDefault
的自定义对象)
解码协议
protocol Decoder {
associatedtype T
static func decode(dictionary: [String: Any]) -> T
}
编码器协议
protocol Encoder {
func encode() -> [String: Any]
}
用户默认协议
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
}
现在,您需要向 NotificationList
确认所有提到的 3 个协议。 (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
保存到用户默认值
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([=18=].encode())
}
将该字典数组保存到 UserDefaults
UserDefaults.standard.setValue(notificationListsArray, forValue: "notificationLists")