2016-03-30 7 views
0

にはAnyObjectが含まれています。それらのうちの1つAnyObjectは、実際にはスイフトアレイです。私はそうのように、配列を変更しようとしている:ディクショナリ内のスワイプ配列を変更する<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]タイプの不変の価値に変異メンバーを使用することはできません私が代わりにスウィフトArrayNSMutableArrayを使用してみました、それが動作する

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

、しかし:それを引き起こしました私は、「純粋な」迅速なソリューションがあるかどうかを知りたいと思います。 <String, Array>タイプの辞書について話している記事がありますが、これはすべての途中でキャストが必要なので、私は自分の問題を解決するとは思わないのです。

アレイを変更する正しい方法は何ですか?

答えて

0

割り当てを使用しないときに警告が表示されるのは、不変であるとみなされるためです。それをvar elements = ...と宣言することにより、append()と呼ぶことができます。 letに変更すると、おそらく同じ警告が表示されます。

もう一度配列を作成し、辞書のelementsオブジェクトを再割り当てすることをお勧めします。その後、あなたはそれを不変であると宣言しました。それから私は自分自身に尋ねなければなりません:辞書自体を不変であると宣言した場合、なぜそのオブジェクトの1つを変更しようとしていますか?

もう1つの質問は、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) 
} 

私はあなたが[Int][AnyObject]から行くようにしようとしているという理由だけで、ここで、オプションのアンラッピングを行うことを避けることができますどのように表示されていないと、このかどうかを知る方法はありません実行時に事前に動作します。

UPDATE:

彼女は私の更新ですので、あなたは完全なコードを追加しています。基本的に2つの大きな問題があります。 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

私は実際にレットを使用していません - 私は自分の間違いを認識し、質問を更新しました。 – Moshe