iOS应用内注册推送通知

8

Q1. 我需要在应用程序启动时执行这个操作吗?还是说我可以在应用程序的任何时候触发允许/不允许提示?

Q2. 是否有方法可以找出用户是否点击了是/否(回调)?

Q3. 如果用户以前已经点击了“否”(在之前的会话中),那么我的提示是否会实际触发?或者我需要告诉用户去他们的手机设置里启用它?

原因是我有一个名为“通知”的部分的应用程序,用户可以在其中启用/禁用某些事物的通知,所以当他们在此部分而不是在应用程序的开始时,我只想提示他们启用等等。


在iOS 10中,如果您使用UserNotifications框架,则可以通过回调函数找出用户是否点击了是/否。请参见此处 - mfaani
4个回答

22

A1:不,它不必在应用程序的开头。您可以从代码的任何位置调用registerForRemoteNotificationTypes。

[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];

你需要处理以下委托方法(在委托中),当成功/失败注册推送通知时会调用它们。
// Delegation methods
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
    const void *devTokenBytes = [devToken bytes];
    self.registered = YES;
    [self sendProviderDeviceToken:devTokenBytes]; // this will send token to your server's database
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
    NSLog(@"Error in registration. Error: %@", err);
}

A2:是的,你可以。有两种可能的情况。如果你的应用程序没有运行,你将在didFinishLaunchingWithOptions中处理推送通知。在这种情况下,如果用户在消息警报中选择了“打开”或点击了横幅(取决于用户的设置),你的应用程序将自动启动,你可以处理传递的用户参数。

 /* Push notification received when app is not running */
 NSDictionary *params = [[launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"] objectForKey:@"appsInfo"];

    if (params) {
        // Use params and do your stuffs
    }

如果您的应用程序已经在运行,推送通知将会传递到application:didReceiveRemoteNotification:代理方法中,您可以在其中简单地展示带有推送通知中消息的UIAlertView,并以标准方式处理alertView代理OK/Cancel按钮点击。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSDictionary *apsInfo = [userInfo objectForKey:@"apsinfo"]; // This appsInfo set by your server while sending push

    NSString *alert = [apsInfo objectForKey:@"alert"];

    UIApplicationState state = [application applicationState];

    if (state == UIApplicationStateActive) {
        application.applicationIconBadgeNumber = 0;

        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

        UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"Push Notification"
                                                            message:alert
                                                           delegate:self
                                                  cancelButtonTitle:@"NO"
                                                  otherButtonTitles:@"YES"];
        [alertview show];
        [alertview release];

    } else {
        [self setTabs:contentsInfo];
     }
}


- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
    if (buttonIndex != [alertView cancelButtonIndex]) {
     // User pressed YES, do your stuffs
     }
}

A3:如果用户拒绝接受您的应用程序推送通知,则其didFailToRegisterForRemoteNotificationsWithError将无法获取用户的devToken,该令牌需要在您的服务器上才能向该用户发送推送通知。如果用户最初同意但后来更改设置以禁用您的推送通知,则苹果服务器将不会向该用户发送您的推送通知。在这种情况下,该用户的UDID将出现在反馈服务中,理想情况下,您的服务器应从数据库中删除该用户的UDID,并停止向该用户发送推送通知。如果您继续发送无效的推送通知,苹果服务器可能会默默地断开您的连接,您将无法发送任何推送通知。
有关实现的详细信息,请参见Apple Push Notification文档。

如果用户拒绝接收推送通知或在设置中关闭推送通知,我们如何处理重新提示用户的情况?即如何知道用户未注册推送并给予重新提示? - Rohan Sanap
1
这个答案(以及可能的其他答案)已经部分过时了。它仅适用于iOS <7。在iOS789中,您需要单独执行[application registerForRemoteNotifications],因为这将为您获取令牌(您可以在不需要用户权限的情况下执行此操作;只有在向用户提供警报/徽章、声音时才需要权限)。在iOS 10中,有一个名为“UserNotifications”的新框架,它将允许您找出用户是否允许访问。请参见这里了解更多关于iOS 10的信息(1/2)。 - mfaani
在之前的版本中,你必须使用 [application isRegisteredForRemoteNotifications] 来查看是否已注册。(2/2) - mfaani

5
你可以使用以下教程学习Swift(点击链接),并使用以下简单的Objective-C代码实现苹果推送通知。
  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
        {
         // iOS 8 Notifications
            [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound |UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
            [application registerForRemoteNotifications];
        }
        return YES;
    }


    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        NSLog(@"Did Register for Remote Notifications with Device Token (%@)", deviceToken);
    }

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

        NSLog(@"Did Fail to Register for Remote Notifications");
        NSLog(@"%@, %@", error, error.localizedDescription);
    }

    -(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
        NSLog(@"%@",userInfo);
    }

我们可以跳过 iOS < 8 的通知部分,因为现在我们使用的是iOS 8及以上版本。Mohammad 写的 Obj-C 代码很不错。 - karan

5
  • Q1 在应用程序启动时放置推送注册并不是必须的,但有些人会在application: didFinishLaunchingWithOptions:中放置它以确保设备令牌成功存储到开发人员的服务器上。
  • Q2 这里的“是/否”是什么意思?如果您指的是“是否接收推送通知”的“是/否”,那么如果用户点击“是”,则将触发委托方法application: didRegisterForRemoteNotificationsWithDeviceToken,否则不会。
  • Q3 如果用户点击“否”拒绝接收推送通知,则可以稍后提醒他在设置中打开它,或者有一个功能,例如UISwitch,允许用户再次触发[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];

0

iOS 10中第2个问题的答案:

iOS 10中实现了完成处理程序。因此,您将立即在完成处理程序块内得到通知。

if([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.f){
    UNUserNotificationCenter* notificationCenter = [UNUserNotificationCenter currentNotificationCenter];
    [notificationCenter requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge completionHandler:^(BOOL granted, NSError * _Nullable error) {
        NSLog(@"grant Access:%d",granted);
    }];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接