問題描述
我需要在后臺和前臺完成一項長時間運行的任務.這會更新核心數據.因此,為了保持 UI 響應,我創建了另一個線程,在其中使用不同的 managedObjectContext(MOC).因此,在后臺和前臺都設置了一個計時器,并在狀態更改時適當地停用.在任務開始之前和任務完成之后,當我按下主頁按鈕時,它會正確調用兩個委托方法,但是當我按下主頁按鈕屏幕更改和 UI 掛起(變為空白)時,任務處于活動狀態,但兩個委托方法不是正確調用并且應用程序不會終止.我找不到發生這種情況的原因.如果有人可以提供幫助會很有幫助.
I need a long running task to be done in background as well as in foreground. This updates the core data. So to maintain UI responsive I created an another thread where I use different managedObjectContext(MOC). So a timer is set in background as well as in foreground and is inactivated appropriately when state changes. Before the task is starting and after the task is completed when I press home button it calls the two delegate methods properly but during the task is active when I press home button screen changes and UI hangs (becomes blank) but the two delegate methods are not called properly and the app is not terminated. I could not find the reason why this happens so. It would be helpful if someone can help.
我將附上所需的代碼:
-(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 : %@
",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
");
[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 : %@
",self.logDownloader.managedObjectContext);
self.backgroundTimer = [NSTimer scheduledTimerWithTimeInterval:90 target:self.logDownloader selector:@selector(getDataFromFile) userInfo:nil repeats:YES];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"Foreground
");
//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 : %@
",self.logDownloader.managedObjectContext);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadAppDelegateTable" object:nil];
self.notificationTimer = [NSTimer scheduledTimerWithTimeInterval:180 target:self.logDownloader selector:@selector(startTimerThread) userInfo:nil repeats:YES];
}
推薦答案
原因applicationDidEnterBackground:
和 applicationDidEnterForeground:
永遠不會被調用,因為這些方法與 應用程序不在后臺運行
這個選項可以在你的***-info.plist
中找到.如果此選項設置為 YES
,那么您的應用程序將永遠不會調用這些方法,因為當您使用已將選項設置為 YES
實例的應用程序按下主頁按鈕時,這些方法正在運行的應用程序將被終止,因此每次按下主頁按鈕然后選擇應用程序圖標時,都會創建一個新實例,因此它正在使用 applicationWillTerminate:
.
The reason why applicationDidEnterBackground:
and applicationDidEnterForeground:
are never called is because these methods are used in joint with Application does not run in background
this option can be found in your ***-info.plist
. If this option is set to YES
than your app will never call these methods, because these when you press the home button with an app that has set the option to YES
the instance of the app that is running will get terminated so everytime you press the home button and then select the app icon a new instance is being created so it is using applicationWillTerminate:
.
Kirti mali
所說的方法也將是不正確的方法來使用你想要的,原因是 applicationDidBecomeActive:
和 applicationWillResignActive:
用于接聽電話等情況.正在運行的實例不會被終止,也不會被發送到后臺.該實例會暫停,直到用戶完成該調用,然后它將再次變為活動狀態.
The methods that Kirti mali
has said would also be the incorrect methods to use for want you are after, the reason being is that applicationDidBecomeActive:
and applicationWillResignActive:
are used when something like when you answer a phone call. The instance running is not terminated neither is it sent to the background. The instance is paused until the user has finished on that call when it will become active again.
因此,如果您希望應用程序在后臺運行,解決方案是更改選項應用程序不在后臺運行
".在 ***-info.plist
中為 NO
只是 applicationDidBecomeActive:
和 applicationWillResignActive:
是這些方法的錯誤使用方式.
So the solution to this would be if you want the app to run in background would be to change the option "Application does not run in background
" in the ***-info.plist
to be NO
just applicationDidBecomeActive:
and applicationWillResignActive:
is the wrong way for these methods to be used.
請參閱 上的蘋果文檔UIApplicationDelegate
以更好地理解這些方法.
Please see the apple documentation on UIApplicationDelegate
to get a better understanding of these methods.
這篇關于在 iOS 模擬器中按下主頁按鈕時不會調用 applicationDidEnterBackground 和 applicationWillEnterForeground 方法的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!