2013-03-14 7 views
3

전경에서뿐만 아니라 백그라운드에서도 장기 실행 작업이 필요합니다. 핵심 데이터가 업데이트됩니다. 그래서 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]; 
} 

답변

17

applicationDidEnterBackground:applicationDidEnterForeground:이 호출되지 않는 이유는 다음과 같습니다. 이러한 방법은 Application does not run in background과 함께 사용되므로이 옵션은 ***-info.plist에서 찾을 수 있습니다. 이 옵션을 YES으로 설정하면 앱에서 이러한 메소드를 호출하지 않습니다.이 옵션을 사용하면 앱이 YES으로 설정된 앱으로 홈 버튼을 누를 때마다 앱의 인스턴스가 종료되므로 매번 앱이 종료됩니다. 홈 버튼을 클릭 한 다음 새 인스턴스를 만들려는 앱 아이콘을 선택하면 applicationWillTerminate:이 사용됩니다.

Kirti mali이 말한 방법은 나중에 전화를받을 때처럼 applicationDidBecomeActive:applicationWillResignActive:이 사용되는 이유입니다. 이유는 다음과 같습니다. 실행중인 인스턴스는 백그라운드로 보내지도 종료되지도 않습니다. 사용자가 통화가 다시 활성화 될 때까지 통화가 끝날 때까지 인스턴스가 일시 중지됩니다. 앱이 ***-info.plist to be NO justapplicationDidBecomeActive:andapplicationWillResignActive:에서 옵션 "Application does not run in background"로 변경하는 것입니다 백그라운드에서 실행하려면

그래서이에 대한 해결책이 될 것`이 방법을 사용하기위한 잘못된 방법입니다.

이러한 방법을 더 잘 이해하려면 UIApplicationDelegate의 Apple 설명서를 참조하십시오.

+0

고마워요. 나는 지금 이해할 수있다. 그것은 매우 도움이되었습니다. 사실 저는 백그라운드에있을 때만 타이머를 호출하고 싶습니다. 그리고이 응용 프로그램은 위치 서비스를 사용하고 있으므로 "응용 프로그램이 백그라운드에서 실행되지 않습니다"info.plist에서 "예"로 설정됩니다. 백그라운드로 들어가는 지 알 수있는 방법이 있습니까? – aparna

+0

'NSLogs'를'NSTimers'에서 실행 시키면됩니다. 그러나 백그라운드로 보내 졌는지 알 수 있습니다. 일단 앱으로 돌아 오면 실행중인 app 인스턴스가 계속 될 것이기 때문입니다. – Popeye

+0

"응용 프로그램이 백그라운드에서 실행되지 않음"을 NO로 설정했는지 확인하고 백그라운드에서 실행합니다. – Popeye

0

홈 버튼을

- (void)applicationDidBecomeActive:(UIApplication *)application 

을 눌렀을 때이 메소드가 호출 및 아이콘 버튼을

- (void)applicationWillResignActive:(UIApplication *)application 

을 눌렀을 때이 메소드가 불려
+0

그 다음 두 가지 방법이 있습니다. 맞습니까? – aparna

+0

나는이 메소드들을 호출 할 때 - (void) applicationDidBecomeActive : (UIApplication *) 어플리케이션과 - (void) applicationWillResignActive : (UIApplication *) 어플리케이션 http://www.cocoanetics.com/2010을 호출하는 사이트를 몇 개 추천했다./07/understanding-ios-4-backgrounding-and-delegate-messaging/및 https://s3-ap-northeast-1.amazonaws.com/booksikindle/html/Beginning%20IOS%205%20Development1/Beginning_iO-ng_the_iOS_SDK_split_039. html. – aparna

+0

예 잘 작동합니다. –