Swift:将可选数组存储到NSUserDefaults吗? [英] Swift: Storing Array of Optionals to NSUserDefaults?

查看:77
本文介绍了Swift:将可选数组存储到NSUserDefaults吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to save an array of optionals Strings to NSUserDefaults, but unfortunately it doesn't work:

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?'
} 


推荐答案

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

[String?] is a Swift type that cannot be represented as a Foundation type. Normally, Swift Array bridges to NSArray, but an NSArray cannot contain nil. An Array of Optionals can contain nil, so it doesn't bridge automatically.

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

You could work around this by using a sparse array representation. (And since your content is strings — a property list type and therefore legal for use in NSUserDefaults — you don't even need to use NSCoding to encode the array.) A dictionary makes a pretty good sparse array:

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数组。

Then, when you go to read in your data from defaults, convert from the sparse-array dictionary form to the array-of-optionals form. That's a little bit more fun because you need to figure out from the sparse representation how many nils you need the array to store.

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中文本字段的数量。)

(Alternately, you might know that count is constant because it's, say, the number of text fields in your UI.)

这篇关于Swift:将可选数组存储到NSUserDefaults吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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