我正在尝试插入带有inout参数的函数,以将从异步回调接收的数据追加到外部数组。但是,它不起作用。我尽一切所能找出原因-没运气。
inout
正如@AirspeedVelocity所建议的那样,我将代码重写如下,以删除不必要的依赖项。我还使用an Int作为inout参数来保持简单。 输出始终为: c before: 0 c after: 1
Int
c before: 0
c after: 1
我无法弄清楚这里出了什么问题。
func getUsers() { let u = ["bane", "LiweiZ", "rdtsc", "ssivark", "sparkzilla", "Wogef"] var a = UserData() a.userIds = u a.dataProcessor() } struct UserData { var userIds = [String]() var counter = 0 mutating func dataProcessor() -> () { println("counter: \(counter)") for uId in userIds { getOneUserApiData(uriBase + "user/" + uId + ".json", &counter) } } } func getOneUserApiData(path: String, inout c: Int) { var req = NSURLRequest(URL: NSURL(string: path)!) var config = NSURLSessionConfiguration.ephemeralSessionConfiguration() var session = NSURLSession(configuration: config) var task = session.dataTaskWithRequest(req) { (data: NSData!, res: NSURLResponse!, err: NSError!) in println("c before: \(c)") c++ println("c after: \(c)") println("thread on: \(NSThread.currentThread())") } task.resume() }
谢谢。
可悲的是,修改inout在异步回调参数是没有意义的。
从官方文件:
参数可以提供默认值以简化函数调用,并且可以作为输入-输出参数传递,参数 在函数完成执行后会 修改传递的变量。 … 输入输出参数具有一个值,该值传递给函数,由函数修改,然后从函数 传递回 以替换原始值。
参数可以提供默认值以简化函数调用,并且可以作为输入-输出参数传递,参数 在函数完成执行后会 修改传递的变量。
…
输入输出参数具有一个值,该值传递给函数,由函数修改,然后从函数 传递回 以替换原始值。
语义上,输入输出参数不是“按引用调用”,而是“按复制副本恢复”。
就您而言,counter仅在getOneUserApiData()返回时才回写,而不在dataTaskWithRequest()回调中。
counter
getOneUserApiData()
dataTaskWithRequest()
这是您的代码中发生的事情
0
c
getOneUserApiData
结果counter是未修改的:(
详细说明
通常,in-out参数是通过引用传递的,但这只是编译器优化的结果。当闭包捕获inout参数时,“传递引用”是 不安全的 ,因为编译器无法保证原始值的生存期。例如,考虑以下代码:
in-out
func foo() -> () -> Void { var i = 0 return bar(&i) } func bar(inout x:Int) -> () -> Void { return { x++ return } } let closure = foo() closure()
在此代码中,返回var i时foo()将其释放。如果x是对的引用i,x++则会导致访问冲突。为了防止出现这种竞争情况,Swift在此处采用了“按副本还原呼叫”策略。
var i
foo()
x
i
x++