I am sending Push Notifications to my iPhone app, and I'd like a different set of instructions to execute depending on whether the app is already launched or not. I'm new to iPhone development, and while I suspect UIApplication or my project's AppDelegate class has the solution, I haven't found a good answer. Is there an easy way to check for this?
问题:
回答1:
The UIApplication delegate has the method
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
which you need to implement. This receives the notification when the app is running.
If your app is not currently running and a notification is received then your app can be launched with
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
with the notification details held in the launchOptions dictionary. if the dictionary is nil then the user tapped the application icon as normal.
回答2:
Here's the more appropriate way of handling active/inactive state of the app.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// check for the app state
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
//the app is in the foreground, so here you do your stuff since the OS does not do it for you
//navigate the "aps" dictionary looking for "loc-args" and "loc-key", for example, or your personal payload)
}
application.applicationIconBadgeNumber = 0;
}
didReceiveRemoteNotification:
is called when the app is running, yes, but when it is suspended, the iOS
takes care of putting up the badge, etc. If the app is in the foreground, the OS does nothing, and just calls your didReceiveRemoteNotification:
.
回答3:
Depending upon what you mean by "launched", you are either looking for:
- Kevin's answer above (differentiates between launched or not launched)
- or this (differentiates between suspended or active, but already launched):
Use a flag that is set true when the application becomes active, and false when the application is not active.
Flag (in header file [.h]):
BOOL applicationIsActive;
Code (in implementation file [.m]):
- (void)applicationDidBecomeActive:(UIApplication *)application {
applicationIsActive = YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
applicationIsActive = NO;
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if (applicationIsActive) {
// Handle notification in app active state here
}
else {
// Handle notification in app suspended state here
}
This works because when the application is suspended, the OS calls "applicationDidReceiveRemoteNotification" before it calls "applicationDidBecomeActive" during the "wake-up" process.
The "complete" answer is actually Kevin's answer plus this answer.
Hope this helps.
回答4:
If you are going to check applicationState on iOS less than 4, you'll need to check that applicationState is supported:
if ([application respondsToSelector:@selector(applicationState)] ){
// Safe to check applicationState
UIApplicationState state = [application applicationState];
}
回答5:
The Apple documentation for push notifications explains this:
However, there are two situations where applicationDidFinishLaunching: is not a suitable implementation site:
- The application is running when the notification arrives.
- The notification payload contains custom data that the application can use.
In the first case, where the application is running when iPhone OS receives a remote notification, you should implement the application:didReceiveRemoteNotification: method of UIApplicationDelegate if you want to download the data immediately. After downloading, be sure to remove the badge from the application icon. (If your application frequently checks with its provider for new data, implementing this method might not be necessary.)
This means that if your application:didReceiveRemoteNotification: delegate method is called, your app is running.