Swift:在NSUserDefaults中存储选项数组?

时间:2015-12-02 20:29:47

标签: arrays swift nsuserdefaults

我正在尝试将一系列可选项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?'
} 

2 个答案:

答案 0 :(得分:2)

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

然后,当您从默认值中读取数据时,请从稀疏数组字典表单转换为可选数组表单。这更有趣,因为您需要从稀疏表示中找出需要存储数组的nils。

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是不变的,因为它是您的用户界面中文本字段的数量。)

答案 1 :(得分:0)

让我们说这是原始数组

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