【问题标题】:Using dispatch_async with self将 dispatch_async 与 self 一起使用
【发布时间】:2014-07-28 08:53:36
【问题描述】:

我在将 Objective-C 代码移植到 Swift 时遇到过几次这个问题。假设我有以下代码:

dispatch_async(dispatch_get_main_queue()) {
    self.hostViewController?.view.addSubview(self.commandField)
}

这将导致错误,在整个dispatch_async 调用下划线,提供:

Could not find member 'addSubview'

我认为这是一个尚未正确实施的错误,因为如果我将 addSubview 调用放在 dispatch_async 块之外,则项目构建良好。最初我认为这可能与在块中捕获self 有关。但是,插入 [unowned self] in 会导致相同的错误,[weak self] in 也会导致同样的错误(在插入适当的 ! 展开运算符之后)。

如何让dispatch_async 块在需要捕获self 的Swift 中工作?

【问题讨论】:

    标签: grand-central-dispatch swift


    【解决方案1】:

    您应该以非空为条件关闭此操作,而不是在您已经启动它之后对其进行测试:

    if let hostView = self.hostViewController?.view {
        DispatchQueue.main.async {
             hostView.addSubview(self.commandField)
        }
    } else {
        // handle nil hostView 
    }
    

    您永远不应该在if let 之外打开可选的包装,或者先对其进行测试。这样做也应该可以解决你的弱自我问题。

    【讨论】:

    • 啊,这行得通,谢谢!那么编译器是否抱怨它不能确定性地解开块内的hostController??还是这里发生了其他事情?
    • 这是因为表达式self.hostViewController?.view返回了一个NSView?类型的对象,不是NSView。必须始终检查可选链,并且必须允许或强制结果。
    【解决方案2】:

    dispatch_async 语法在 Swift 3 中发生了变化:

    DispatchQueue.main.async { 
        hostView.addSubview(self.commandField)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-06
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      相关资源
      最近更新 更多