Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift用于输入条目作为参考_Swift_For Loop_Pass By Reference - Fatal编程技术网

Swift用于输入条目作为参考

Swift用于输入条目作为参考,swift,for-loop,pass-by-reference,Swift,For Loop,Pass By Reference,有没有一种方法可以为..生成。。在循环中,返回对集合项的引用,而不是副本的引用 假设我有一个由CGPoint对象组成的数组points,我想循环它们,并将每个点传递给一个函数adjustPoint,该函数可以使用inout参数修改该点 现在执行以下操作不起作用,因为。。in循环将点返回为不可变/可变(取决于我是否使用var)复制数组中的实际点: for var point in points { adjustPoint(point: &point) // This functi

有没有一种方法可以为..生成
。。在
循环中,返回对集合项的引用,而不是副本的引用

假设我有一个由
CGPoint
对象组成的数组
points
,我想循环它们,并将每个点传递给一个函数
adjustPoint
,该函数可以使用
inout
参数修改该点

现在执行以下操作不起作用,因为。。in循环将点返回为不可变/可变(取决于我是否使用
var
复制数组中的实际点:

for var point in points {
    adjustPoint(point: &point)  // This function only changes the copy
}
目前,我看到的唯一方法是循环索引:

for i in 0..<points.count {
    adjustPoint(point: &points[i])
}

for i in 0..因此,原始
for
循环问题的基本答案是:否。
for…in
旨在为您提供值类型的副本。正如您在评论中所说,这是一种强制函数式编程风格

要改变数组,你必须以某种方式说
array[index]
,现在你指的是原始值,可以改变它。诀窍在于找到一种能够防止常见错误的表达方式。以下是我提倡的四种技巧:

  • 将一个强大的抽象作为一个
    扩展
    ,这样你就可以在整个代码中干涸

  • 使用
    索引
    不是一个也容易出错的手动范围(
    ..
    相比)。也许您可以尝试将它们包装在一个类中。为什么不使用map?您将创建副本,但
    points=points.map{adjustPoint(point:$0)}
    就可以了。是的,我想函数式方法是下一个最好的选择,可以保持事情的整洁,但我仍然不喜欢这样一个事实,即Swift使正确使用引用变得如此烦人,相反,您拥有所有这些“一次性使用”到处都是变量副本。这可能只是个人喜好…@jjatie还有,如果我不想更新最后n个条目以外的所有条目怎么办。有没有一种方法可以使用地图来做到这一点?我认为这里对Swift数组有一个误解。你从来没有真正修改过Swift数组,就像你在修改时修改了数字4一样对数组的每一次修改都会创建一个新的数组(比如将1和4相加会创建一个新的Int)。在某些情况下,编译器可以使新的副本非常便宜(通过证明没有人能看到旧的副本,所以只需在适当的位置对旧的副本进行变异),但从逻辑上讲,而且在很多情况下,赋值后的数组与赋值前的数组是完全不同的数据结构,因此不能引用单个元素。
    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