我有以下游乐场代码:
import UIKit
import XCPlayground
class A {
var arr : [UIImage] = []
func addItem(inout localArr: [UIImage]) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(2 * NSEC_PER_SEC)), dispatch_get_main_queue()) { () -> Void in
localArr.append(UIImage())
print("from inside function localArr: \(localArr)")
print("form inside function: \(self.arr)")
}
}
}
let a = A()
a.addItem(&a.arr)
print("instant print :\(a.arr)")
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(3 * NSEC_PER_SEC)), dispatch_get_main_queue()) { () -> Void in
print("print after delay: \(a.arr)")
}
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
输出结果为:
instant print :[]
from inside function localArr: [<UIImage: 0x7f99e8706f10>, {0, 0}]
form inside function: []
print after delay: []
我的问题是,为什么localArr
与self.arr
中的addItem
不同,而a.arr
与inout
不同?我的期望是,当我将参数作为inout
传递时,我应该能够对实际对象进行操作,而不是副本,但显然这不是发生的事情。
编辑:感谢dfri回答,我知道为什么这不起作用。 k8s.io/kubernetes/pkg/api
确实是call-by-copy-restore,请检查另一个答案here。现在,关于如何实际使闭包捕获对原始对象的引用的任何建议?或许我应该用其他技术来实现我想要的目标?
答案 0 :(得分:2)
有关inout
关键字的某些理论,请参阅以下答案:
不要依赖于copy-in copy-out之间的行为差异 并通过引用致电。
...
当函数返回时,您对原始文件的更改是 用副本的值覆盖。不要依赖 实现调用引用优化以试图保持 被覆盖的变化。
现在,您的addItem
函数将立即完成其调用,从而在函数中延迟调度之前完成inout
复制/复制输出任务。这使得在{/ 1}}参数的方法中中使用延迟调度本身就很糟糕,至少如果延迟是试图改变inout
参数的延迟。
要看到这一点,我们可以跟踪某个数组的引用(而不是跟踪值),以及它们在我们的示例运行时期间如何显示数组的变异。
inout
输出很明显:
func foo(inout bar: [Int]) {
var pBar : UnsafePointer<Int> = UnsafePointer(bar)
print("2: \(pBar)")
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(2 * NSEC_PER_SEC)), dispatch_get_main_queue()) { () -> Void in
pBar = UnsafePointer(bar)
print("3: \(pBar)")
bar[0] = 2
pBar = UnsafePointer(bar)
print("4: \(pBar)")
}
}
var a : [Int] = [1]
var pA : UnsafePointer<Int> = UnsafePointer(a)
print("1: \(pA)")
foo(&a)
print("foo call to a finished, a = \(a)")
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(5 * NSEC_PER_SEC)), dispatch_get_main_queue()) { () -> Void in
print("value of a naturally not changed here = \(a)")
pA = UnsafePointer(a)
print("5: \(pA)")
}
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
答案 1 :(得分:1)
Swift Arrays是值类型。总是复制分配。
如果要引用原始数组,请使用NSMutableArray。
那么也不需要inout
class A {
var arr : NSMutableArray = []
func addItem(localArr: NSMutableArray) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(2 * NSEC_PER_SEC)), dispatch_get_main_queue()) { () -> Void in
localArr.addObject(UIImage())
print("from inside function localArr: \(localArr)")
print("form inside function: \(self.arr)")
}
}
}
let a = A()
a.addItem(a.arr)
print("instant print :\(a.arr)")
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(3 * NSEC_PER_SEC)), dispatch_get_main_queue()) { () -> Void in
print("print after delay: \(a.arr)")
}
打印:
instant print :(
)
from inside function localArr: (
"<UIImage: 0x7ffe1872b5f0>, {0, 0}"
)
form inside function: (
"<UIImage: 0x7ffe1872b5f0>, {0, 0}"
)
print after delay: (
"<UIImage: 0x7ffe1872b5f0>, {0, 0}"
)