如何等待线程块完成

时间:2014-04-16 14:10:34

标签: ios objective-c objective-c-blocks grand-central-dispatch

我在应用中遇到线程问题。这是我第一次使用AFNetworking和Parse。问题是我要调用这两个功能,他们都需要完成才能进入下一个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块的末尾),以便在这些请求的 完全完成之前不会调用它?

4 个答案:

答案 0 :(得分:0)

您可以使用Grand Central Dispatch解决此问题,更具体地说,#34; Dispatch Groups"

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

  

分组块允许聚合同步。你的申请   甚至可以提交多个块并跟踪它们是否全部完成   虽然他们可能会在不同的队列上运行。这种行为可以   在完成所有指定任务之前无法取得进展时很有帮助   已经完成了。

答案 1 :(得分:0)

这里发生了什么:

// 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

答案 2 :(得分:0)

我认为这就是你想要的......

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);
}];

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

答案 3 :(得分:0)

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

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