【问题标题】:How to write a callback for the asynchronous function below如何为下面的异步函数编写回调
【发布时间】:2017-09-13 15:31:12
【问题描述】:

我在下面使用了一个函数。我想要来自该异步函数的数据,但如果我尝试使用 fullResolutionImageData 函数之外的数据,它会出现 nil 。所以我必须写一个回调。但我不知道如何编写回调。有人可以告诉我如何为下面的异步函数编写回调,以便我可以在其他地方访问数据。你能告诉我如何编写回调,以便我可以访问fullResolutionImageData 异步函数之外的文件。

public func fullResolutionImageData(completion: @escaping (Data?) -> ()) {
    SharedQueues.imageProcessingQueue.addOperation { [path] in
        let data = try? Data(contentsOf: URL(fileURLWithPath: path))
        DispatchQueue.main.async {
            completion(data)
        }
    }
}

在我的视图控制器中,我有一个使用此功能的操作

class ViewController: UIViewController{
    func buttonAction(sender:UIButton!){
        var photos2: [ImageSource]?
        var files : [Data] = []
        let _ = self.photos2?.map ({completion: path in
            path.fullResolutionImageData{ data in
                files.append(data) --> (prints 2)
            }
        })
        print("(files.count)") --> (prints 0 How do I write callback?)
    }
}

【问题讨论】:

  • 以这种结构方式实现您的网络服务:stackoverflow.com/a/46081822/3400991 按照此链接说明进行操作
  • 我建议在图像处理完成后使用协议/委托模式通知您的ViewController
  • 您能否进行编辑并告诉我如何执行此操作。我有点困惑。我是编码新手,还没有学到很多协议
  • @toddg 你能告诉我你在说什么
  • @Useruuu 你应该花时间详细研究异步编程。您的问题清楚地表明您缺乏问题的基础知识,因此要求回答者展示如何做一些不可能的事情。您想像访问同步函数一样访问异步函数的结果,但这不是它的工作原理。

标签: ios swift asynchronous swift3 callback


【解决方案1】:

你只需要调度组。

func buttonAction(sender:UIButton!){
        var photos2: [ImageSource]?
        var files : [Data] = []

        let myGroup = DispatchGroup()
        let _ = self.photos2?.map ({completion: path in
            myGroup.enter()
            path.fullResolutionImageData{ data in
                files.append(data) --> (prints 2)
                myGroup.leave()
            }
        })

        myGroup.notify(queue: DispatchQueue.main) { // 2
            print("(files.count)")
        }
    }

一点解释:

调度组用于监控多个异步任务的完成情况。就像在您的情况下从您在后台线程上执行的文件路径中获取数据一样。

注意事项:

进入组的每一个任务都应该离开组,无论它是否成功地实现了它的目标。如果任何进入组的任务未能退出,线程将被永远阻塞。所以请确保fullResolutionImageData 始终执行完成块!

编辑:

最后正如 David 在 cmets 中指出的那样,如果你要丢弃结果,使用 foreach 循环然后使用 map 是有意义的

因此使用

func buttonAction(sender:UIButton!){
        var photos2: [ImageSource]?
        var files : [Data] = []

        let myGroup = DispatchGroup()
        photos2?.forEach{ path in
             myGroup.enter()
             path.fullResolutionImageData{ data in
                 files.append(data) --> (prints 2)
                 myGroup.leave()
             }
        }

        myGroup.notify(queue: DispatchQueue.main) { // 2

        }
    }

【讨论】:

  • 那么我在哪里可以访问函数之外的文件计数。是否在 dispatch.notify 中
  • 我知道您刚刚从 OP 复制了该部分,但如果您要丢弃返回值,请不要使用 map。如果要保留语法,请使用 forEach
  • @useruuu :是的,先生!请仔细阅读答案。 DispatchGroup 是一个了不起的工具,只要你知道如何使用它:D
  • @dávid-pásztor : 同意 100%
  • @dávid-pásztor : 用你的建议更新了答案,并在回答中提到了你 :) 感谢指点 :)
猜你喜欢
  • 1970-01-01
  • 2011-10-17
  • 2021-12-19
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多