You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在任意UIViewController中调用UIUserNotificationSettings注册通知?

当然可以把远程推送的注册逻辑移到UIViewController的按钮点击事件里,下面是具体的实现思路和代码示例,完全适配你的需求:

实现思路与步骤

1. 在UIViewController中触发推送注册

因为UIApplication是全局单例,所以在VC里直接通过[UIApplication sharedApplication]就能调用注册方法,和你在AppDelegate里的逻辑几乎一致,只是触发时机改成按钮点击。

给按钮绑定点击事件后,实现如下代码:

- (IBAction)registerPushNotification:(UIButton *)sender {
    UIApplication *app = [UIApplication sharedApplication];
    UIUserNotificationSettings *currentSettings = [app currentUserNotificationSettings];
    
    // 先判断当前是否已有通知权限,避免重复弹权限弹窗
    if (currentSettings.types == UIUserNotificationTypeNone) {
        // 请求通知权限
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
        [app registerUserNotificationSettings:settings];
        [app registerForRemoteNotifications];
    } else {
        // 已有权限,可选择重新注册device token(比如用户之前取消后又开启)
        [app registerForRemoteNotifications];
        NSLog(@"已经拥有通知权限,重新注册device token");
    }
}

2. 把AppDelegate的回调传递到VC

系统的推送回调(比如获取deviceToken、接收通知)还是会默认发到AppDelegate,所以得把这些信息传递到你的VC里,这里推荐两种常用方式:

方式一:用NSNotificationCenter转发(推荐)

这是低耦合的方案,在AppDelegate的回调里发送通知,VC里监听即可:

第一步:修改AppDelegate的回调方法

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    // 发送通知传递deviceToken
    [[NSNotificationCenter defaultCenter] postNotificationName:@"PushDeviceTokenRegistered" object:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Register Remote Notifications error:{%@}",[error localizedDescription]);
    // 转发注册失败的错误信息
    [[NSNotificationCenter defaultCenter] postNotificationName:@"PushRegisterFailed" object:error];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSLog(@"Receive remote notification : %@",userInfo);
    // 转发收到的通知内容
    [[NSNotificationCenter defaultCenter] postNotificationName:@"PushNotificationReceived" object:userInfo];
}

第二步:在VC里监听并处理通知

在viewDidLoad里添加监听,记得在dealloc里移除,避免内存泄漏:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 注册通知监听
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(handleDeviceTokenReceived:) 
                                                 name:@"PushDeviceTokenRegistered" 
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(handlePushRegisterFailed:) 
                                                 name:@"PushRegisterFailed" 
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(handlePushNotificationArrived:) 
                                                 name:@"PushNotificationReceived" 
                                               object:nil];
}

// 处理deviceToken获取成功
- (void)handleDeviceTokenReceived:(NSNotification *)notification {
    NSData *deviceToken = notification.object;
    // 这里可以把deviceToken上传到你的服务器
    NSLog(@"VC中拿到deviceToken: %@", deviceToken);
}

// 处理注册失败
- (void)handlePushRegisterFailed:(NSNotification *)notification {
    NSError *error = notification.object;
    NSLog(@"VC中收到注册失败提示: %@", error.localizedDescription);
    // 可以给用户弹个提示框告知失败原因
}

// 处理收到远程通知
- (void)handlePushNotificationArrived:(NSNotification *)notification {
    NSDictionary *userInfo = notification.object;
    NSLog(@"VC中收到远程通知内容: %@", userInfo);
    // 在这里处理通知展示逻辑,比如弹Alert或者更新UI
}

- (void)dealloc {
    // 移除所有监听
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

方式二:直接持有VC引用(不推荐)

如果你的VC是全局唯一的(比如根VC),可以在AppDelegate里直接持有它的指针,然后调用VC的对应方法。但这种方式会增加代码耦合,项目复杂时容易出问题,所以不建议使用。

3. 额外注意事项

  • 确保Info.plist里配置了推送相关权限:如果需要后台推送,要在UIBackgroundModes里添加remote-notification;
  • 你的代码是基于iOS 8-9的旧API,iOS 10及以后推荐使用UNUserNotificationCenter框架,如果你需要兼容高版本,可以做版本适配;
  • 重复请求权限会被系统限制,所以先检查当前权限状态再请求是很有必要的。

内容的提问来源于stack exchange,提问作者user2688045

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:52:36