【问题标题】:Variable used within its own initial value while variable is used inside a closure past init变量在其自己的初始值中使用,而变量在初始化后的闭包中使用
【发布时间】:2021-06-12 06:28:51
【问题描述】:
typealias CBType = () -> Void

class A {

    let b = B()

    func test() {
        let token = b.register { CBType in
            self.b.waitFor([token]) // ERROR: Variable used within its own initial value
        }

        b.dispatch()
    }
}

class B {
    private var _callbacks = [String:CBType]()

    func register(callback: CBType) -> String {
        let id = "1234"
        _callbacks[id] = callback
        return id
    }

    func dispatch() {
        for (_, cb) in self._callbacks {
            cb()
        }
    }

    func waitFor(tokens: [String]) {
    }
}

A().test()

当我修改测试函数以使用实例变量时,一切都恢复正常了,但语法感觉有点重。

class A {

    let b = B()
    var token: String?

    func test() {
        token = b.register { CBType in
            self.b.waitFor([self.token!])
        }

        b.dispatch()
    }
}

为什么我不能在闭包中使用局部变量,因为当闭包最终被调用时它会经过初始化?

【问题讨论】:

    标签: swift swift2


    【解决方案1】:

    常量token 在被闭包捕获时没有值。

    您可以改用可变变量,闭包将捕获变量而不是其值。

    func test() {
        var token = ""
        token = b.register {
            self.b.waitFor([token])
        }
    
        b.dispatch()
    }
    

    或者,您可以将令牌作为参数传递到闭包中:

    typealias CBType = (String) -> Void
    
    class A {
        let b = B()
    
        func test() {
            let token = b.register { theToken in
                self.b.waitFor([theToken])
            }
    
            b.dispatch()
        }
    }
    
    class B {
        private var _callbacks = [String:CBType]()
    
        func register(callback: CBType) -> String {
            let id = "1234"
            _callbacks[id] = callback
            return id
        }
    
        func dispatch() {
            for (id, cb) in self._callbacks {
                cb(id)
            }
        }
    
        func waitFor(tokens: [String]) {
            println("Wait for \(tokens)")
        }
    }
    
    A().test()
    

    【讨论】:

      【解决方案2】:

      在您的第一个示例中,当您拨打电话 self.b.waitFor([token]) 时,token 没有值。

      在您的第二个示例中,一切似乎都正常工作,因为通过像这样声明 tokenvar token: String?,它被赋予了一个初始值 (nil)。

      问题不在于您是否使用实例变量 -vs- 局部变量(或者它在闭包中使用),问题在于(在第一个示例中)您正在尝试使用 @987654326 @ 在提供其初始值的表达式中。

      相当于这样声明Intlet myValue: Int = myValue + 1 - 它的初始值应该是“what”+1?

      【讨论】:

      • 我意识到这一点,但我仍然对闭包只是一个函数指针这一事实感到困惑:在调用闭包之前不会运行函数代码。那么,如果在执行闭包代码之前没有引用相同的变量,为什么编译器会坚持初始化变量呢?
      • 编译器正在完成它的工作:) 没有可能的条件可以成功初始化token,因此错误 re: 在设置其初始值时引用自身 - 我很感激它足够聪明,给我这些错误!
      • @JohnDifool 你的预感是正确的。这里没有问题,这适用于 Haskell 等其他语言,被称为“打结”。这是一个快速的缺陷。
      猜你喜欢
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      相关资源
      最近更新 更多