如何快速进行异步回调?我正在为我的应用程序编写一个小框架,因为它应该同时在iOS和OS X上运行。因此,我将非特定于设备的主要代码放入该框架中,该框架还处理对我的在线api的请求。很显然,我也希望应用程序的GUI以及ViewController在api请求完成后立即做出反应。在Objective- C中,我通过将包含必须在id变量中调用的函数以及函数本身的视图保存在选择器变量中的视图来完成此操作。然后,我使用以下代码调用了该函数:
SEL selector = callbackMethod; ((void (*)(id, SEL))[callbackViewController methodForSelector:selector])(callbackViewController, selector);
如何快速完成此任务?还是有更好的方法呢?
非常感谢您的帮助!
我已经在以下要点中共享了用于此场景的模式:https : //gist.github.com/szehnder/84b0bd6f45a7f3f99306
基本上,我创建一个单例DataProvider.swift来设置AFNetworking客户端。然后,视图控制器调用该DataProvider上的方法,每个方法都由一个闭包终止,我已将其定义为一种称为ServiceResponse的类型别名。此闭包返回字典或错误。
它使您可以非常干净地(imo)从VC调用异步数据操作,并非常清楚地指示当异步响应返回时要执行的操作。
DataProvider.swift
typealias ServiceResponse = (NSDictionary?, NSError?) -> Void class DataProvider: NSObject { var client:AFHTTPRequestOperationManager? let LOGIN_URL = "/api/v1/login" class var sharedInstance:DataProvider { struct Singleton { static let instance = DataProvider() } return Singleton.instance } func setupClientWithBaseURLString(urlString:String) { client = AFHTTPRequestOperationManager(baseURL: NSURL.URLWithString(urlString)) client!.operationQueue = NSOperationQueue.mainQueue() client!.responseSerializer = AFJSONResponseSerializer() client!.requestSerializer = AFJSONRequestSerializer() } func loginWithEmailPassword(email:String, password:String, onCompletion: ServiceResponse) -> Void { self.client!.POST(LOGIN_URL, parameters: ["email":email, "password":password] , success: {(operation:AFHTTPRequestOperation!, responseObject:AnyObject!) -> Void in self.setupClientWithBaseURLString("http://somebaseurl.com") let responseDict = responseObject as NSDictionary // Note: This is where you would serialize the nsdictionary in the responseObject into one of your own model classes (or core data classes) onCompletion(responseDict, nil) }, failure: {(operation: AFHTTPRequestOperation!, error:NSError!) -> Void in onCompletion(nil, error) }) } }
MyViewController.swift
import UIKit class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) DataProvider.sharedInstance.loginWithEmailPassword(email:"some@email.com", password:"somepassword") { (responseObject:NSDictionary?, error:NSError?) in if (error) { println("Error logging you in!") } else { println("Do something in the view controller in response to successful login!") } } } }