Swift:asynchronouscallback

如何在swift中进行asynchronouscallback? 我正在为我的应用程序编写一个小框架,因为它应该在iOS和OS X上运行。所以我把不是特定于设备的主代码放到这个框架中,也处理对我的在线api的请求。 很显然,我也希望应用程序的GUI,因此我的ViewController一旦API请求完成反应。 在Objective-C中,我通过保存包含必须在idvariables中调用的函数的视图和select器variables中的函数本身来完成此操作。 然后我使用下面的代码调用函数:

SEL selector = callbackMethod; ((void (*)(id, SEL))[callbackViewController methodForSelector:selector])(callbackViewController, selector); 

我怎样才能做到这一点迅速? 还是有更好的方法呢?

我非常感谢你的帮助!

我已经在下面的要点中分享了我用于这个场景的模式: https : //gist.github.com/szehnder/84b0bd6f45a7f3f99306

基本上,我创build一个单独的DataProvider.swift设置一个AFNetworking客户端。 然后View控制器调用DataProvider上的方法,每个方法都被一个我定义为一个名为ServiceResponse的types别的闭包终止。 这个闭包返回一个字典或一个错误。

它允许你非常干净(imo)从VC中调用一个asynchronous数据操作,并且非常清楚地表明当asynchronous响应返回时你想要执行的操作。

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!") } } } } 

我想推荐使用块或闭包callback,而不是使用NSThread和select器。

例如,在我的API中,我有以下方法:

迅速:

下面你会发现一个更新的实现。

 func getUsers(completion: (result: NSArray?, error: NSError?)->()) { var session = NSURLSession.sharedSession() var task = session.dataTaskWithRequest(request){ (data, response, error) -> Void in if error != nil { completion(nil, error) } else { var result:NSArray = data to NSArray; completion(result, nil) } } task.resume() } 

Objective-C的:

 ... typedef void (^CBSuccessBlock)(id result); typedef void (^CBFailureBlock)(NSError *error); ... - (void)usersWithSucces:(CBSuccessBlock)success failure:(CBFailureBlock)failure { NSURLSession *session = [NSURLSession sharedSession]; [[session dataTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSArray *users = //convert data to array if(error) failure(error); else success(users); }] resume]; } 

然后,从视图控制器调用api:

 Objc: [api usersWithSucces:^(id result) { //Success callback } failure:^(NSError *error) { //Failure callback }]; Swift: api.getUsers({(result: AnyObject?, error: NSError?) -> Int in // callback here }) 

更新:

同时,我看到问题和答案仍然有用和有兴趣。 那么,这里是使用generics枚举作为结果对象的swift实现的更新版本:

 //Generic enum that represents the result enum AsyncResult<T> { case Success(T) case Failure(NSError?) } class CustomUserObject { } func getUsers(completion: (AsyncResult<[CustomUserObject]>)->()) { let request = NSURLRequest() let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(request){ (data, response, error) -> Void in if let error = error { completion(AsyncResult.Failure(error)) } else { let result: [CustomUserObject] = []//deserialization json data into array of [CustomUserObject] completion(AsyncResult.Success(result)) } } task.resume() } //Usage: getUsers { (result) in switch result { case .Success(let users): /* work with users*/ break case .Failure(let error): /* present an error */ break } } 

我刚刚做了这个小例子: Swift:asynchronouscallback块模式的例子

基本上有ClassA:

 //ClassA it's the owner of the callback, he will trigger the callback when it's the time class ClassA { //The property of that will be associated to the ClassB callback var callbackBlock : ((error : NSError?, message : String?, adress : String? ) -> Void)? init() { //Do Your staff } //Define your function with the clousure as a parameter func yourFunctionWithCallback(#functionCallbackParameter : (error : NSError?,message : String?, adress : String?) -> ()) { //Set the calback with the calback in the function parameter self.callbackBlock = functionCallbackParameter } //Later On.. func callbackTrigger() { self.callbackBlock?(error: nil,message: "Hello callback", adress: "I don't know") } } 

ClassB:

 //ClassB it's the callback reciver the callback class ClassB { @IBAction func testCallbackFunction(sender: UIButton) { let classA = ClassA() classA.yourFunctionWithCallback { (error, message, adress) -> () in //Do your stuff } } } 

ClassA:这是拥有一个属性女巫是callback块。 ClassB将通过调用yourFunctionWithCallback函数来设置此属性。 之后ClassA就准备好了,通过调用callbackTrigger函数内的callBackBlock来触发callback。

ClassB:将调用ClassA方法来设置callback块,并等待块被触发。

NSThread可以帮助你吗? :

 NSThread.detachNewThreadSelector(<#selector: Selector#>, toTarget: <#AnyObject?#>, withObject: <#AnyObject?#>)