Swift - 如何在迭代结构对象时改变它

Avn*_*arr 23 struct copy mutable swift

我仍然不确定struct copy或reference的规则.

我想在从数组迭代它时改变一个struct对象:例如在这种情况下我想改变背景颜色但是编译器对我大喊大叫

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

var arrayOfMyStruct = [MyStruct]

...

for obj in arrayOfMyStruct {
  obj.backgroundColor = UIColor.redColor() // ! get an error
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*mbo 38

struct是值类型,因此在for循环中你正在处理一个副本.

就像测试一样,你可以试试这个:

斯威夫特3:

struct Options {
   var backgroundColor = UIColor.black
}

var arrayOfMyStruct = [Options]()

for (index, _) in arrayOfMyStruct.enumerated() {
   arrayOfMyStruct[index].backgroundColor = UIColor.red
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特2:

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

var arrayOfMyStruct = [Options]()

for (index, _) in enumerate(arrayOfMyStruct) {
    arrayOfMyStruct[index].backgroundColor = UIColor.redColor() 
}
Run Code Online (Sandbox Code Playgroud)

在这里,您只需枚举索引,并直接访问存储在数组中的值.

希望这可以帮助.


eml*_*lai 14

您可以使用use Array.indices来避免忽略第二个值Array.indices:

for index in arrayOfMyStruct.indices {
    arrayOfMyStruct[index].backgroundColor = UIColor.red
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意Apple的文档中的讨论:`集合的索引属性可以对集合本身进行强有力的引用,导致集合被非唯一引用.如果在迭代索引时改变集合,强引用可能会导致集合的意外副本.要避免意外复制,请使用以startIndex开头的index(after :)方法来生成索引.来源:[https://developer.apple.com/documentation/swift/collection/1641719-indices] (3认同)
  • @Mihai Erös 评论中的链接已移至:https://developer.apple.com/documentation/swift/string/2949967-indices (3认同)

Ond*_*cek 9

您正在处理struct使用for in循环时复制到局部变量的对象。数组也是一个struct对象,所以如果你想改变数组的所有成员,你必须创建由原始对象的修改副本填充的原始数组的修改副本。

arrayOfMyStruct = arrayOfMyStruct.map { obj in
   var obj = obj
   obj.backgroundColor = .red
   return obj
}
Run Code Online (Sandbox Code Playgroud)

可以通过添加这个 Array 扩展来简化它。

斯威夫特 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
        }
     }
}
Run Code Online (Sandbox Code Playgroud)

用法

arrayOfMyStruct.mutateEach { obj in
    obj.backgroundColor = .red
}
Run Code Online (Sandbox Code Playgroud)


ldo*_*ogy 5

对于 Swift 3,请使用该enumerated()方法。

例如:

for (index, _) in arrayOfMyStruct.enumerated() {
  arrayOfMyStruct[index].backgroundColor = UIColor.redColor() 
}
Run Code Online (Sandbox Code Playgroud)

元组还包含对象的副本,因此您可以使用for (index, object)直接访问对象,但由于它是副本,您将无法以这种方式改变数组,而应该使用 来这样做index。直接引用文档

如果您需要每个项目的整数索引及其值,请使用 enumerated() 方法来迭代数组。对于数组中的每个项目, enumerated() 方法返回一个由整数和项目组成的元组。