Search code examples
iosobservers

Two UIApplicationDidEnterBackgroundNotification when killing the app


in the iOS simulator 7.1, with the simple code at below :

  1. command+shift+H to simulate a home button press, the output is logically:
    • activing
    • resigning
    • backgrounding
  2. double command+shift+H to simulate a double click on home button and then a swipe to kill the app, the output is "strangely":
    • activing
    • resigning
    • backgrounding
    • backgrounding

For which reason in case 2. the backgrounding is called two times ? Note that with iOS 8.0 case 2. display: - activing - resigning - backgrounding

#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController {}

- (void)backgrounding {
    NSLog(@"backgrounding");
}

- (void)resigning {
    NSLog(@"resigning");
}

- (void)activing {
    NSLog(@"activing");
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgrounding) name:UIApplicationDidEnterBackgroundNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resigning) name:UIApplicationWillResignActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(activing) name:UIApplicationDidBecomeActiveNotification object:nil];
}

@end

Solution

  • iOS 7 (in the simulator, at least) sends two backgrounding events. You simply need to write your app to handle multiple backgrounding events gracefully.

    I checked this by creating a custom UIApplication subclass that logs each event, along with its internal GraphicsServices event if there is one:

    #import "MyApplication.h"
    
    @interface NSObject (hack)
    
    - (id)_gsEvent;
    
    @end
    
    @implementation MyApplication
    
    - (void)sendEvent:(UIEvent *)event {
        NSLog(@"event=%@", event);
        if ([event respondsToSelector:@selector(_gsEvent)]) {
            NSLog(@"_gsEvent=%@", event._gsEvent);
        }
        [super sendEvent:event];
    }
    
    @end
    

    Here's the output upon swiping away the app in the multitasking screen:

    2014-09-15 16:14:32.894 background[19438:70b] event=<UIInternalEvent: 0x8c148e0>
    2014-09-15 16:14:32.894 background[19438:70b] _gsEvent=<GSEvent 0xd9149f0>{type = 32, windowLoc = (0.000000, 0.000000)}
    2014-09-15 16:14:32.895 background[19438:70b] event=<UIInternalEvent: 0x8c148e0>
    2014-09-15 16:14:32.895 background[19438:70b] _gsEvent=<GSEvent 0x8f1ac20>{type = 7d7, windowLoc = (0.000000, 0.000000)}
    2014-09-15 16:14:32.896 background[19438:70b] backgrounding
    2014-09-15 16:14:32.943 background[19438:70b] event=<UIInternalEvent: 0x8c148e0>
    2014-09-15 16:14:32.944 background[19438:70b] _gsEvent=<GSEvent 0x8b22c90>{type = 7d7, windowLoc = (0.000000, 0.000000)}
    2014-09-15 16:14:32.944 background[19438:70b] backgrounding
    

    You can see that there are two separate GraphicsServices events (with different addresses), one for each UIApplicationDidEnterBackgroundNotification.