私は現在の非同期ネットワーク要求数を把握し、進行中の要求が1つ以上ある間だけアクティビティインジケータを表示しようとしています。GCD - 総数または非同期タスクのトラッキング
fatal error: unexpectedly found nil while unwrapping an Optional value
私が原因ときそこにこの問題が発生したことを考える:私は時折dispatch_group_leave(taskGroup)
ライン上でクラッシュを取得するので、私は派遣・グループを使用していますが、私はdispatch_group_notify
のブロックと、私のclosure
ブロック間の競合状態を持っていると思いますディスパッチグループ内の項目がなくなったため、新しいグループが作成されるのではなく、それ以降のリクエストで使用される前に時間外に解放されないことがあります(nil
に設定)。その後、グループはすぐに空であることを通知し、コールバッククロージャが呼び出され、nil
に設定されますが、今すぐnil
グループから離れることを試みる余分な項目があります。
私は解決策が最後dispatch_group_leave
がすなわちcallback
閉鎖する前に、triggedされた直後にdispatch_group_leave
はそのブロックを発射を確認することにあると思います。
別のdispatch_sync
クロージャでdispatch_group_leave
とcallback
のコードをラップし、カスタムシリアルキューに追加しようとしましたが、問題はすべての実行の50%以上にとどまりました。
メインキューのdispatch_async
(後述のコードを参照)のクロージャーコールをラップすると役立ちますが、この問題はすべての実行の約10%に残ります。
Creating new dispatch group
Using existing dispatch group
Task fired with [2] second delay.
Task fired with [2] second delay.
Task with [2] second delay finished!
All done!
Task with [2] second delay finished!
Creating new dispatch group
Task fired with [2] second delay.
All done!
Task with [2] second delay finished!
そして、私はクラッシュを取得し、他の回:
Creating new dispatch group
Using existing dispatch group
Task fired with [2] second delay.
Task fired with [2] second delay.
Task with [2] second delay finished!
Using existing dispatch group
Task fired with [2] second delay.
All done!
Task with [2] second delay finished!
fatal error: unexpectedly found nil while unwrapping an Optional value
私は時々、良い結果を得る
import UIKit
import XCPlayground
// Allow for asynchronous execution to take as long as it likes
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
// Background container view
let view = UIView(frame: CGRectMake(0, 0, 100, 100))
view.backgroundColor = UIColor.blackColor()
XCPlaygroundPage.currentPage.liveView = view
// Our activity indicator
let activityIndicator = UIActivityIndicatorView()
view.addSubview(activityIndicator)
activityIndicator.center = view.center
// Used to keep track of the number of current tasks
var taskGroup: dispatch_group_t!
// An async task that calls its callback after 2 to 5 seconds
func fireATask(callback: String -> Void) {
if taskGroup == nil {
print("Creating new dispatch group")
taskGroup = dispatch_group_create()
dispatch_group_enter(taskGroup)
activityIndicator.startAnimating()
dispatch_group_notify(taskGroup, dispatch_get_main_queue()) {
activityIndicator.stopAnimating()
taskGroup = nil
print("All done!")
}
} else {
print("Using existing dispatch group")
dispatch_group_enter(taskGroup)
}
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
let delay = arc4random_uniform(1) + 2
print("Task fired with [\(delay)] second delay.")
let delayNanoseconds = Int64(UInt64(delay) * NSEC_PER_SEC)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delayNanoseconds), dispatch_get_main_queue()) {
dispatch_group_leave(taskGroup) // Sometimes crashing here because taskGroup is nil
dispatch_async(dispatch_get_main_queue()) { // My attempt to make sure dispatch_group_notify is called before the callback
callback("Task with [\(delay)] second delay finished!")
}
}
}
}
:ここ
は私のコード(テストするための遊び場にコピーペースト)です
1.なぜあなたはdispatch_group_notifyは、コールバックの前に呼び出されているかどうかを気にしていますか? 2. fireATask関数がdispatch_groupの作成を担当するのはなぜですか?永続グループを1つだけ使用できますか? – jtbandes
2)ディスパッチグループはAFAIKが一度しか使えないので、一度起動するとnilに設定して再作成します。 1)dispatch_group_notifyは最初に呼び出す必要があります。なぜなら、前回グループを離れるときには、グループを再作成してから、他のfireATask呼び出しを呼び出すコールバックを呼び出す必要があるからです(現在のグループに入ります) 。 – paulvs
2)に追加するには、このコードを使用して、アプリ内のどこからでも通話できるように、ネットワークアクティビティインジケータを一度に中央の場所で処理します。fireTaskリクエストを起動している間は、インジケータが表示されるはずですが、すべてのリクエストが終了し、それ以上は追加されていない場合、アクティビティインジケータは消えてしまいます。 – paulvs