0

UITabBarController를 사용하여보기를 전환하는 앱을 작성하고 있습니다. 하나의 탭은 UITableView를 채우기 전에 JSON 데이터를 수집하고 처리하기위한 웹 요청을합니다. 백그라운드에서이 데이터를로드하려고 시도하므로 사용자가 탭을 누르면 테이블을 표시 할 때 지연이 없습니다. ActivityIndicator가 표시되고 테이블에 데이터가로드됩니다.UITabViewController에서 dispatch_sync를 사용하여 데이터 가져 오기

각 요청이 만들어지고 처리되며 NSMutableArray에 결과가 정렬 된 다음 정렬되어 UITableView에 추가됩니다.

dispatch_sync를 사용하면 데이터가로드되고 배열이 생성되어 잘 표시되지만 뷰의 UI로드가 차단됩니다. 어떤 이유로 배경 쿼리에이 쿼리가 나타나지 않기 때문에 생각하고 있습니다. dispatch_async를 사용하면 주 스레드의 NSMutableArray에 액세스하려고 시도 할 때 예외가 발생합니다.

내 질문은 사용자가이 TableView를 포함하는 탭으로 전환하고 데이터가로드되고 처리되는 동안 (백그라운드에서) ActivityIndicator를 제시 한 다음 한 번 완료되면 UITableView가 처리 된 데이터가로드됩니다. 있는 UITableViewController에서

Relavent 코드 :

#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]; 

} 

답변

0

Dispatch_sync() 사실이이 블록을 대기열에 실행을 중단 이후부터라고 스레드를 차단합니다. Dispatch_async은 호출 기능을 다시 시작할 수 있으므로 훨씬 더 나은 선택입니다. 하나의 호출을 다른 호출로 랩핑하여 주 스레드에서 완료 코드를 실행할 수 있습니다. 또한 코드 실행을 매우 쉽게 읽을 수 있습니다. NSURLConnection 같은 콜백 기반의 API가 네트워크 로딩 아마 최고의 동안

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

이 상당히 잘 작동합니다. 특히 작은 요청에 대해서.

+0

감사합니다. 백그라운드에서 잘 작동한다고 생각하지만 후속 코드는 NSMutableArray에 액세스하고 데이터가로드되기 전에 예외를 발생시킵니다. 데이터가로드되고 정렬되기 전에 본질적으로 기다리는 방법은 무엇입니까? – blueHula

+0

"여기 배경 자료 사용"부분까지로드 한 데이터를 사용해서는 안됩니다. 어떤 가능성이 가져온 데이터를 복사하고'reloadTable' 호출 [이 질문에 대한 답변은 귀하의 새로운 문제와 관련 있습니다.] (http://stackoverflow.com/a/8962406/927947) – NJones

관련 문제