如何在NSUserDefaults中保存带有(多种类型)的数组

时间:2017-07-06 04:50:43

标签: ios swift 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)")
    }

enter image description here

更新:

这更接近,但在此问题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")
        }
    }

2 个答案:

答案 0 :(得分:2)

您必须以Data的形式存储您的对象 使用转换为数据 NSKeyedArchiver.archivedData(withRootObject:)

使用转换回Object  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

答案 1 :(得分:2)

这就是我在 Swift 4 中实际保存应用程序中创建的自定义对象的方法。

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

  

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

3个协议是:

  1. Decoder(用于将字典解码为自定义对象)
  2. Encoder(用于将自定义对象编码为字典)
  3. UserDefaultsProtocol(用于保存,删除,更新和检索UserDefault中的自定义对象)
  4. 解码器协议

    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个协议。 (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
    }
    

    如何保存通知列表?

    Say notificationLists包含notificationList对象数组。

    var notificationListsArray = [[String: Any]]()
    
    notificationLists.forEach {
         notificationListsArray.append($0.encode())
    }
    

    将该字典数组保存到UserDefaults

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