在iOS模拟器中按下主页按钮时不调用applicationDidEnterBackground和applicationWillEnterForeground方法

apa*_*rna 3 iphone nstimer nsthread uiapplicationdelegate ios5

我需要在后台和前台完成一项长时间运行的任务.这会更新核心数据.因此,为了维护UI响应,我创建了另一个线程,我使用不同的managedObjectContext(MOC).因此,计时器在后台和前台设置,并在状态发生变化时被适当地停用.在任务开始之前和任务完成之后,当我按下主页按钮时,它会正确调用两个委托方法但在任务处于活动状态时按下主页按钮屏幕更改并且UI挂起(变为空白)但是两个委托方法不是正确调用,应用程序不会终止.我找不到这种情况发生的原因.如果有人可以提供帮助,将会很有帮助.

我将附上所需的代码:

-(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];
}
Run Code Online (Sandbox Code Playgroud)

Ili*_*rim 28

在 iOS13+ 上,如果您实现 UIWindowSceneDelegate,它会调用func sceneDidEnterBackground(_ scene: UIScene), 代替。


Pop*_*eye 17

之所以applicationDidEnterBackground:和之所以applicationDidEnterForeground:被调用的原因是因为这些方法与Application does not run in background此选项一起使用可以在你的***-info.plist.如果此选项设置为YES大于您的应用程序将永远不会调用这些方法,因为当您按下主页按钮时,如果应用程序已将选项设置YES为正在运行的应用程序实例将被终止,因此每次按下主页按钮然后选择应用程序图标,正在创建一个正在使用的新实例applicationWillTerminate:.

该方法Kirti mali已表示也将是不正确的方法来使用想你之后,产生的原因是,applicationDidBecomeActive:applicationWillResignActive:使用时的东西,当你接听电话等.运行的实例不会被终止,也不会被发送到后台.实例暂停,直到用户完成该呼叫,此时它将再次变为活动状态.

因此,如果您希望应用程序在后台运行,那么解决方法就是更改NO applicationDidBecomeActive中的选项" Application does not run in background" :applicationWillResignActive: `这是使用这些方法的错误方法.***-info.plist to bejustand

请参阅Apple文档UIApplicationDelegate以更好地了解这些方法.


Sha*_*ary 8

由于您的应用程序在后台运行,这些方法永远不会被调用,但是您可以使用willEnterForegroundNotificationdidEnterBackgroundNotification来执行您想要的相同操作。

您可以在ApplicationDelegate的didFinishLaunchingWithOptions方法中编写以下代码

    NotificationCenter.default.addObserver(forName:UIApplication.willEnterForegroundNotification, object: nil, queue: nil) { (_) in
        // Your Code here
}

NotificationCenter.default.addObserver(forName:UIApplication.didEnterBackgroundNotification, object: nil, queue: nil) { (_) in
       // Your Code here        
}
Run Code Online (Sandbox Code Playgroud)