如何等待线程块完成

我在我的应用程序中遇到线程问题。 这是我第一次使用AFNetworking和Parse。 问题是我调用这两个function,他们都需要完成才能进入下一个segue。

这是我的代码。 第一个块用于使用AFHTTP的网络请求,第二个块用于解析请求。

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSDictionary *parameters = @{@"foo": @"bar"}; [manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"JSON: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; PFQuery *query = [PFQuery queryWithClassName:@"dependant"]; [query whereKey:@"parentID" equalTo:[masterAccount getObjectID]]; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { for (PFObject *dependant in objects) { //do some stuff with parse object here } [self performSegueWithIdentifier: @"MySegue" sender: self]; }]; 

据我所知,这两个都是在自己的线程中创建和运行,以便不阻止gui,这是正确的吗? 我将在何处移动segue调用(当前位于Parse块的末尾),以便在这两个请求完全完成之前不会调用它?

您可以使用Grand Central Dispatch解决此问题,更具体地说是“Dispatch Groups”

https://developer.apple.com/library/mac/documentation/performance/reference/gcd_libdispatch_ref/Reference/reference.html

分组块允许聚合同步。 您的应用程序可以提交多个块并跟踪它们是否完成,即使它们可能在不同的队列上运行。 在完成所有指定任务之前无法进行此操作时,此行为很有用。

这是发生了什么:

 // Runs 1st AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSDictionary *parameters = @{@"foo": @"bar"}; [manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { // Runs 3rd NSLog(@"JSON: %@", responseObject); // Run your code here, or trigger your code here PFQuery *query = [PFQuery queryWithClassName:@"dependant"]; [query whereKey:@"parentID" equalTo:[masterAccount getObjectID]]; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { for (PFObject *dependant in objects) { //do some stuff with parse object here } [self performSegueWithIdentifier: @"MySegue" sender: self]; }]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; // Runs 2nd 

我想这就是你想要的……

 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSDictionary *parameters = @{@"foo": @"bar"}; __weak __typeof(self) weakSelf = self; [manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"JSON: %@", responseObject); PFQuery *query = [PFQuery queryWithClassName:@"dependant"]; [query whereKey:@"parentID" equalTo:[masterAccount getObjectID]]; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { __strong __typeof(self) strongSelf = weakSelf; for (PFObject *dependant in objects) { //do some stuff with parse object here } [strongSelf performSegueWithIdentifier: @"MySegue" sender: self]; }]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; 

此代码按顺序运行每个异步请求,这是最简单的方法。

一个简单的方法是使用一个单独的对象,比如ResourceState。 给它两个属性,一个用于gotJsonData,一个用于gotParseData。 在完成处理程序中,只需在ResourceState中调用一个方法,该方法更新相应的属性(json或parse),如果两个属性都设置为success,则触发segue。 我不会尝试做一个块内块方法 – 它的代码较少,但可以使代码难以维护。

你在这里遇到的根本问题是你需要在’model’和’view controller’之间进行清晰的分离。 我通常的工作方式是让模型完成所有工作,包括网络请求,当它知道需要UI端更新时,它会发送一个NSNotification,主线程上的UI会监听,然后更新UI。