在 Swift 3.0 中的转义闭包中改变自我(结构/枚举)
Posted
技术标签:
【中文标题】在 Swift 3.0 中的转义闭包中改变自我(结构/枚举)【英文标题】:Mutating self (struct/enum) inside escaping closure in Swift 3.0 【发布时间】:2016-09-26 12:34:54 【问题描述】:在 swift 2.2 中,我们可以在闭包内改变结构或枚举,当它位于变异函数内时。但在 swift 3.0 中,它不再可能。我收到以下错误
闭包不能隐式捕获变异的自我参数
这是一个代码sn-p,
struct Point
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double)
x += deltaX
y += deltaY
test (a) -> Void in
// Get the Error in the below line.
self.x = Double(a)
mutating func test(myClosure: @escaping (_ a: Double) -> Void)
myClosure(3)
我知道值类型不应该是可变的。在某些情况下,当我收到 API 响应时,我必须在其中一个函数内修改结构中的一个变量。 (在完成闭包中)
我在 swift 2.2 中所做的事情是不可能的,还是有办法做到这一点?
【问题讨论】:
删除@escaping
...你为什么有它?
@MartinR 它正在逃逸,因为它的 Alamofire 完成关闭。
这可能解释了它:github.com/apple/swift-evolution/blob/master/proposals/….
相关问题:***.com/questions/37043070/…、***.com/questions/38058280/…。
是的,我看过提案。看来已经不可能了。 @MartinR 那么我在这里使用课程的唯一可能方式是什么?
【参考方案1】:
问题在于@escaping 闭包可以存储起来供以后执行:
Escaping Closures
当闭包作为参数传递给函数时,闭包被称为转义函数,但在函数返回后被调用。 ...
闭包可以逃逸的一种方法是将其存储在函数外部定义的变量中......
由于闭包可以在函数范围之外存储和存在,闭包(self)内部的结构/枚举将被复制(它是一个值)作为闭包的参数。而且,如果允许它发生变异,闭包可能会有它的旧副本,从而导致不需要的结果。
因此,在回答您的问题时,您不能;除非您能够删除“@escaping”(不是您的情况,因为它是第 3 方 API)
【讨论】:
【参考方案2】:是的,你可以这样做。
struct Point
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double)
x += deltaX
y += deltaY
test (a) -> Void in
self.x = Double(a)
mutating func test(myClosure: (_ a: Double) -> Void)
myClosure(3)
【讨论】:
删除@escaping
是一种方法,但在异步调用的情况下,您不能只删除@escaping
。所以这不是这个问题的有效选项。【参考方案3】:
结构是值类型。所以当用作 Model 或 ModelView 时,你可以用新的 Value 给 VC 组成一个闭包。
struct Point
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double)
x += deltaX
y += deltaY
test [x, y](a) -> Point in
// Get the Error in the below line.
return Point(x: Double(a), y: y)
mutating func test(myClosure: @escaping (_ a: Double) -> Point)
self = myClosure(3)
【讨论】:
您刚刚被移动了一些东西,但还没有解决self
无法从 within 转义闭包中解决的核心问题。想一想:如果在myClosure(3)
中,3
来自异步调用怎么办。您的结构将如何处理?底线:您的解决方案不适用于异步调用。以上是关于在 Swift 3.0 中的转义闭包中改变自我(结构/枚举)的主要内容,如果未能解决你的问题,请参考以下文章