Kei*_*wan 3 for-loop pass-by-reference swift
有没有办法让for .. in循环返回对集合条目的引用而不是副本?
假设我有一个对象数组points,CGPoint我想循环它们并将每个点传递给一个adjustPoint可以使用inout参数修改点的函数.
现在执行以下操作不起作用,因为for .. in循环将点返回为不可变/可变(取决于我是否使用var)数组中实际点的副本:
for var point in points {
adjustPoint(point: &point) // This function only changes the copy
}
Run Code Online (Sandbox Code Playgroud)
目前,我认为这样做的唯一方法是遍历索引:
for i in 0..<points.count {
adjustPoint(point: &points[i])
}
Run Code Online (Sandbox Code Playgroud)
这真的是唯一的方式,还是for .. in循环可能?
注意:我已经阅读了很久以前的这个问题(我相信Swift 1)所以我想也许他们在此期间改变了一些东西:将循环局部变量转换为可变变量
因此,原始for循环问题的基本答案是:不.本for...in是为了给你值类型的副本.正如你在评论中所说的那样,这是一种强制功能的编程风格.
要改变一个数组,你必须array[index]以某种方式说出来,现在你指的是原始值,并且可以改变它.诀窍是找到一种可以防止常见错误的表达方式.我在下面提倡的四种技术是:
extension让你在整个代码中干掉indices不要使用也容易出错的手动范围(...vs. ..<)&(参见#1)这可能最符合Swift的精神,即古怪,冗长,比你想要的更麻烦,但最终具有适当的层次,非常富有表现力和强大:
import Foundation
import CoreGraphics
protocol Pointy {
var x: CGFloat { get set }
var y: CGFloat { get set }
func adjustBy(amount: CGFloat) -> CGPoint
mutating func adjustInPlace(amount: CGFloat) -> Void
}
extension CGPoint: Pointy {
func adjustBy(amount: CGFloat) -> CGPoint {
return CGPoint(x: self.x + amount, y: self.y + amount)
}
mutating func adjustInPlace(amount: CGFloat) -> Void {
x += amount
y += amount
}
}
extension Array where Element: Pointy {
func adjustBy(amount: CGFloat) -> Array<Pointy> {
return self.map { $0.adjustBy(amount: amount) }
}
mutating func adjustInPlace(amount: CGFloat) {
for index in self.indices {
// mysterious chunk of type calculus: need "as! Element" -- https://forums.developer.apple.com/thread/62164
self[index].adjustInPlace(amount: amount) // or self[index] = (self[index].adjustBy(amount: amount)) as! Element
}
}
}
// Hide the above in a Util.swift that noone ever sees.
// AND NOW the true power shows
var points = [ CGPoint(x: 3.0, y: 4.0) ]
points.adjustInPlace(amount: 7.5)
points.forEach { print($0) }
// outputs (10.5, 11.5)
let adjustedPoints = points.adjustBy(amount: 7.5) // Original unchanged
Run Code Online (Sandbox Code Playgroud)