![](/img/trans.png)
[英]Objective-C: Blocking a Thread until an NSTimer has completed (iOS)
[英]NSTimer in objective c blocking main thread - ipad programming
我在Objective-C中使用NSTimer
定期運行后台進程(間隔為1分鍾),該進程檢查是否有未保存的數據並通過Web服務提交到數據庫。 在重新啟動Web服務器之前的一種特定情況下,此過程可以正常運行而不會阻塞主應用程序的流。
當Web服務器啟動時,后台進程正在嘗試連接到服務器,只是掛在那兒,直到服務器完全啟動並可以訪問為止。 當掛斷電話時,它也阻塞了主要應用程序的流程並凍結了整個屏幕。 當Web服務器完全啟動時,掛斷過程將恢復,並且主應用程序也將恢復工作。
誰能讓我知道掛斷后台進程時為什么主應用程序間歇性凍結。
以下代碼啟動計時器
- (void) startSync{
syncTimer = [NSTimer scheduledTimerWithTimeInterval:60
target:self
selector:@selector(syncExtSys:)
userInfo:nil
repeats:YES];
}
每60秒調用一次以下方法, saveAgendaToDb
方法調用將調用Web服務:
- (void) syncExtSys:(NSTimer *) theTimer{
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:[NSBundle mainBundle]];
AgendaItemViewController *agendaItemViewController = [storyboard instantiateViewControllerWithIdentifier:@"AgendaItemViewController"];
RollCallViewController *rollCallViewController = [storyboard instantiateViewControllerWithIdentifier:@"RollCallViewController"];
for(int i=0;i<agenda.count;i++){
unsavedAgenda = [agenda objectAtIndex:i];
if(unsavedAgenda !=nil && [unsavedAgenda.dirtyFlag isEqualToString:@"Y"] && [self checkNetworkStatus]){
NSLog(@"agenda out of sync = %@ %@",unsavedAgenda.measureType,unsavedAgenda.measureNum);
[agendaItemViewController saveAgendaToDb:[agendaItemViewController createDictForAgenda:unsavedAgenda]:unsavedAgenda];
}
}
for(int i=0;i<_rollCall.count;i++){
Member *member = [_rollCall objectAtIndex:i];
if(member !=nil && [member.dirtyFlag isEqualToString:@"Y"] && [self checkNetworkStatus]){
[rollCallViewController saveRollCall:[rollCallViewController createRollCall]];
break;
}
}
[self calcDirtyFlag];
}
代碼調用Web服務
-(void) saveAgendaToDb:(NSMutableDictionary*) agendaDictionary:(AgendaItem*) agenda{
NSError *error;
CommVotesAppDelegate *delegate = (CommVotesAppDelegate *)[[UIApplication sharedApplication] delegate];
@try{
NSString *postUrlString = [NSString stringWithFormat:@"%@%@:%@%@%@/%@",@"http://",delegate.prop.serverName,
delegate.prop.port,delegate.prop.urlPattern,delegate.prop.saveAgendaMethod,delegate.prop.objectType];
NSURL *postUrl = [NSURL URLWithString:postUrlString];
NSMutableURLRequest *urlRequestPost = [[NSMutableURLRequest alloc] initWithURL:postUrl];
NSData *postData = [NSJSONSerialization dataWithJSONObject:agendaDictionary options:0 error:&error];
[urlRequestPost setHTTPMethod:@"POST"];
[urlRequestPost setValue:@"text/plain" forHTTPHeaderField:@"Accept"];
[urlRequestPost setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[urlRequestPost setHTTPBody: postData];
// NSLog(@"After calling webservices");
NSData *returnData = [ NSURLConnection sendSynchronousRequest: urlRequestPost returningResponse: nil error: &error ];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding: NSUTF8StringEncoding];
NSLog(@"Response after calling save agenda web service = %@",returnString);
[delegate dirtyFlagCalc:returnString :[error localizedDescription]:agenda];
}@catch(NSException *nserror){
NSLog(@"Error while sending agenda through webservices = %@",nserror.debugDescription);
}@finally {
NSLog(@"Inside finally block of agenda saving ");
[delegate saveDataToDisk];
}
}
計時器在主線程上觸發。 如果syncExtSys:方法沒有立即完成,它將掛起主線程。
您的情況是,您想做一些可能需要一段時間的事情,但是您希望結果顯示在主線程的UI中。 解決此問題的一些好方法是對Grand Central Dispatch執行以下操作之一:
您的錯誤是此調用: sendSynchronousRequest
。 簡而言之就是這樣。 幾乎沒有任何理由同步發送Web請求-現在您知道了為什么不應該這樣做。 它是同步的! 這意味着它在我們等待時會阻塞線程-如果等待很長時間,就會有很長的阻塞。 這是主線程,因此我們阻止了用戶界面,計時器以及所有內容。
只需切換到異步請求並正確使用委托回調,一切都會很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.