morningstar
morningstar

Reputation: 9122

What happens when observing UIApplicationDidEnterBackgroundNotification on old iOS without multitasking?

I have this line of code:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationDidEnterBackgroundNotification object:nil];

Works fine in iPhone 4.3 simulator and on my iPhone running 4.x. However a crash occurs there on an iPhone running 3.x. Makes sense. My guess is that that line of code doesn't work when there is no multitasking.

It's difficult for me to debug because the person testing for me with the 3.x system is in a remote location. I'm not even sure whether the symbol UIApplicationDidEnterBackgroundNotification evaluates to the correct string, or nil, or random uninitialized memory, or what on that OS.

But beyond figuring out why it's failing, which I can do with some effort, what am I supposed to do? How do I detect whether a particular notification exists before I observe it? Or do I check if multitasking is available as a general category? I guess I thought the line of code would be safe. If the OS never generates that notification, then I don't get notified, but the line shouldn't crash.

Upvotes: 0

Views: 1120

Answers (4)

Pierre Lebeaupin
Pierre Lebeaupin

Reputation: 1113

Just for your enlightenment, the problem happens not so much when registering for an unknown notification, but that the notification name does not exist (as you suspected), and in fact it's not even that UIApplicationDidEnterBackgroundNotification is NULL, but in fact &UIApplicationDidEnterBackgroundNotificationis NULL; that's how you test for it, in fact.

So what happens (happened) in your case is a simple NULL dereference, NSNotificationCenter did not even get involved.

Upvotes: 1

Olaf
Olaf

Reputation: 3042

Backgrounding (i.e. Multitasking) did not exist prior to 4.0. Registering to a notification that does not exist should not cause much damage. I would expect it simply never gets called. But I admit I have not tested this with notifications.

The example below checks at runtime for the os version (here 4.0 and 3.2), then executes one method or another.

NSString *requiredSystemVersion = @"4.0"; 
NSString *currentSystemVersion = [[UIDevice currentDevice] systemVersion];
if (![currentSystemVersion compare:requiredSystemVersion options:NSNumericSearch] != NSOrderedAscending) [self do4dotXStuff];

requiredSysVer = @"3.2";
if ([currentSystemVersion compare:requiredSystemVersion options:NSNumericSearch] != NSOrderedAscending) [self do3dotTwoStuff];

Upvotes: 0

user244343
user244343

Reputation:

You should check whether the iOS version is 4.0 or later when compiling (there are inbuilt preprocessor #defines for this) and test multitasking support as well (in case it's disabled on the device when it would otherwise be supported):

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
    if([[UIDevice currentDevice]
        respondsToSelector:@selector(isMultitaskingSupported)] &&
       [[UIDevice currentDevice] isMultitaskingSupported])
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationDidEnterBackgroundNotification object:nil];
    }
#endif

You don't have to use the #if, but it saves compiling in extra checks which you know will always return false.

Upvotes: 3

Mobile App Dev
Mobile App Dev

Reputation: 1814

I think this will work for you, i have not check.

#ifdef _USE_OS_4_OR_LATER
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationDidEnterBackgroundNotification object:nil];
#endif

Upvotes: 0

Related Questions