所以我有一个来自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()是否是一种有效的方法。
答案 0 :(得分:14)
是的,可以这样做。它被称为closure
,或更常见的是callback
。 callback
本质上是一个函数,可以在另一个函数中用作参数。参数的语法是
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?
。
所以,你的代码可能看起来像这样
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
}
答案 1 :(得分:3)
您想要的正是承诺/未来设计模式的作用。 Swift中有很多实现。我将以优秀的BrightFutures库为例。 (https://github.com/Thomvis/BrightFutures)
这里是代码:
func imageFromFile(file: PFFile) -> Future<UIImage> {
let promise = Promise<UIImage>()
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
}
说明:你基本上做的是创造一个&#34;承诺&#34;在&#34;未来&#34;将会有结果。在异步方法完成之前,您将立即返回此未来承诺。
此方法的调用者将按如下方式处理:
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处理程序中处理它。
这解决了返回&#34; nil&#34;并且也是处理异步过程的最佳实践之一。
答案 2 :(得分:1)
我不推荐这个
我为Swift 2.0编写了一个小型库,它可以在同步和异步方法之间进行转换,这就是你要求的。它可以找到here。请务必阅读免责声明,该声明解释了在哪些情况下可以使用它(很可能不适用于您的情况)
您可以像这样使用它:
func imageFromFile(file: PFFile) throws -> UIImage? {
let syncGet = toSync(file.getDataInBackgroundWithBlock)
let data = try syncGet()
return data.map(UIImage.init)
}