在 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 中的转义闭包中改变自我(结构/枚举)的主要内容,如果未能解决你的问题,请参考以下文章

如何解决转义闭包捕获 Swift 中的“inout”参数?

转义闭包捕获 Swift 中的变异“self”参数错误

无法从同一类中的闭包中更改变量 [swift 3.0]

转义闭包捕获变异的“自我”参数,Firebase

错误:转义闭包捕获变异的“自我”参数

获取 JSON,附加到数组:转义闭包捕获变异的“自我”参数