【问题标题】:Save and Load Custom Dictionary - NSUserDefaults保存和加载自定义字典 ​​- NSUserDefaults
【发布时间】:2016-08-15 20:38:40
【问题描述】:

我有一个 [Int:Bool] 字典,我正在尝试将其保存到我的 NSDictionary 中。但是,它崩溃并出现错误 Attempt to set a non-property-list object

let dictionary = [Int:Bool]()


self.dictionary[2] = true
self.dictionary[3] = false

NSUserDefaults.standardUserDefaults().setObject(dictionary, forKey: "dictionary")

另外,为了加载,我首先尝试了这个,但记录了错误,它严格要求 AnyObject?。

NSUserDefaults.standardUserDefaults().objectForKey("dictionary")

然后我尝试了这个并记录了:

NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool]

我也试过dictionaryForKey。我得到了..

NSUserDefaults.standardUserDefaults().dictionaryForKey("dictionary")

无法将值赋给类型 [String: AnyObject] 以键入 [Int:Bool]


那么这两种方法中哪一种更好呢? (我认为这些值在我的情况下是可选的)

1.
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool] ?? [Int:Bool]()

2.
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool])!

【问题讨论】:

  • 您是否在保存后同步了您的 NSUserDefaults? NSUserDefaults.standardUserDefaults().synchronize()
  • 我认为你应该使用dictionaryForKey(_:)
  • 啊。我完全忘记将其添加到问题中。我也试过了..出现错误..更新了我的问题
  • 如果在当前范围内声明,为什么要访问dictionaryself.
  • 另外,您显然不能将值添加到您使用 let 声明的字典中...

标签: ios swift dictionary nsuserdefaults


【解决方案1】:

斯威夫特 4

在基本类型中,UserDefaults 可以保存任何符合Codable 协议的对象。 Dictionary 是实现此协议的类型之一。您甚至不需要编写任何自定义代码:

let dictionary = ["name": "Adam"]

// Save to User Defaults
UserDefaults.standard.set(dictionary, forKey: "names") 

// Read from User Defaults     
let saved = UserDefaults.standard.value(forKey: "names") as? [String: String]

查看更多关于Codable的信息

斯威夫特 3

您可以使用UserDefaults 保存Dictionary,只要键和值类型是可以以plist 格式表示的类型(NSNumberData 等)。如果不是这样,我们总是可以在写入时将其他类型序列化为Data,并在读取时从Data 反序列化。它可以通过使用NSKeyArchiverUserDefaults 进行非常简单的扩展来完成:

extension UserDefaults {
    /// Save dictionary on key
    open func set<Key, Value>(dictionary: [Key: Value]?, forKey key: String) {
        let data = NSKeyedArchiver.archivedData(withRootObject: dictionary as Any)
        set(data, forKey: key)
    }

    // Retrieve dictionary for key
    open func dictionary<Key, Value>(forKey key: String) -> [Key: Value]? {
        guard let data = object(forKey: key) as? Data else { return nil }
        return NSKeyedUnarchiver.unarchiveObject(with: data) as? [Key: Value]
    }
}

现在你可以调用这些方法了:

let ages = ["Adam": 25]

// Save
UserDefaults.standard.set(dictionary: ages, forKey: "ages")

// Read
let saved: [String: Int]? = UserDefaults.standard.dictionary(forKey: "ages")
print(saved) // Optional(["Adam": 25])

斯威夫特 2

保存自定义数据

func setCustomDictionary(dict: [Int: Bool]) {
    let keyedArch = NSKeyedArchiver.archivedDataWithRootObject(dict)

    NSUserDefaults.standardUserDefaults().setObject(keyedArch, forKey: "dictionary")
}

检索数据

func getDictionary() -> [Int: Bool]? {
    let data = NSUserDefaults.standardUserDefaults().objectForKey("dict")
    let object = NSKeyedUnarchiver.unarchiveObjectWithData(data as! NSData)
    return object as? [Int: Bool]
}

用法

var customDictionary = [Int: Bool]()
customDictionary[2] = true
customDictionary[3] = false

// Store data in NSUserDefaults
setCustomDictionary(customDictionary)

// Get data from NSUserDefaults
let userDefaultsDictionary = getDictionary()

【讨论】:

  • [Int: Bool] 类型的东西不是自动转换为 NSDictionary 吗?
  • 没有。这是因为 Swift 字典是通用结构 Dictionary&lt;T,E&gt;NSDictionary 是 ObjectiveC NSObject 派生类。它们在早期版本的 Swift 中被桥接,但现在不是。
  • 你能用源备份吗?这在操场上对我有用:let dictionary: NSDictionary = [1: "a", 2: "b"].
  • @TimVermeulen 似乎 NSDictionary 仍然与 swift Dictionary 桥接。类型之间的转换不会自动发生,您可以使用 swift 字典语法初始化 NSDictionary
  • 但这也有效:let dict = [1: "a", 2: "b"]; let nsDict: NSDictionary = dict
【解决方案2】:

我遇到了类似的问题,但数据类型不同。 我的建议是转换为 NSData 并像这样检索数据:

/// Save
NSUserDefaults.standardUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(object), forKey: key)

/// Read
var data = NSUserDefaults.standardUserDefaults().objectForKey(key) as NSData
var object = NSKeyedUnarchiver.unarchiveObjectWithData(data) as [String: String]

(虽然提到 [String : String] 我实际上用于 [[String: AnyObject]] 并且有效,所以也许它也可以为您工作!)

【讨论】:

    【解决方案3】:

    这是为 Swift 3 准备的

    func setCustomDictionary(dict: [Int: Bool]) {
        let keyedArch = NSKeyedArchiver.archivedData(withRootObject: dict)
    
        UserDefaults.standard.set(keyedArch, forKey: "dictionary")
    }
    
    func getDictionary() -> [Int: Bool]? {
        let data = UserDefaults.standard.object(forKey: "dict")
        let object = NSKeyedUnarchiver.unarchiveObject(with: (data as! NSData) as Data)
        return object as? [Int: Bool]
    }
    

    【讨论】:

      【解决方案4】:

      如果你需要更多类型,你可以使用这样的泛型:

      func saveUserDefaults<T>(withKey key: String, dict: AnyObject, myType: T.Type) {
          guard let dict = dict as? T else {
              print("Type mismatch")
              return
          }
          let archiver = NSKeyedArchiver.archivedData(withRootObject: dict)
          UserDefaults.standard.set(archiver, forKey: key)
      }
      
      func getUserDefaults<T>(withKey key: String, myType: T.Type) -> T? {
          let unarchivedObject = getUserDefaultData(withKey: key)
          return unarchivedObject as? T
      }
      
      func getUserDefaultData(withKey key: String) -> Any? {
          guard let data = UserDefaults.standard.object(forKey: key) else {
              return nil
          }
          guard let retrievedData = data as? Data else {
              return nil
          }
          return NSKeyedUnarchiver.unarchiveObject(with: retrievedData)
      }
      

      例如[Int:Int]类型用法:

          var customDictionary = [Int: Int]()
          customDictionary[234] = 1
          customDictionary[24] = 2
          customDictionary[345] = 3
      
          saveUserDefaults(withKey: "hello", dict: customDictionary as AnyObject, myType: [Int: Int].self)
          let savedDictionary = getUserDefaults(withKey: "hello", myType: [Int: Int].self)
          print(savedDictionary)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多