2015-11-02 88 views
1

我使用库上传图像。这个库正在工作异步。异步任务后返回数据

我的功能:

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 
} 

正如你所看到的,我必须回到图片名称。但现在它总是返回空字符串,因为上传过程是异步的。如何在上传过程后返回图片名称?

回答

4

很明显,你不能返回图片的名字作为函数的结果,除非你想等待异步任务完成,等待会使它再次成为同步任务。

有三种非常普遍的方式,使异步任务取得成果:

  1. 传递任务的回调(是一个回调函数或完成块,如果你需要捕获状态或引用)。一旦任务完成,它会调用回调。在你的情况下,回调可能会将图像名称作为参数,然后回调代码需要决定如何处理它。

  2. 如果任务被封装在一个对象中,则允许该对象拥有一个委托。任务完成后,将调用委托方法。要么这个方法获取图像名称作为参数,要么可以从它委托的对象中查询图像名称(通常你会将对象本身作为参数传递给委托,这是根据Apple的惯例和良好的编码风格) 。

  3. 发送上传图像的通知。图像名称可以是通知的对象;或封装图像名称和可能的其他属性的某个对象。谁有兴趣知道何时完成上传任务可以注册该通知。

关于上述选项的一些注意事项:

我会用通知小心。虽然它们易于使用,并且非常有用,但是如果需要了解大型项目中的许多组件需要了解有关事件的信息,它们很难调试(您无法在调试器中轻松执行代码流),并且它们会创建一个非常丢失的耦合(这可能是也可能不是可取的),但与通知本身有很强的联系。如果需要,通知也不能返回值。

委托始终是一个不错的选择,但它强制用户创建一个实现委托协议的类。如果您需要的不仅仅是单一的回调方法,或者您打算非常频繁地调用委托方法,这通常只会带来好处。代表非常适合单元测试。

回调就像一个只有一个回调方法的小委托。如果您在旅途中一般会做出“随意而忘却”的任务,并且只需要一次回调,以便在成功和失败的情况下进行调用;并且它只会被调用一次,并且不需要永久回收它,然后回调通常比代理更可取。它具有委托的所有优点,但它更轻量。

+0

出色答卷。我还会提到在完成块中传递,这是近来很常见的模式,并且类似于使用回调。 –

+0

@DuncanC其实我并不是说回调只是一个函数回调。一个完成块也只是一个回调,毕竟一个块只是一个带有隐含参数的函数(它包含了所有捕获的状态,就像你写块时捕获的变量一样)。我会让答案更加明显。 – Mecki

+0

完成块的另一个优点是块的代码可以在线提供,这有助于可读性。 –

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) 
     }) 
} 
1

这是哪门子的,有望被设计为的问题。你可以实现回调,但如果你有几个处理的话,它很快就变得难以管理。

做一个大忙,并将PromiseKit导入你的代码。花半个小时来学习如何使用它。

最后你会喜欢的东西

func upload() -> Promise<String>