2016-04-17 15 views
0

でネットワークコールを行う複数のNSOperationを連鎖して、すべて完了するまで待つ必要があります。NSOperationQueue内のNSOperationの非同期コールバックが呼び出されることはありません

NSOperationをすべてNSOperationQueueに追加してから、operationQueue.waitUntilAllOperationsAreFinished()に電話してください。これは動作しますが、操作の状態を「完了」に設定したコールバックは、NSOperationsのコールバックとして無期限に待機し、決して呼び出されません。

私は、次のNSOperationサブクラスを使用しています:

class ConcurrentOperation: NSOperation 
{ 
    enum State: String 
    { 
     case Ready, Executing, Finished 

     private var keyPath: String 
     { 
      return "is" + self.rawValue 
     } 
    } 

    var state: State = State.Ready { 
     willSet (newValue) 
     { 
      self.willChangeValueForKey(newValue.keyPath) 
      self.willChangeValueForKey(self.state.keyPath) 
     } 

     didSet 
     { 
      self.didChangeValueForKey(oldValue.keyPath) 
      self.didChangeValueForKey(self.state.keyPath) 
     } 
    } 
} 

extension ConcurrentOperation 
{ 
    override var ready: Bool { 
     return super.ready && self.state == .Ready 
    } 

    override var executing: Bool { 
     return self.state == .Executing 
    } 

    override var finished: Bool { 
     return self.state == .Finished 
    } 

    override var concurrent: Bool { 
     return true 
    } 

    override var asynchronous: Bool { 
     return true 
    } 
} 

extension ConcurrentOperation 
{ 
    override func start() 
    { 
     if self.cancelled 
     { 
      self.state = .Finished 
      return 
     } 

     self.state = .Executing 
     self.main() 
    } 

    override func cancel() 
    { 
     self.state = .Finished 
    } 
} 

これはRaywenderlichチュートリアルとhttps://gist.github.com/calebd/93fa347397cec5f88233に基づいています。

ConcurrentOperationサブクラスのmain()メソッドが.Finishedに状態を設定した場合にのみ、それが完了したことをNSOperationQueueに伝えます。 これは操作によっても実現されます。

しかし、私は、このようなConcurrentOperationサブクラスでは、次のmain()の方法を構築した場合非同期部分が呼び出されることはありませんよう、NSOperationQueueが停止することはありません:

override func main() 
{ 
    dispatch_async(dispatch_get_main_queue(), { 
     sleep(1) 
     self.state = .Finished // never called! 
    }) 
} 

問題は同じですFirebase-Query私のアプリで使用するコールバック。

concurrent: Boolプロパティを無効にして、trueを返そうとしましたが、それでもどちらも修正されません。

非同期タスクは、実際に私のConcurrentOperationサブクラスの 'main()メソッドで実行されますか?

ありがとうございました!

+0

メインキューで 'waitUntilAllOperationsAreFinished'を呼び出していますか?その場合、メインキューをブロックし、 'dispatch_async(dispatch_get_main_queue()...')コードでは – Paulw11

+0

を実行する機会がありません。私が 'dispatch_async(_、_) 'ブロック、それはメインキューをブロックしました。あなたは素晴らしいです!ありがとう!私の質問に定期的な答えを書くなら、私はそれを正しいとマークします。 – florianpfisterer

答えて

1

waitUntilAllOperationsAreFinishedをメインキューで呼び出すと、メインキューがブロックされます。メインキューがブロックされると、デッドロックを作成したときにdispatch_async(dispatch_get_main_queue(),を実行することはできません。メインキューをブロック解除するために実行する必要のあるタスクは、ブロックされたメインキューにディスパッチされているため、決して実行されず、決して実行できません。

waitUntilAllOperationsAreFinishedを独自のキューにディスパッチする必要があります。

関連する問題