0

は、私はそのようなFirebase非同期コールバックNSOperationに戻っていない

import Foundation 

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

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

    var state = State.Ready { 
     willSet { 
      willChangeValueForKey(newValue.keyPath) 
      willChangeValueForKey(state.keyPath) 
     } 
     didSet { 
      didChangeValueForKey(oldValue.keyPath) 
      didChangeValueForKey(state.keyPath) 
     } 
    } 

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

    override var executing: Bool { 
     return super.ready && state == .Executing 
    } 

    override var finished: Bool { 
     return super.ready && state == .Finished 
    } 

    override var asynchronous: Bool { 
     return true 
    } 

    override func start() { 
     if cancelled { 
      state = .Finished 
      return 
     } 
     main() 
     state = .Executing 
    } 

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

として定義AsyncOperationクラスとそれImageLoadOperationのサブクラスを持っています。

import Foundation 
import UIKit 
import Firebase 

class ImageLoadOperation: ASyncOperation { 
    var imagePath: String? 
    var image: UIImage? 

    override func main(){ 
     let storage = FIRStorage.storage() 
     let storageRef = storage.referenceForURL("gs://salisbury-zoo- 91751.appspot.com") 
     if let path = imagePath { 
      let imageReference = storageRef.child(path) 
      imageReference.dataWithMaxSize(3 * 1024 * 1024) { (data, error) -> Void in 
      if (error != nil) { 
       self.image = nil 
      } else { 
       self.image = UIImage(data: data!) 
       self.state = .Finished 
      } 
     } 
    } 
    } 
} 

だから私は、キュー

let queue = NSOperationQueue() 
    let imageLoad = ImageLoadOperation() 
    queue.addOperation(imageLoad) 

    let img:UIImage? = imageLoad.image 

で操作を呼び出すために行く。しかし、それは常にnilを返します。 ImageLoadOperationのコールバックにprintステートメントを置くと、イメージはそこにあり、stateはfinishedに設定されます。私が追加したとき

queue.waitUntilAllOperationsAreFinished() 

Incoming queue.addOperationとlet img:UIImage? = imageLoad.loadメインスレッドがブロックされると、アプリケーション全体が停止します。私がイメージをコールバックの範囲外に置く方法に関する他のアイデア?私はまた、NSOperationQueueなしでそれをやってみましたが、運がないNSOperationと同じようにしました。

答えて

1

queue.addOperation関数が演算を追加し、バックグラウンドスレッドで実行を開始します。したがって、バックグラウンドスレッドが終了する前に戻ります。そのため、画像はゼロです。

ドキュメントが示すように、waitUntilAllOperationsAreFinishedは操作が完了するまでスレッドをブロックします。これは、メインスレッドでは非常に望ましくありません。

imageReference.dataWithMaxSizeは、完了ハンドラ(現在はself.imageを設定している)を持つ非同期操作です。 imageLoad.imageを使用できるようにコードを実行するには、そこに何かが必要です。これを行う方法は、あなたのアプリのアーキテクチャに依存します。

たとえば、画像をUITableViewCellで表示する場合は、イメージがインデックスのテーブル行に一致するイメージの配列に格納してから、少なくともtableViewのその行を再読み込みする必要があります。これは、画像が受信されるまでに、その行にセルが存在しなくなるためです。明らかに、あなたはこのコードをあなたのImageLoadOperationクラスの中に置いてはいけません。代わりに、完了ハンドラとしてmain()に渡す必要があります。

+0

だから、ここでの概要はhttp://stackoverflow.com/questions/36675986/asynchronous-callback-in-nsoperation-inside-of-nsoperationqueue-is-never-calledです。私の次の質問は、 'imageReference.dataWithMaxSize'をメインスレッドではなくキュースレッドで実行する方法です。私自身のキューに入っていて、非同期関数がメインスレッド上で動作してデッドロックが発生しているように見えます。非同期関数をキュースレッド上で実行するべきではありませんか? – Spothedog1

関連する問題