10我在SOF上關注了使用GCD進行異步調用的幾篇文章,如果遠程服務器響應速度夠快,就像在本地測試服務器上工作和測試時一樣正常工作。主線程不等待異步強制
SOF解決方案嘗試:
Waiting until two async blocks are executed before starting another block
iPhone - Grand Central Dispatch main thread
現在,我有一個遠程服務器建立其採取至少8秒鐘返回它的JSON數據和GCD代碼充當如果它沒有等待異步調用在更新UI之前完成,我最終得到了一個空的表視圖。
我能得到這個正確的行爲的唯一方法是通過在該行
[NSThread sleepForTimeInterval:10.0];
迫使應用程序等待10秒,允許離開「[自我runUnirestRequest:requestUrl]。」返回數據,然後我得到數據。這顯然是一個黑客,並希望讓我的GCD代碼正常工作。
有沒有什麼辦法讓UI代碼只在異步調用返回數據後才執行?
注意:從runUnirestRequest返回的數據是JSON格式,並被反序列化並放入「salesData」實例中。
我與GCD調用代碼如下:
- (void)viewDidLoad
{
...unrelated code...
[self createActivityIndicator];
dispatch_queue_t jsonQueue = dispatch_queue_create("com.ppos.pbsdashboard", NULL);
// Start block on background queue so the main thread is not frozen
// which prevents apps UI freeze
[activityIndicator startAnimating];
dispatch_async(jsonQueue, ^{
// Run remote RESTful request
[self runUnirestRequest:requestUrl];
// Force main thread to wait a bit to allow ansync dispatch
// to get its response with data
[NSThread sleepForTimeInterval:10.0];
// Everything in background thread is done.
// Call another block on main thread to do UI stuff
dispatch_sync(dispatch_get_main_queue(), ^{
// Back within main thread
[activityIndicator stopAnimating];
PBSVCDataDisplay *dataVc = [[PBSVCDataDisplay alloc] init];
[dataVc setSalesData:salesData];
[self performSegueWithIdentifier:@"showDataChart" sender:self];
});
});
}
runUnirestRequest功能
- (void) runUnirestRequest:(NSString*)urlToSendRequestTo
{
[requestVCMessages setTextAlignment:NSTextAlignmentCenter];
[requestVCMessages setText:@"Processing request"];
// Handle errors if any occur and display a friendly user message.
@try{
NSDictionary* headers = @{@"p": settingsPassPhrase};
[[UNIRest get:^(UNISimpleRequest* request) {
[request setUrl:urlToSendRequestTo];
[request setHeaders:headers];
}] asJsonAsync:^(UNIHTTPJsonResponse* response, NSError *error) {
UNIJsonNode *jsonNde = [response body];
NSDictionary *jsonAsDictionary = jsonNde.JSONObject;
salesData = [self deserializeJsonPacket:(NSDictionary*)jsonAsDictionary withCalenderType:[requestParameters calendType]];
}];
}
@catch(NSException *exception){
[requestVCMessages setTextAlignment:NSTextAlignmentLeft];
NSString *errHeader = @"An error has occured.\n\n";
NSString *errName = [exception name];
NSString *errString = nil;
// Compare the error name so we can customize the outout error message
if([errName isEqualToString:@"NSInvalidArgumentException"]){
errString = [errHeader stringByAppendingString:@"The reason for the error is probably because data for an invalid date has been requested."];
}else{
errString = [errHeader stringByAppendingString:@"General exception. Please check that your server is responding or that you have requested data for a valid date."];
}
salesData = nil;
[requestVCMessages setText:errString];
}
}
看看這個問題http://stackoverflow.com/questions/11909629/waiting-until-two-async-blocks-are-executed-before-starting-another-block – tkanzakic
感謝您的回覆,我確實嘗試過,並且完全一樣。除去sleepForTimeInterval調用還會添加錯誤「嵌套的推動動畫可能導致損壞的導航欄」,另外兩個涉及「」調用。是否有dispatch_async的onComplete塊?不能發現這樣的事情。 –
'runUnirestRequest'中有什麼?對於'onComplete',你應該使用一個操作隊列,而不是GDC隊列。 – Wain