Swift - How to mutate a struct object when iterating over it

情到浓时终转凉″ 提交于 2019-11-27 23:02:28

问题


I am still not sure about the rules of struct copy or reference.

I want to mutate a struct object while iterating on it from an array: For instance in this case I would like to change the background color but the compiler is yelling at me

struct Options {
  var backgroundColor = UIColor.blackColor()
}

var arrayOfMyStruct = [MyStruct]

...

for obj in arrayOfMyStruct {
  obj.backgroundColor = UIColor.redColor() // ! get an error
}

回答1:


struct are value types, thus in the for loop you are dealing with a copy.

Just as a test you might try this:

Swift 3:

struct Options {
   var backgroundColor = UIColor.black
}

var arrayOfMyStruct = [Options]()

for (index, _) in arrayOfMyStruct.enumerated() {
   arrayOfMyStruct[index].backgroundColor = UIColor.red
}

Swift 2:

struct Options {
    var backgroundColor = UIColor.blackColor()
}

var arrayOfMyStruct = [Options]()

for (index, _) in enumerate(arrayOfMyStruct) {
    arrayOfMyStruct[index].backgroundColor = UIColor.redColor() 
}

Here you just enumerate the index, and access directly the value stored in the array.

Hope this helps.




回答2:


You can use use Array.indices:

for index in arrayOfMyStruct.indices {
    arrayOfMyStruct[index].backgroundColor = UIColor.red
}



回答3:


For Swift 3, use the enumerated() method.

For example:

for (index, _) in arrayOfMyStruct.enumerated() {
  arrayOfMyStruct[index].backgroundColor = UIColor.redColor() 
}

The tuple also includes a copy of the object, so you could use for (index, object) instead to get to the object directly, but since it's a copy you would not be able to mutate the array in this way, and should use the index to do so. To directly quote the documentation:

If you need the integer index of each item as well as its value, use the enumerated() method to iterate over the array instead. For each item in the array, the enumerated() method returns a tuple composed of an integer and the item.




回答4:


You are working with struct objects which are copied to local variable when using for in loop. Also array is a struct object, so if you want to mutate all members of the array, you have to create modified copy of original array filled by modified copies of original objects.

arrayOfMyStruct = arrayOfMyStruct.map { obj in
   var obj = obj
   obj.backgroundColor = .red
   return obj
}

It can be simplified by adding this Array extension.

Swift 4

extension Array {
    mutating func mutateEach(by transform: (inout Element) throws -> Void) rethrows {
        self = try map { el in
            var el = el
            try transform(&el)
            return el
        }
     }
}

Usage

arrayOfMyStruct.mutateEach { obj in
    obj.backgroundColor = .red
}



回答5:


I saw this method in some code and it seems to be working

for (var mutableStruct) in arrayOfMyStruct {
  mutableStruct.backgroundColor = UIColor.redColor()
}


来源:https://stackoverflow.com/questions/29777891/swift-how-to-mutate-a-struct-object-when-iterating-over-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!