protocols.forEach { $0.prop = nil }
results in:
Cannot assign to property: '$0' is immutable
I worked around this with:
protocols.forEach { var protocol = $0 protocol.prop = nil }
But why is the compiler okay with this? I would expect it could figure this out.
You have an array of items that implement a protocol. If you don't tell Swift that this is a class
protocol, it will assume that it can be implemented by a struct
.
In a forEach
loop, you will essentially have a let
variable (called $0
by default) assigned to each value in the array in turn. If you have an array of objects (instances of a class), then you can modify properties of that item. If you have an array of struct
items, then those will be immutable. If you have an array of items that implement a protocol, then Swift will treat them as the more restrictive struct
unless you add : class
to your protocol definition.
For example:
protocol Xyzzy: class { var prop: Int? { get set } } class Fred: Xyzzy, CustomStringConvertible { var description: String { return "\(prop)" } var prop: Int? = 17 } let objects: [Xyzzy] = [Fred(), Fred(), Fred()] print(objects) // [Optional(17), Optional(17), Optional(17)] objects.forEach { $0.prop = nil } print(objects) // [nil, nil, nil]
Your workaround:
protocols.forEach { var protocol = $0 protocol.prop = nil }
works for class objects because it creates a new var
pointer to the object, and then that allows you to modify the object. Note, this workaround only works for instances of classes. If your protocol is implemented by a struct
, then the new var
will be a new copy of the struct
item, and the original ones in the array will not be changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With