iOS:如何在 AppDelegate 之外调用“应用程序 didRegisterForRemoteNotificationsWithDeviceToken”?

Posted

技术标签:

【中文标题】iOS:如何在 AppDelegate 之外调用“应用程序 didRegisterForRemoteNotificationsWithDeviceToken”?【英文标题】:iOS: How do I call "application didRegisterForRemoteNotificationsWithDeviceToken" outside of AppDelegate? 【发布时间】:2014-07-23 05:51:11 【问题描述】:

使用 解析

场景 = 我有一个发送消息的应用程序。当消息发送给用户时,它也会发送推送通知。

困难 = 应用启动时调用

-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 

    if ([PFUser currentUser]) 

        PFInstallation *currentInstallation = [PFInstallation currentInstallation];
        [currentInstallation setDeviceTokenFromData:deviceToken];
        [currentInstallation setObject:[PFUser currentUser][@"userID"] forKey:@"userID"];
        [currentInstallation saveInBackground];

        NSLog(@"INSTALLATION REGISTERED");
    


当用户第一次下载应用程序时,还没有创建 currentUser。因此,如果 currentUser 存在,应用程序会检查 didRegisterForRemoteNotificationsWithDeviceToken 方法内部。由于第一次启动应用程序时 currentUser 不存在(他们必须先创建一个帐户),我希望能够再次致电 didRegisterForRemoteNotificationsWithDeviceToken currentUser 之后已创建。

问题 = 我如何在AppDelegate 类之外调用didRegisterForRemoteNotificationsWithDeviceToken

我的尝试 = 我注册用户时的代码

UIApplication *app = [[UIApplication alloc]init];

[app registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];

这会引发错误

*** Assertion failure in -[UIApplication init]
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'There can only be one UIApplication instance.'

【问题讨论】:

【参考方案1】:

使用这个

 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge|
 UIRemoteNotificationTypeAlert|
 UIRemoteNotificationTypeSound];

【讨论】:

【参考方案2】:

您不应直接调用 didRegisterForRemoteNotificationsWithDeviceToken,因为它是委托协议的一部分。您应该保存您的 deviceToken 并稍后将其传递给 PFInstallation,例如:

AppDelegate.m

-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 
    self.token = deviceToken;
    [self saveInstallation];


-(void)saveInstallation

    if ([PFUser currentUser]) 
        PFInstallation *currentInstallation = [PFInstallation currentInstallation];
        [currentInstallation setDeviceTokenFromData:self.token];
        [currentInstallation setObject:[PFUser currentUser][@"userID"] forKey:@"userID"];
        [currentInstallation saveInBackground];

        NSLog(@"INSTALLATION REGISTERED");
    


AppDelegate.h

@property(strong) NSData* token;
-(void)saveInstallation;

RegistrationScreen.m

#import "AppDelegate.h"

-(void)yourSaveAction
    // Call this after having a valid PFUser.
    [(AppDelegate*)[[UIApplication sharedApplication] delegate] saveInstallation];

【讨论】:

嘿布鲁诺感谢您的回复。我喜欢这样做的方式。不过有几个问题。 1) 将设备令牌作为属性存储在 AppDelegate 上是否存在安全风险? 2) 在您的代码中,“(YourAppDelegate*)”为什么是“Your”?我不明白。在我用 Xcode 制作的每一个应用程序中,它总是被简单地称为“AppDelegate”。你把“你的”放在那里,就像我应该把我的应用程序的名称放在单词的“...AppDelegate”部分之前一样。这让我很困惑。 1) 我认为这不会带来安全风险,因为您会将其存储在 RAM 内存中。但是,如果您对此感到担心,可以在保存 PFInstallation 后执行self.token = nil;2) 抱歉,我仍然习惯于调用应用代理的旧方式。在 Xcode 5 之前(如果我没记错的话),应用程序委托有另一个名称,例如“FacebookAppDelegate”。我正在编辑我的回复,以便更轻松地完成像您这样的新项目。【参考方案3】:

UIApplication 是一个单例,您应该使用sharedApplication 调用它。

UIApplication * app = [UIApplication sharedApplication];
[app registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];

[编辑] 我弄错了 registerForRemote is an UIApplication 方法

【讨论】:

嗨,安德里亚,谢谢您的回复。澄清一下,我可能在我的代码中也写错了——但是“registerForRemoteNotificationTypes”与“didRegisterForRemoteNotificationsWithDeviceToken”一样吗? 你不应该自己调用didRegister..这是你成功注册推送通知时系统调用的。该过程是您在需要的地方调用 registerForRemoteNotification,应用程序向苹果服务器请求其推送令牌,一旦它成功接收到它调用 didRegisterForRemoteNotification。要获得有效的令牌,您必须要求它。【参考方案4】:

你为什么这样做

UIApplication *app = [[UIApplication alloc]init];

[app registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];

相反,您应该知道 UIApplication 是一个单例类,因此您可以这样做

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

在你想要的地方使用上面的代码

希望这会对您有所帮助。快乐编码:)

【讨论】:

以上是关于iOS:如何在 AppDelegate 之外调用“应用程序 didRegisterForRemoteNotificationsWithDeviceToken”?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 中从 AppDelegate 调用视图控制器

来自 appDelegate 的 javascript 调用:phonegap iOS

如何在 AppDelegate 之外注册推送通知?

如何提示用户接受 AppDelegate 之外的推送通知?

在 AppDelegate 之外,我如何在 UINavigationController 中包含一个 UIViewController,然后再对它执行基本的 `performSegueWIthIden

motionBegan:withEvent: 在 iOS 10 的 AppDelegate 中未调用