私のアプリには、NSRURLSessionを作成してNSURLRequestを送信する関数があります。
sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error)
このタスクの完了ブロックでは、呼び出し側のViewControllerにUIImageを追加する計算をする必要があります。という関数があります
func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
それはUIImageを追加する計算をします。補完ブロック内でビュー追加コードを実行しようとすると、Xcodeは、バックグラウンド処理中はレイアウトエンジンを使用できないというエラーをスローします。そのため、SOにメインスレッドのメソッドをキューに入れようとするコードが見つかりました。
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_MSEC)))
dispatch_after(time, dispatch_get_main_queue(), {
let returned = UIApplication.sharedApplication().sendAction("displayQRCode:", to: self.delegate, from: self, forEvent: nil)
})
しかし、この関数呼び出しにパラメータ "receiveAddr"と "amountBTC"を追加する方法がわかりません。これをどのように行うのでしょうか。それともアプリケーションのメインキューにメソッド呼び出しを追加するための最適な方法を誰かが提案することができますか?
これをcompletion handler
に書くだけです。dispatch_after
を使う必要はありません。
dispatch_async(dispatch_get_main_queue(), {
let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
delegateObj.addUIImage("yourstring")
})
Swift 3/4:
DispatchQueue.main.async {
let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
delegateObj.addUIImage("yourstring")
}
メインキューでのディスパッチ後も
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// your code here
}
YourAppDelegateClass
をあなたがデリゲートクラスに置き換えます
Swift 3とSwift 4のバージョン
DispatchQueue.main.async {
print("Hello")
}
Swift3とXCode 9.2:
dispatch_async_on_main_queue {
//Your code
print("Hello")
}
スイフト2
トレーリングクロージャを使用すると、これは次のようになります。
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
Trailing ClosuresはSwiftの構文糖衣で、関数パラメータのスコープ外でクロージャを定義することを可能にします。詳細については、Swift 2.2 Programming Language Guideの 末尾のクロージャ を参照してください。
Dispatch_asyncの場合、dispatch_block_t
は() -> Void
の型の別名であるためAPIはfunc dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t)
です。戻り値を持たない0個のパラメーターを持つクロージャー、およびblockを関数の最後のパラメーターにすることで、dispatch_async
の外部スコープでクロージャーを定義できます。
これは他の答えと同じ結果を達成するためのより良い(IMO)Swifty/Cocoaスタイルの構文です。
NSOperationQueue.mainQueue().addOperationWithBlock({
// Your code here
})
あるいは、より少ないコードとより多くの機能のために、人気のある Async Swiftライブラリ を入手することもできます。
Async.main {
// Your code here
}
メインスレッドでcollectionViewをリロード
DispatchQueue.main.async {
self.collectionView.reloadData()
}
これを行う適切な方法は、次のコードで行ったように、main_queueでdispatch_asyncを使用することです。
dispatch_async(dispatch_get_main_queue(), {
(self.delegate as TBGQRCodeViewController).displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
})
これは、より良い構文のために追加できる、ちょっとしたグローバル関数です。
func dispatch_on_main(block: dispatch_block_t) {
dispatch_async(dispatch_get_main_queue(), block)
}
そして使い方
dispatch_on_main {
// Do some UI stuff
}
//Perform some task and update UI immediately.
DispatchQueue.global(qos: .userInitiated).async {
// Call your function here
DispatchQueue.main.async {
// Update UI
self.tableView.reloadData()
}
}
//To call or execute function after some time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}
//If you want to do changes in UI use this
DispatchQueue.main.async(execute: {
//Update UI
self.tableView.reloadData()
})
あなたがクロージャーの中で自分自身を使っているなら、自分自身を弱めることを忘れないでください。
dispatch_async(dispatch_get_main_queue(),{ [weak self] () -> () in
if let strongSelf = self {
self?.doSomething()
}
})