NSOperation中的Firebase异步回调未返回

时间:2016-09-07 01:46:55

标签: swift asynchronous firebase nsoperationqueue firebase-storage

我有一个AsyncOperation类定义为

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
  }
}

及其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

但它总是返回零。当我在ImageLoadOperation的回调中放置一个print语句时,图像就在那里,状态设置为finished。当我添加

queue.waitUntilAllOperationsAreFinished()

介于queue.addOperation并让img:UIImage? = imageLoad.load然后整个应用程序在主线程被阻止时停止。关于如何让图像在回调范围之外的任何其他想法?我也尝试过没有NSOperationQueue,只是作为一个没有运气的NSOperation。

1 个答案:

答案 0 :(得分:1)

queue.addOperation函数添加操作,并在后台线程中开始执行。因此它在后台线程完成之前很好地返回,这就是图像为零的原因。

正如文档所述,waitUntilAllOperationsAreFinished将阻止线程,直到操作完成。这在主线程上是非常不受欢迎的。

imageReference.dataWithMaxSize是一个异步操作,它有一个完成处理程序(你当前正在设置self.image)。你需要一些东西来触发运行代码才能使用imageLoad.image。如何执行此操作取决于应用程序的体系结构。

例如,如果要在UITableViewCell中显示图像,则需要将图像存储在图像数组中,可能是索引与表行匹配的位置,然后至少重新加载tableView的那一行。这是因为到接收图像时,该行可能不再存在。显然,您不希望此代码位于ImageLoadOperation类中。相反,它应作为完成处理程序传递给main()