使用UITabViewController中的dispatch_sync检索数据

时间:2012-02-14 02:39:08

标签: objective-c xcode uitableview grand-central-dispatch uitabview

我正在编写一个利用UITabBarController切换视图的应用程序。在填充UITableView之前,一个选项卡会生成Web请求以收集然后处理JSON数据。我试图在后台加载这些数据,所以当用户按下选项卡时,表格没有延迟。 ActivityIndi​​cator将显示,然后表格将加载数据。

生成,处理每个请求并将结果放在NSMutableArray中,然后对其进行排序并添加到UITableView。

当我使用dispatch_sync时,会加载数据并创建数组并使其显示正常,但是阻止加载视图的UI。我在想因为某些原因我没有把这个查询带到后台队列。如果我使用dispatch_async,则在尝试访问主线程上的NSMutableArray时会出现异常。

所以,我的问题是允许用户切换到包含此TableView的选项卡的正确模式是什么,在数据加载和处理(在后台)时呈现ActivityIndi​​cator然后一旦完成,就会加载UITableView处理过的数据。

来自UITableViewController的相关代码:

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

- (void)viewDidLoad
{
    [super viewDidLoad];

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    currentLat = appDelegate.currentLatitude;
    currentLong = appDelegate.currentLongitude;

    finalDistanceArray = [[NSMutableArray alloc] init];

    [self compareLocationMMC];
    [self compareLocationLVMC];
    [self compareLocationSBCH];
    [self compareLocationGVCH];
    [self compareLocationSYVCH];

    NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES];

    [hospitalList sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]];  

}

- (void)compareLocationMMC {


NSString * searchURL = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=true", currentLat.floatValue, currentLong.floatValue, MMC_LAT, MMC_LON];
NSURL * myURL = [NSURL URLWithString:searchURL];

dispatch_sync(kBgQueue, ^{
    NSData* data = [NSData dataWithContentsOfURL: 
                    myURL];
     [self performSelectorOnMainThread:@selector(fetchedData:) 
                          withObject:data waitUntilDone:YES];
});


}
//The compareLocationXXX method is repeated 4 more times with different search strings

- (void)fetchedData:(NSData *)responseData {

//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization 
                      JSONObjectWithData:responseData 

                      options:kNilOptions 
                      error:&error];

NSArray* stationDistance = [json objectForKey:@"routes"]; 

NSDictionary* legs = [stationDistance objectAtIndex:0];

NSArray* legsBetween = [legs objectForKey:@"legs"];

NSDictionary* distanceBetween = [legsBetween objectAtIndex:0];

finalDistance = [distanceBetween valueForKeyPath:@"distance.text"];

[finalDistanceArray addObject:finalDistance];

}

1 个答案:

答案 0 :(得分:0)

事实上,

Dispatch_sync()将阻止它被调用的线程,因为它会暂停执行以将块排入队列。 Dispatch_async是一个更好的选择,因为它允许调用函数恢复。您可以将一个调用包装在另一个调用中,以允许您在主线程上执行完成代码。这也使代码执行非常容易阅读。

// Turn on status bar spinner, for example
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    // Do background stuff here
        ....
    NSData* data = [NSData dataWithContentsOfURL:myURL];
    // used parsed data to populate data structure of some type
        ....
    dispatch_async(dispatch_get_main_queue(), ^{
        // Use background stuff here
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    });
});

虽然基于回调的API(如NSURLConnection)可能最适合网络加载,但这样做效果会相当不错。特别是对于小额请求。