【问题标题】:Swift: Storing Array of Optionals to NSUserDefaults?Swift:将选项数组存储到 NSUserDefaults?
【发布时间】:2015-12-02 20:29:47
【问题描述】:

我正在尝试将一组可选参数 Strings 保存到 NSUserDefaults,但不幸的是它不起作用:

var textFieldEntries: [String?]
...
func encodeWithCoder(aCoder: NSCoder!) {
    aCoder.encodeObject(textFieldEntries, forKey: "textFieldEntries")
    // prints error: Cannot convert value of type '[String?]'
    // to expected argument type 'AnyObject?'
} 

【问题讨论】:

    标签: arrays swift nsuserdefaults


    【解决方案1】:

    [String?] 是 Swift 类型,不能表示为 Foundation 类型。通常,Swift Array 桥接到 NSArray,但 NSArray 不能包含 nil。一个 Optionals 数组可以包含 nil,所以它不会自动桥接。

    您可以通过使用稀疏数组表示来解决此问题。 (而且由于你的内容是字符串——一种属性列表类型,因此在NSUserDefaults 中使用是合法的——你甚至不需要使用NSCoding 来对数组进行编码。)字典是一个非常好的稀疏数组:

    var textFieldEntries: [String?] = ["foo", nil, "bar"]
    
    func saveToDefaults() {
        var sparseArray: [String: String] = [:] // plists need string keys
        for (index, entry) in textFieldEntries.enumerate() {
            if let e = entry {
                sparseArray["\(index)"] = e
            }
        }
        // sparseArray = ["0": "foo", "2": "bar"]
    
        let defaults = NSUserDefaults.standardUserDefaults()
        defaults.setObject(sparseArray, forKey: "textFieldEntries")
    }
    

    然后,当您从默认值中读取数据时,将稀疏数组字典形式转换为可选数组形式。这更有趣一点,因为您需要从稀疏表示中计算出需要数组存储多少个 nil。

    func readFromDefaults() {
        let defaults = NSUserDefaults.standardUserDefaults()
        guard let sparseArray = defaults.objectForKey("textFieldEntries") as? [String: String]
            else { fatalError("unepxected defaults key format") }
    
        // count of the sparse array = index of highest key + 1
        let count = sparseArray.keys.flatMap({Int($0)}).maxElement()! + 1
    
        // wipe the old array to put nils in all the right places
        textFieldEntries = [String?](count: count, repeatedValue: nil)
    
        // fill in the values
        for (strindex, entry) in sparseArray {
            guard let index = Int(strindex)
                else { fatalError("non-numeric key") }
    
            textFieldEntries[index] = entry
        }
    }
    

    (或者,您可能知道count 是不变的,因为它是您 UI 中文本字段的数量。)

    【讨论】:

      【解决方案2】:

      假设这是原始数组

      let textFieldEntries: [String?]
      

      首先让我们把String?的数组变成String的数组。

      let entries = textFieldEntries.flatMap { $0 }
      

      现在我们可以保存它了

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

      然后检索它

      if let retrieved = NSUserDefaults.standardUserDefaults().objectForKey("entries") as? [String] {
          // here your have your array
          print(retrieved)
      }
      

      【讨论】:

      • 但是你如何从默认状态恢复状态呢?现在您已经flatMapped 数组,您不知道哪些索引有空值。据推测,OP 首先使用[String?] 的原因是某些索引可能为空。
      • @rickster:好点子!如果 OP 确实需要保存 nil 值,我可以考虑更详细的解决方案。
      • Here's one solution,尽管它远非唯一可能的。
      猜你喜欢
      • 2015-07-19
      • 1970-01-01
      • 2015-06-15
      • 1970-01-01
      • 1970-01-01
      • 2018-08-18
      • 1970-01-01
      • 2013-09-25
      • 1970-01-01
      相关资源
      最近更新 更多