iOS – Swift – 返回异步检索值的函数

所以我有一个来自Parse的PFFile对象,我正在尝试创建一个函数来检索该PFFile的UIImage表示并返回它。 就像是:

func imageFromFile(file: PFFile) -> UIImage? { var image: UIImage? file.getDataInBackgroundWithBlock() { (data: NSData?, error: NSError?) -> Void in if error != nil { image = UIImage(data: data!) } } return image } 

但是,这里的问题很明显。 因为getDataInBackroundWithBlock函数是异步的,所以我每次都会得到nil。 有没有办法等到在返回图像变量之前检索到UIImage? 我不知道在这种情况下使用同步getData()是否是一种有效的方法。

是的,可以这样做。 它被称为closure ,或者更常见的是callbackcallback本质上是一个函数,可以在另一个函数中用作参数。 参数的语法是

 functionName: (arg0, arg1, arg2, ...) -> ReturnType 

ReturnType通常是Void 。 在你的情况下,你可以使用

 result: (image: UIImage?) -> Void 

调用函数的语法是一个回调函数

 function(arg0, arg1, arg2, ...){(callbackArguments) -> CallbackReturnType in //code } 

调用具有多个回调函数的语法是(缩进以使其更易于阅读)

 function( arg0, arg1, arg2, {(cb1Args) -> CB1Return in /*code*/}, {(cb2Args) -> CB2Return in /*code*/}, {(cb3Args) -> CB3Return in /*code*/} ) 

如果函数转义函数(在函数返回后调用),则必须在参数类型前添加@escaping

您将要使用在函数返回后调用并包含UIImage?的单个回调UIImage? 作为结果。

所以,你的代码可能看起来像这样

 func imageFromFile(file: PFFile, result: @escaping (image: UIImage?) -> Void){ var image: UIImage? file.getDataInBackgroundWithBlock() { (data: NSData?, error: NSError?) -> Void in //this should be 'error == nil' instead of 'error != nil'. We want //to make sure that there is no error (error == nil) before creating //the image if error == nil { image = UIImage(data: data!) result(image: image) } else{ //callback nil so the app does not pause infinitely if //the error != nil result(image: nil) } } } 

打电话给你,你可以简单地使用

 imageFromFile(myPFFile){(image: UIImage?) -> Void in //use the image that was just retrieved } 

你想要的正是承诺/未来设计模式的作用。 Swift中有很多实现。 我将以优秀的BrightFutures库为例。 ( https://github.com/Thomvis/BrightFutures

这里的代码:

 func imageFromFile(file: PFFile) -> Future { let promise = Promise() file.getDataInBackgroundWithBlock() { (data: NSData?, error: NSError?) -> Void in if error != nil { image = UIImage(data: data!) // As soon as the method completes this will be called // and triggers the future.onSuccess in the caller. promise.success(image) } else { // This would trigger future.onFailure in the caller promise.failure(error) } } return promise.future } 

说明:你基本上做的是创建一个“承诺”,即“未来”中会有结果。 在异步方法完成之前,您将立即返回此未来承诺。

这个方法的调用者会像这样处理它:

 func doSomethingWithTheImage() { let future = imageFromFile(file: pffile) future.onSuccess { image in // do something with UIImage: image } future.onFailure { error in // handle NSError: error } } 

在onSuccess处理程序中,您正在使用成功下载的图像执行所有操作。 如果在onFailure处理程序中处理错误。

这解决了返回“nil”的问题,也是处理异步进程的最佳实践之一。

我不推荐这个

我为Swift 2.0编写了一个小型库,它可以在同步和异步方法之间进行转换,这就是你所要求的。 它可以在这里找到。 请务必阅读免责声明,该免责声明说明在哪些情况下可以使用它(很可能不适用于您的情况)

你可以像这样使用它:

 func imageFromFile(file: PFFile) throws -> UIImage? { let syncGet = toSync(file.getDataInBackgroundWithBlock) let data = try syncGet() return data.map(UIImage.init) }