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