繁体   English   中英

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

[英]How to save a Array with (Multiple Types) in NSUserDefaults

这很简单,但是似乎找不到正确的信息来解决在User Defaults中保存这样的数组。

它说这不是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)")
    }

在此处输入图片说明

更新:

这是接近,但给出了这个问题,发现错误这里 这些是我能找到的壁橱答案,或者已经过期或崩溃了。

码:

    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:)转换回Object

为用户默认值保存数据

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应用程序中创建的自定义对象的方式。

首先,为了将自定义对象保存在UserDefaults ,我们创建了3种协议。 背后的逻辑是将Custom Object转换为规范化的Dictionary/Array形式。

这可以应用于您创建的任何类型的对象。

这三个协议是:

  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
}

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM