ForEach results at $ 0 - immutable error

protocols.forEach { $0.prop = nil } 

leads to:

 Cannot assign to property: '$0' is immutable 

I worked with this:

 protocols.forEach { var protocol = $0 protocol.prop = nil } 

But why is the compiler ok? I expect this can figure it out.

+7
arrays foreach swift
source share
1 answer

You have an array of elements that implement the protocol. If you don't tell Swift that this is a class protocol, it will assume that it can be implemented using struct .

In the forEach loop, you will essentially have a let variable ( $0 by default) assigned to each value in the array in turn. If you have an array of objects (instances of the class), you can change the properties of this element. If you have an array of struct elements, then they will be immutable. If you have an array of elements that implement the protocol, then Swift will consider them as more restrictive struct unless you add : class to the 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 object for the object and then lets you modify the object. Note that this workaround only works for class instances. If your protocol is implemented using struct , then the new var will be a new copy of the struct element, and the original ones in the array will not be changed.

+18
source share

All Articles