2015-12-02 84 views
2

我想保存自選StringsNSUserDefaults的數組,但不幸的是它不工作:Swift:將選擇數組存儲到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

[String?]是不能被表示爲基金類型雨燕。通常,Swift數組橋接到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文本字段的數量。)

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

但後來你怎麼從默認還原狀態呢?既然你已經'flatMap'數組,你不知道哪些索引有nil。據推測,OP首先使用'[String?]'的原因是有些索引可能是空的。 – rickster

+0

@ rickster:好點!如果OP確實需要保存'nil'值,我可以考慮更詳細的解決方案。 –

+0

[這是一個解決方案](http://stackoverflow.com/a/34053503/957768),儘管它遠非唯一可能的解決方案。 – rickster