0

UITabBarControllerを使用してビューを切り替えるアプリケーションを作成しています。 1つのタブは、UITableViewにデータを入力する前にJSONデータを収集して処理するWebリクエストを作成します。このデータをバックグラウンドで読み込もうとしているので、ユーザーがタブを押したときにテーブルの表示が遅れることはありません。 ActivityIndi​​catorが表示され、テーブルにデータがロードされます。UITabViewControllerでdispatch_syncを使用してデータを取得する

各リクエストが作成され、処理され、結果がNSMutableArrayに格納され、その後、ソートされてUITableViewに追加されます。

dispatch_syncを使用すると、データがロードされ、配列が作成されて正常に表示されますが、ビューのUIの読み込みがブロックされます。私は何らかの理由でこのクエリーをバックグラウンドキューに取得していないので、考えています。 dispatch_asyncを使用すると、メインスレッドのNSMutableArrayにアクセスしようとすると例外が発生します。

私の質問は、このTableViewを含むタブに切り替え、データがロードされ、バックグラウンドで処理され、一度完了した後、ActivityIndi​​catorを提示するための適切なパターンは何ですか。処理されたデータがロードされる。 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は、呼び出し関数を再開できるので、はるかに良い選択です。あるコールを別のコールにラップすると、メインスレッドで完了コードを実行できます。これにより、コードの実行も非常に簡単になります。

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

NSURLConnectionのようなコールバックベースのAPIは、ネットワークの負荷のために、おそらく最高のですが、これはかなりうまく動作します。特に小規模なリクエストの場合。

+0

ありがとうございます!私は、バックグラウンドでこれは正常に動作していると思いますが、後続のコードはNSMutableArrayにアクセスして、データがロードされる前に例外を起こしています。データにアクセスする前にデータがロードされ、ソートされていることを確認するにはどうすればよいでしょうか? – blueHula

+0

「ここで背景を使用する」の部分が表示されるまで、読み込んだデータを使用しないでください。これはおそらくあなたのフェッチされたデータをコピーして 'reloadTable'を呼び出すでしょう[私が投稿したこの回答は新しい問題と関連しています。](http://stackoverflow.com/a/8962406/927947) – NJones

関連する問題