Получение данных с помощью dispatch_sync в UITabViewController - PullRequest
0 голосов
/ 14 февраля 2012

Я пишу приложение, которое использует UITabBarController для переключения представлений. Одна вкладка выполняет веб-запрос для сбора и обработки данных JSON перед заполнением UITableView. Я пытаюсь загрузить эти данные в фоновом режиме, поэтому, когда пользователь нажимает на вкладку, нет задержки в представлении таблицы. ActivityIndicator будет отображаться, а затем таблица загружается с данными.

Каждый запрос выполняется, обрабатывается и результаты помещаются в NSMutableArray, который затем сортируется и добавляется в UITableView.

Когда я использую dispatch_sync, данные загружаются, и массив создается и отображается нормально, однако пользовательский интерфейс для представления заблокирован от загрузки. Я думаю, потому что по какой-то причине я не получаю этот запрос в фоновую очередь. Если я использую dispatch_async, я получаю исключения, когда делаю попытку доступа к NSMutableArray в основном потоке.

Итак, мой вопрос в том, что является правильным шаблоном, позволяющим пользователю переключиться на вкладку, которая содержит этот TableView, представить ActivityIndicator, пока данные загружаются и обрабатываются (в фоновом режиме), а затем после завершения UITableView загружается с обработанными данными.

Relavent код из 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 голосов
/ 14 февраля 2012

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, вероятно, лучше всего подходит для загрузки по сети, он будет работать достаточно хорошо Специально для небольших запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...