修改字典中的Swift数组<string,anyobject =“”>

时间:2016-03-30 21:07:03

标签: arrays swift nsarray immutability

我有一个Dictionary,其中有AnyObject个。其中一个AnyObject实际上是一个Swift数组。我正在尝试修改数组,如下所示:

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而不是Swift Array,这有效,但我想知道是否有“纯粹的”Swift解决方案。有些帖子谈论的是带有<String, Array>类型的字典,但这需要在其中间进行演员,所以我认为它们不能解决我的问题。

修改数组的正确方法是什么?

3 个答案:

答案 0 :(得分: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]并且没有办法知道这是否会提前工作在运行时。

<强>更新

您已添加完整代码,因此她是我的更新。基本上有两个主要问题。 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()

答案 1 :(得分:0)

当您不使用分配时,您会收到警告,因为它认为它是不可变的。通过声明var elements = ...,您可以拨打append()。如果将其更改为let,您可能会收到相同的警告。

我打算建议你再次创建数组,并重新分配你的字典的elements对象,然后我看到你声明它是不可变的。然后我开始问自己:如果你宣称字典本身是不可变的,你为什么要改变它的一个对象呢?

另一个问题是:为什么它甚至允许您使用var声明元素而不强制执行let

答案 2 :(得分:0)

“让”的意图是事物不可改变。如果要在任何级别“内部”更改某些内容,请使用var作为成员变量

你在这里找到旧的Objective-C东西“工作”的原因是它们无法改变所有这些语义并保持兼容性。

相关问题