전경에서뿐만 아니라 백그라운드에서도 장기 실행 작업이 필요합니다. 핵심 데이터가 업데이트됩니다. 그래서 UI 응답을 유지하기 위해 다른 managedObjectContext (MOC)를 사용하는 또 다른 스레드를 만들었습니다. 따라서 타이머는 전경뿐만 아니라 배경에서도 설정되며 상태가 변경되면 적절하게 비활성화됩니다. 작업이 시작되기 전에 작업이 완료된 후 홈 버튼을 누르면 두 대리자 메서드가 제대로 호출되지만 집 버튼 스크린 변경 사항을 누르면 UI가 중단되고 (비어 있음) 작업이 활성화되지만 두 대리자 메서드는 활성화되지 않습니다. 제대로 호출되고 응용 프로그램이 종료되지 않습니다. 이런 일이 일어나는 이유를 찾지 못했습니다. 누군가가 도울 수 있다면 도움이 될 것입니다.iOS 시뮬레이터의 홈 버튼을 눌렀을 때 applicationDidEnterBackground 및 applicationWillEnterForeground 메서드가 호출되지 않습니다.
나는 이것에 필요한 코드를 첨부합니다
-(void) startTimerThread
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Add code here to do background processing
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator]];
self.managedObjectContext = context;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:context];
NSLog(@"managedObjContext : %@\n",self.managedObjectContext);
[self getDataFromFile];
dispatch_async(dispatch_get_main_queue(), ^{
// Add code here to update the UI/send notifications based on the
// results of the background processing
[[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadAppDelegateTable" object:nil];
[context release];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:context];
});
});
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"Background\n");
[self.notificationTimer invalidate];
self.notificationTimer = nil;
UIApplication *app = [UIApplication sharedApplication];
self.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
//start location update timer and background timer
self.timer = [NSTimer scheduledTimerWithTimeInterval:180 target:self
selector:@selector(startLocationServices) userInfo:nil repeats:YES];
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
self.logDownloader.managedObjectContext = self.managedObjectContext;
NSLog(@"managedObjContext : %@\n",self.logDownloader.managedObjectContext);
self.backgroundTimer = [NSTimer scheduledTimerWithTimeInterval:90 target:self.logDownloader selector:@selector(getDataFromFile) userInfo:nil repeats:YES];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"Foreground\n");
//invalidate background timer and location update timer
[self.timer invalidate];
[self.backgroundTimer invalidate];
self.timer = nil;
self.notificationTimer = nil;
self.logDownloader.managedObjectContext = self.managedObjectContext;
NSLog(@"managedObjContext : %@\n",self.logDownloader.managedObjectContext);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadAppDelegateTable" object:nil];
self.notificationTimer = [NSTimer scheduledTimerWithTimeInterval:180 target:self.logDownloader selector:@selector(startTimerThread) userInfo:nil repeats:YES];
}
고마워요. 나는 지금 이해할 수있다. 그것은 매우 도움이되었습니다. 사실 저는 백그라운드에있을 때만 타이머를 호출하고 싶습니다. 그리고이 응용 프로그램은 위치 서비스를 사용하고 있으므로 "응용 프로그램이 백그라운드에서 실행되지 않습니다"info.plist에서 "예"로 설정됩니다. 백그라운드로 들어가는 지 알 수있는 방법이 있습니까? – aparna
'NSLogs'를'NSTimers'에서 실행 시키면됩니다. 그러나 백그라운드로 보내 졌는지 알 수 있습니다. 일단 앱으로 돌아 오면 실행중인 app 인스턴스가 계속 될 것이기 때문입니다. – Popeye
"응용 프로그램이 백그라운드에서 실행되지 않음"을 NO로 설정했는지 확인하고 백그라운드에서 실행합니다. – Popeye