我使用图书馆上传图片。这个库正在异步工作。
我的功能:
func upload() -> String {
let imageData:NSData = UIImageJPEGRepresentation(pureImage!, 100)!
var picture=""
SRWebClient.POST("http://domain.com/upload.php")
.data(imageData, fieldName:"image_field", data: ["username":"test","key":"test"])
.send({(response:AnyObject!, status:Int) -> Void in
if status == 200 {
let responseJSON = response! as! Dictionary<String, AnyObject>
let s_status=responseJSON["status"] as! Int
if s_status == 1 {
picture=responseJSON["picture"] as! String
print(picture)
}
}
},failure:{(error:NSError!) -> Void in
picture=""
})
return picture
}
如您所见,我必须返回图片名称。但现在它总是返回空字符串,因为上传过程是异步的。如何在上传过程后返回图片名称?
答案 0 :(得分:4)
显然你不能将图片名称作为函数结果返回,除非你想等到异步任务完成并等待再次使它成为同步任务。
有三种非常常见的方法可以使异步任务提供结果:
将任务传递给回调(如果需要捕获状态或引用,则为回调函数或完成块)。任务完成后,它会调用回调。在您的情况下,回调可以将图像名称作为参数,然后回调代码需要决定如何处理它。
如果任务封装在对象中,则允许该对象拥有委托。任务完成后,将调用委托方法。方法可以将图像名称作为参数获取,也可以从它所委托的对象中查询图像名称(通常您将对象本身作为参数传递给委托,这是常见做法和良好的编码风格,根据苹果)。
发送上传图片的通知。图像名称可以是通知的对象;或一些封装图像名称和可能的其他属性的对象。有兴趣知道上传任务何时完成的人可以注册该通知。
有关上述选项的一些注意事项:
我小心使用通知。虽然它们易于使用且非常有用,但是如果很多组件分布在一个巨大的项目中需要了解事件,那么它们很难调试(您无法在调试器中轻松地遵循代码流)并且它们会造成很大的失败耦合(这可能是也可能不是可取的),但与通知本身的强烈耦合。此外,如果需要,通知也不能返回值。
委托总是一个很好的选择,但它会强制用户创建一个实现委托协议的类。如果您需要的不仅仅是一个回调方法,或者您计划非常频繁地调用委托方法,这通常只会得到回报。代表们非常适合进行单元测试。
回调就像一个只有一个回调方法的小代理。如果你经常发生火灾并忘记&#34;在旅途中的任务,只有一个回调需要在成功和失败的情况下被调用;它只会被调用一次而且不需要再循环它,然后回调通常比委托更好。它具有委托的所有优点,但它更轻量级。
答案 1 :(得分:1)
这是Promises的设计问题。您可以实现回调,但如果您有多个要处理的话,它很快就会变得无法管理。
帮自己一个大忙,并将PromiseKit导入您的代码中。花半小时来学习如何使用它。
你最终会得到像
这样的东西 func upload() -> Promise<String>
答案 2 :(得分:0)
您可以使用块来接听回电
func upload(completionHandler : (pictureName : NSString?)-> Void){
let imageData:NSData = UIImageJPEGRepresentation(pureImage!, 100)!
var picture=""
SRWebClient.POST("http://domain.com/upload.php")
.data(imageData, fieldName:"image_field", data: ["username":"test","key":"test"])
.send({(response:AnyObject!, status:Int) -> Void in
if status == 200 {
let responseJSON = response! as! Dictionary<String, AnyObject>
let s_status=responseJSON["status"] as! Int
if s_status == 1 {
picture=responseJSON["picture"] as! String
print(picture)
completionHandler(pictureName: picture)
}
}
},failure:{(error:NSError!) -> Void in
picture=""
completionHandler(pictureName: nil)
})
}