2016-03-30 47 views
0

我有一個Dictionary其中有AnyObject s。其中AnyObject s實際上是一個Swift數組。我試圖修改數組,像這樣:修改字典中的Swift數組<String,AnyObject>

class MyClass { 
    internal(set) var dictionary : Dictionary<String, AnyObject> 

    init() { 
     self.dictionary = [ 
      "displayName": "Foo", //String : String 
      "elements" : [] // String : Array 
     ] 
    } 

    // ... 

    func addNumber(number : Int) { 
    // Something here 
    } 
} 

這裏是我此代碼單元測試:

func testAddNumber() { 

    let foo = MyClass() 

    let beforeCount = foo.dictionary["elements"].count 

    foo.addNumber(10) 

    let afterCount = foo.dictionary["elements"].count 

    XCTAssert(beforeCount + 1 == afterCount, "Count was \(afterCount)") 

} 

我試着拔出陣列並將其分配給一個臨時變量,但是這個項目實際上並沒有被添加到鍵入elements的數組中。

var elements = (self.dictionary["elements"] as! [Int]) 
elements.append(10) 

此代碼運行,但是當我跑我的單元測試,以檢查是否被添加的元素,測試失敗。

如果我不使用中間分配,我得到一個編譯錯誤約易變性:

無法在類型的不可變的值使用可變成員[FormGroup]

這裏的代碼,導致它:

(self.dictionary["elements"] as! [Int]).append(10) 

我嘗試使用NSMutableArray而不是斯威夫特Array,那工作,但我想知道是否有「純粹」的Swift解決方案。有一些帖子提到類型爲<String, Array>的字典,但這需要將其全部投入中間,所以我不認爲它們解決了我的問題。

什麼是修改數組的正確方法?

回答

0

當您不使用任務時,您會收到警告,因爲它認爲它不可變。通過聲明var elements = ...,您可以撥打電話append()。如果將其更改爲let,則可能會得到相同的警告。

我打算建議你再次創建數組,然後重新指定字典的elements對象,然後我看到你聲明它是不可變的。然後我得問自己:如果你將字典本身定義爲不變的,爲什麼你要改變它的一個對象?

另一個問題是:爲什麼它甚至可以讓你聲明元素使用var而不是強制執行let

1

擺脫力量解開。它會在方法中暴露無效的參數,或者在相關邏輯中出現其他問題。

guard var elements = self.dictionary["elements"] as? [Int] else { return } 
elements.append(10) 

if var elements = self.dictionary["elements"] as? [Int] { 
    elements.append(10) 
} 

我看不出你如何能避免這裏做什麼可選的未包裝僅僅是因爲你試圖去從[AnyObject][Int],也沒有辦法知道,如果這將在運行時提前工作。

UPDATE:

您已經添加了完整的代碼,所以她是我的更新。基本上有兩個主要問題。 1)你試圖避免處理可選項。在迅速,你必須處理它們。因爲處理Dictionary和Array類型的方法只返回可選值。 2)你的單元測試幾乎沒有用處。除了「不空的東西」之外,你應該檢查許多其他的東西,以確保該方法按預期工作。

這裏是我的操場承擔您的問題。

let elementsKey = "elements" 

class MyClass { 
    var dictionary : Dictionary<String, AnyObject> 

    init() { 
     self.dictionary = [ 
      "displayName": "Foo", //String : String 
      elementsKey : [] // String : Array 
     ] 
    } 

    func addNumber(number : Int) { 

     guard var mutableArray = self.dictionary[elementsKey] as? [Int] else { return } 

     mutableArray.append(number) 
     self.dictionary[elementsKey] = mutableArray 
    } 
} 

func testAddNumber() { 

    let number: Int = 10 
    let foo = MyClass() 

    let before = foo.dictionary[elementsKey] as? [Int] 
    foo.addNumber(number) 
    let after = foo.dictionary[elementsKey] as? [Int] 

    print(before != nil) 
    print(after != nil) 
    print(before! != after!) 
    print(before?.isEmpty) 
    print(after?.isEmpty) 
    print(after?.contains(number)) 
} 

testAddNumber() 
+0

這實質上是一個本地可變副本。單元測試以這種方式失敗。 – Moshe

0

「let」的意思是事物不可改變。使用var作爲成員變量,如果你想在任何級別上改變「內部」的東西

你會發現舊的Objective-C的東西「工作」在這裏的原因是,他們不能改變所有這些語義,並保持兼容性。

+0

我實際上並沒有使用let - 我意識到我的錯誤並更新了問題。 – Moshe

相關問題