我有一个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>
类型的字典,但这需要在其中间进行演员,所以我认为它们不能解决我的问题。
修改数组的正确方法是什么?
答案 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东西“工作”的原因是它们无法改变所有这些语义并保持兼容性。