このviewDidLoadを持つtableviewcontrollerを持つアプリがあります:
- (void)viewDidLoad{
[super viewDidLoad];
// begin animating the spinner
[self.spinner startAnimating];
[SantiappsHelper fetchUsersWithCompletionHandler:^(NSArray *users) {
self.usersArray = [NSMutableArray array];
for (NSDictionary *userDict in users) {
[self.usersArray addObject:[userDict objectForKey:@"username"]];
}
//Reload tableview
[self.tableView reloadData];
}];
}
ヘルパー クラス メソッドは次のとおりです。
+(void)fetchUsersWithCompletionHandler:(Handler)handler {
NSString *urlString = [NSString stringWithFormat:@"http://www.myserver.com/myApp/fetchusers.php"];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];
[request setHTTPMethod: @"GET"];
__block NSArray *usersArray = [[NSArray alloc] init];
//A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Peform the request
NSURLResponse *response;
NSError *error = nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error) {
// Deal with your error
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(@"HTTP Error: %d %@", httpResponse.statusCode, error);
return;
}
NSLog(@"Error %@", error);
return;
}
NSString *responseString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
usersArray = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSASCIIStringEncoding] options:0 error:nil];
if (handler){
dispatch_async(dispatch_get_main_queue(), ^{
handler(usersArray);
});
}
});
}
上記のコードは私に提案されたものであり、GCD について私が知っていることから理解できます。すべてがメイン キューで実行されますが、NSURLConnection 同期呼び出しの前にバックグラウンド キューにディスパッチされる前です。データを取得した後、usersArray を満たし、それをメイン キューに返す必要があります。usersArray に値が設定され、if ハンドラーをテストするときに、dispatch_asynch(dispatch_get_main_queue () 行に移動します。しかし、配列辞書を処理するためにメイン キューに戻ると、NSArray *users は空です。このエラーでアプリがクラッシュします。 :
* キャッチされていない例外 'NSInvalidArgumentException' が原因でアプリを終了しています。理由: '* -[__NSArrayM insertObject:atIndex:]: オブジェクトを nil にすることはできません'
dispatch_async(dispatch_get_main_queue() コードをコメントアウトすると、次のようになります。
if (handler){
//dispatch_async(dispatch_get_main_queue(), ^{
handler(usersArray);
//});
}
それは正常に動作します...まあ、ちょっと遅いです。なぜこれが失敗するのですか?