1

您好:我一直在编写一个 iOS 程序,它使用许多对后端 Rails 服务器的 http 查询,因此有大量如下所示的代码。在这种情况下,它正在更新UITableView

//making requests before this...
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)
{
    NSLog(@"Request sent!");

    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
    NSLog(@"Response code: %d", [httpResponse statusCode]);
    if ([data length] > 0 && error == nil){
        NSLog(@"%lu bytes of data was returned.", (unsigned long)[data length]); }
    else if ([data length] == 0 &&
             error == nil){
        NSLog(@"No data was returned.");
    }
    else if (error != nil){
        NSLog(@"Error happened = %@", error); }

    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    if (jsonObject != nil && error == nil){
        NSLog(@"Successfully deserialized...");
        if ([jsonObject isKindOfClass:[NSDictionary class]]){
            NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject;
            NSLog(@"Dersialized JSON Dictionary = %@", deserializedDictionary);
            [listOfItems addObject:deserializedDictionary];
        }
        else if ([jsonObject isKindOfClass:[NSArray class]]){
            NSArray *deserializedArray = (NSArray *)jsonObject; 
            NSLog(@"Dersialized JSON Array = %@", deserializedArray);
            [listOfItems addObjectsFromArray:deserializedArray];
        }
        else {
            /* Some other object was returned. We don't know how to deal
             with this situation as the deserializer only returns dictionaries
             or arrays */ }
    }
    else if (error != nil){
        NSLog(@"An error happened while deserializing the JSON data., Domain: %@, Code: %d", [error domain], [error code]); 
    }
    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
}];
//the place where never runs
NSLog(@"End of function.");

这是问题所在:最后一行通常在代码块之前执行。如何确保块后的代码实际上在块之后运行?

我知道该块使用其他一些线程,这就是为什么我使用performSelectorOnMainThread函数而不是直接调用[self.tableView reloadData]. 但是,如果我以后想做其他事情,我该怎么做?

另外,任何人都可以展示一些更好的方法来做到这一点吗?我正在尝试找出对后端进行大量调用的最佳方法。有几种方法可以发出异步请求,包括这种阻塞方式和另一种调用委托类的老式方式。在重构代码的过程中,我还尝试创建自己的委托类并让其他类调用它,但是很难确定回调函数针对它返回的连接数据的正确行为,尤其是对于使用多个函数的类调用不同的请求。而且我不想使用同步调用。

非常感谢任何答案。也欢迎指出代码中的任何错误。

4

1 回答 1

2

您可以使用调度组

示例代码:

- (void)doSomethingAndWait {
// synchronous method
// called in main thread is not good idea.
NSAssert(! [NSThread isMainThread], @"this method can't run in main thread.");

dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);

//making requests before this...
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)
{
    // your work here.


    dispatch_group_leave(group);
}];

// wait for block finished
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);

//will call until block is finished.
NSLog(@"End of function.");
}

要调用该方法,您需要避免在主线程中调用它。

你应该这样称呼它

dispatch_queue_t queue = dispatch_queue_create("com.COMPANYNAME.APPNAME.TASKNAME", NULL);
    dispatch_async(queue, ^{
        [self doSomethingAndWait];
    });
于 2012-07-21T10:26:17.430 回答