问题
I have a collection of objects in a Set
. The objects' type follows GeneratorType
, so I have a mutating method next
. Although I can mutate the set by adding/removing elements, I don't know how to mutate an element. Using both for-in
statement and the forEach
method give errors about the element being immutable. Is the mutability of Swift containers shallow?
Is there a way to call a mutating method on a contained element? Does it work for other collection/sequence types besides Set
? (My changes would change each object's hash, and maybe I'm not allowed to affect a set like that.)
回答1:
The situation is similar to that of mutating one of a dictionary's values, where that value is a value type. You can't do it, even if your reference to the dictionary is a var
reference. Typically, you'll just pull the value out, mutate it, and put it back again:
var d = ["key":"hell"]
var val = d["key"]!
val.append(Character("o"))
d["key"] = val
Your Set works similarly.
var s = Set(["hell"])
var val = s.remove("hell")!
val.append(Character("o"))
s.insert(val)
There are other ways to notate that, but in effect they amount to the same thing.
The thing to keep in mind here is that no value type, e.g. a struct, is truly mutable. We speak of it as if it were, and so does Swift with its mutating
functions, but mutation actually consists of assigning a new value back into the reference. That is why the reference must be a var
. There is thus no such thing as mutation in place for any value type.
Now, of course, with a reference type, e.g. a class, the situation is completely different:
let s = Set([NSMutableString(string:"hell")])
s.first!.appendString("o")
s // {"hello"}
来源:https://stackoverflow.com/questions/36000869/is-the-mutability-of-swift-containers-shallow-or-can-an-element-be-mutated-in-p