I'm new to Swift, so I appreciate any feedback or suggestions on my approach. For reference, I'm using Xcode 12.1 and Swift 5.3. Essentially, I have a series of struct
s, one of which has an array of strings. What I'd like to do, is to append a string to that array. Consider the following code:
struct Collection {
var things: [Thing] = []
mutating func add(_ thing: Thing) {
things.append(thing)
}
}
struct Thing {
var messages: [String] = []
mutating func add(_ message: String) {
messages.append(message)
}
}
var collection = Collection()
collection.add(Thing())
var thing = collection.things.first
thing!.add("test")
print(collection.things.first!.messages.count)
I was expecting the final line to print 1
, but instead it prints 0
! The compile does not display any errors either. If I change the code so that struct Thing
is class Thing
and drop the mutating
keyword from its add
method, then the code works.
Having said that, I don't understand why my original code does not work as I would expect. I'm able to append a Thing
instance to Collection
, but not a string to that same Thing
instance after the fact.
Have I misunderstood how the mutating
keyword works?
You would get your expected 1
if you did:
print(thing!.messages.count)
because you have added the "test"
to thing.messages
, not collection.things.first!.messages
.
"Now hold on a second!" I hear you say, "I just said var thing = collection.things.first
on the previous line! How come adding to thing.messages
doesn't imply adding to collection.things.first!.messages
?".
This is because structs have value semantics. When you do var thing = collection.things.first
, you are saying "copy the value of collection.things.first
to a variable called thing
". You are not saying "the variable thing
now refers to the same thing as collection.things.first
". To say that, Thing
has to be a reference type ( class
).
So now you have two copies of the same value, one in thing
and one in collection.things.first
. You change the copy stored in thing
. The other copy is unaffected.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.