简体   繁体   English

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

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

This is pretty simple but can't seem to find the correct information to solve saving an array like this in User Defaults. 这很简单,但是似乎找不到正确的信息来解决在User Defaults中保存这样的数组。

It says it's not a property that NSUser Defaults Excepts. 它说这不是NSUser Defaults Excepts的属性。

Code: 码:

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

在此处输入图片说明

Update: 更新:

This is closer but gives error found in this question here . 这是接近,但给出了这个问题,发现错误这里 These are the closet answers I have been able to find and there either out dated or crash the system. 这些是我能找到的壁橱答案,或者已经过期或崩溃了。

Code: 码:

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

Update 2: This is best answer implementation From Dhiru 更新2:这是Dhiru提供的最佳答案

Code: 码:

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

Its giving me an error that crashes system 它给我一个导致系统崩溃的错误

   *** 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

Im sure this code would fix it but this is horribly implemented with multiple errors below because I have no clue how to use this code. 我确定该代码可以解决该问题,但是由于无法识别如何使用此代码,因此在以下多个错误中都实现了该错误。

Code: 码:

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

You have to store your Object in form of Data Convert into data using NSKeyedArchiver.archivedData(withRootObject:) 您必须以Data形式存储对象使用NSKeyedArchiver.archivedData(withRootObject:)转换为数据

Convert back to Object using NSKeyedUnarchiver.unarchiveObject(with:) 使用NSKeyedUnarchiver.unarchiveObject(with:)转换回Object

Saving Data for UserDefaults 为用户默认值保存数据

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

Retrive Data from User UserDefaults 从用户UserDefaults中检索数据

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

This is how I actually save a Custom Object created in the app in Swift 4 . 这就是我实际上保存在Swift 4应用程序中创建的自定义对象的方式。

First, we create 3 protocols for our purpose of saving the custom object in UserDefaults . 首先,为了将自定义对象保存在UserDefaults ,我们创建了3种协议。 The logic behind is to convert the Custom Object into a normalized Dictionary/Array form. 背后的逻辑是将Custom Object转换为规范化的Dictionary/Array形式。

This can be applied to any kind of Object which you have created. 这可以应用于您创建的任何类型的对象。

The 3 protocols are: 这三个协议是:

  1. Decoder (Used to decode the dictionary into custom object) Decoder (用于将字典解码为自定义对象)
  2. Encoder (Used to encode the custom object into dictionary) Encoder (用于将自定义对象编码为字典)
  3. UserDefaultsProtocol (Used to save, delete, update & retrieve the custom object from UserDefault ) UserDefaultsProtocol (用于从UserDefault保存,删除,更新和检索自定义对象)

Decoder Protocol 解码器协议

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

Encoder Protocol 编码器协议

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

UserDefaultsProtocol UserDefaultsProtocol

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

As per your question, NotificationList Object would look like this 根据您的问题, NotificationList对象看起来像这样

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

Now, you need to confirm all the 3 mentioned protocols to NotificationList . 现在,您需要确认NotificationList提到的所有3个协议。 (Swift Best Practice: Use of Extensions & Protocols) (快速最佳实践:使用扩展和协议)

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

How to save NotificationList to UserDefaults? 如何将NotificationList保存到UserDefaults?

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

Save to UserDefaults 保存到UserDefaults

notificationList.saveToUserDefaults()

Retrieve from UserDefaults 从UserDefaults检索

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

HOW TO SAVE ARRAY OF NOTIFICATION LIST? 如何保存通知列表的阵列?

Say notificationLists contains the array of notificationList objects. notificationLists包含notificationList对象的数组。

var notificationListsArray = [[String: Any]]()

notificationLists.forEach {
     notificationListsArray.append($0.encode())
}

Save that array of dictionary to UserDefaults 将该字典数组保存到UserDefaults

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

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

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