web-dev-qa-db-ja.com

selfでdispatch_asyncを使用する

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ブロックをSwiftでキャプチャする必要があるselfで動作させるにはどうすればよいですか?

42
Ephemera

このアクションを無効ではない状態でスピンオフするように条件を設定する必要があります。すでに開始した後でテストする必要はありません。

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

if letの外側でオプションをアンラップしたり、最初にテストしたりしないでください。これを行うと、ヤーの弱い自己問題も解決するはずです。

65
iluvcapra

dispatch_async構文は、Swift 3:

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