如何在主线程中等待异步火力基地调用(Swift)

问题描述 投票:1回答:1

背景。

我在用一个叫 KolodaView 它为Swift应用程序生成Tinder式的卡片。卡片是在 viewDidLoad() 的函数,并将其分配给我的视图控制器。我写了 viewForCardAt() 委托函数,这样每渲染一张卡,就会调用到 getPics() 做出了设置一个全局变量 imageResult: UIImageView 含有 UIImageView (注: UIViewviewForCardAt() 是实际的 UIView 会放在卡上的)。)

的问题。

getPics() 呼叫消防基地storageRef.getData()),因此是异步的。因为 viewForCardAt() 必须 返回一些东西(当它通过生成卡片时),并在主线程上运行,它不能等待或被 "通知 "当 getPics()函数完成。不能等待会导致渲染后的卡片没有图像,因为 getPics() 之前还没有完成数据的获取 viewForCardAt() 返回其 UIView.

我已经尝试过什么。

使用调度组等待,但是由于这两个调用都发生在主线程上,所以在Koloda中添加一个等待语句 viewForCardAt() 功能,甚至 getPics() 函数冻结整个应用程序。我想过用某种方式把 getPics 在另一个异步的线程中,但后来 viewForCardAt() 还得等 getPics() 竣工,因为它要到 getPics() 已 "返回其值"(将其值分配给全局引用)。

相关代码(摘要)


myViewController() {

    var imageResult: UIImageView

    override func viewDidLoad() {
        self.kolodaView.delegate = self
    }

    .
    .
    .

    func getPics() {
        grabImageDispatchGroup.enter()
        let storage = Storage.storage
        let storageRef = storage.reference(forURL: photoLink)
        //the asynch firebase call
        storageRef.getData(....) { (data, error) in
            //the actual result of the query being stored
            //for the Koloda card to use on the current card
            self.imageResult.image = UIImage(data: data)
            grabImageDispatchGroup.leave()
        }
    }

    //run for element in a specified 'user' array ("dataSource" stuff not shown for brevity) 
    func Koloda(_ koloda: KolodaView, viewForCardAt index: Int) -> UIView {

        var cardView = UIView()
        getPics()
        grabImageDispatchGroup.notify() { //this cannot work since we must return a value
            cardView.addSubview(imageResult)
            return cardView
        }

        //invalid: 'this function must return something'
    }

}

swift firebase asynchronous firebase-storage grand-central-dispatch
1个回答
1
投票

使用完成处理程序代替返回

func Koloda(_ koloda: KolodaView, viewForCardAt index: Int , completion:@escaping (UIView) -> Void )  {

    var cardView = UIView()
    getPics()
    grabImageDispatchGroup.notify() { //this cannot work since we must return a value
        cardView.addSubview(imageResult)
        return completion( cardView)
    }

    //invalid: 'this function must return something'
}
© www.soinside.com 2019 - 2024. All rights reserved.