【问题标题】:Firebase Async Callback in NSOperation not returningNSOperation 中的 Firebase 异步回调未返回
【发布时间】:2017-01-14 13:35:18
【问题描述】:

我有一个这样定义的 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

但它总是返回 nil。当我在 ImageLoadOperation 的回调中放置一个打印语句时,图像就在那里并且状态设置为完成。当我添加

queue.waitUntilAllOperationsAreFinished()

在 queue.addOperation 和 let img:UIImage 之间? = imageLoad.load 然后整个应用程序停止,因为主线程被阻塞。关于如何让图像出现在回调范围之外的任何其他想法?我也试过在没有 NSOperationQueue 的情况下这样做,就像没有运气的 NSOperation 一样。

【问题讨论】:

    标签: swift asynchronous firebase nsoperationqueue firebase-storage


    【解决方案1】:

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

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

    imageReference.dataWithMaxSize 是一个具有完成处理程序的异步操作(您当前正在设置self.image)。你需要一些东西来触发代码运行,这将允许你使用imageLoad.image。你如何做到这一点将取决于你的应用程序的架构。

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

    【讨论】:

    • 所以这个问题在stackoverflow.com/questions/36675986/… 中列出。我的下一个问题是我如何让imageReference.dataWithMaxSize 在队列线程而不是主线程中运行?似乎即使我在自己的队列中并且操作异步函数在创建死锁的主线程上运行。异步函数不应该在队列线程上运行吗?
    猜你喜欢
    • 2014-10-29
    • 2023-03-19
    • 1970-01-01
    • 2022-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    相关资源
    最近更新 更多