如何在NSUserDefaults中使用(多种类型)保存数组 [英] How to save a Array with (Multiple Types) in NSUserDefaults

查看:223
本文介绍了如何在NSUserDefaults中使用(多种类型)保存数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This is pretty simple but can't seem to find the correct information to solve saving an array like this in User Defaults.

它说这不是NSUser Defaults Excepts的属性.

It says it's not a property that 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)")
    }

更新:

距离更近了,但给出了在此问题中发现的错误,此处.这些是我能找到的壁橱答案,那里已经过时或崩溃了.

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.

代码:

    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的最佳答案实现

Update 2: This is best answer implementation From 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)")
    }

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

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.

代码:

   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 中保存在应用中创建的自定义对象的方式.

This is how I actually save a Custom Object created in the app in Swift 4.

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

First, we create 3 protocols for our purpose of saving the custom object in UserDefaults. The logic behind is to convert the Custom Object into a normalized Dictionary/Array form.

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

This can be applied to any kind of Object which you have created.

这三种协议是:

  1. Decoder(用于将字典解码为自定义对象)
  2. Encoder(用于将自定义对象编码为字典)
  3. UserDefaultsProtocol(用于保存,删除,更新和检索UserDefault中的自定义对象)
  1. Decoder (Used to decode the dictionary into custom object)
  2. Encoder (Used to encode the custom object into dictionary)
  3. UserDefaultsProtocol (Used to save, delete, update & retrieve the custom object from 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 对象看起来像这样

As per your question, NotificationList Object would look like this

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

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

Now, you need to confirm all the 3 mentioned protocols to NotificationList. (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)
    }
}

如何将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对象的数组.

Say notificationLists contains the array of notificationList objects.

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

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

将该字典数组保存到UserDefaults

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

这篇关于如何在NSUserDefaults中使用(多种类型)保存数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆