2013-03-14 153 views
3

我需要在後臺以及前臺執行長時間運行的任務。這會更新核心數據。所以爲了保持UI響應,我創建了另一個線程,我使用了不同的managedObjectContext(MOC)。所以一個計時器在後臺和前臺設置,並且在狀態改變時被適當地禁用。在任務開始之前和任務完成後,當我按Home按鈕時,它會正確調用兩個委託方法,但在任務處於活動狀態時,當我按Home按鈕屏幕更改並且UI掛起(變爲空白),但兩個委託方法不是正確調用,應用程序不會終止。我無法找到發生這種情況的原因。如果有人能幫忙,這將會有所幫助。在iOS模擬器中按下home按鈕時,不會調用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:使用時的東西,當你接聽電話等。運行的實例不會被終止,也不會被髮送到後臺。該實例將暫停,直到用戶完成該通話後再次變爲活動狀態。

因此,如果你希望應用程序在後臺運行,會更改選項「Application does not run in background」在***-info.plist to be NO justapplicationDidBecomeActive:andapplicationWillResignActive:解決,這將是'是要使用這些方法的錯誤的方式。

請參閱UIApplicationDelegate上的apple文檔以更好地理解這些方法。

+0

非常感謝。我現在可以理解。這非常有幫助。其實我只想在計時器後臺撥打電話。並且此應用程序正在使用位置服務,因此它將「應用程序不在後臺運行」中的info.plist設置爲「YES」。有什麼方法可以知道它是否進入背景? – aparna 2013-04-13 17:49:01

+0

把一些'NSLogs'運行在'NSTimers'上,但是你會知道它是否被髮送到後臺,因爲一旦你回到應用程序,運行的應用程序實例將繼續運行。 – Popeye 2013-04-13 17:52:44

+0

只需確保將「應用程序不在後臺運行」設置爲NO,並且它將在後臺運行。 – Popeye 2013-04-13 17:54:24

0

當主頁按鈕被按下

- (void)applicationDidBecomeActive:(UIApplication *)application 

這種方法被調用,當圖標按鈕被按下

- (void)applicationWillResignActive:(UIApplication *)application 
調用此方法
+0

接下來是這兩種方法嗎? – aparna 2013-03-14 09:52:56

+0

我提到了幾個解釋這些方法的站點,後面跟着 - (void)applicationDidBecomeActive:(UIApplication *)應用程序和 - (void)applicationWillResignActive:(UIApplication *)application http://www.cocoanetics.com/2010/07 /諒解 - 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 2013-03-14 10:19:18

+0

是的,它運作良好 – 2013-03-14 11:31:02

相關問題