iOS开发构建中点击推送/定时通知时addNotificationResponseReceivedListener未触发
问题描述
最小可复现示例
Expo Snack推送通知测试项目
问题环境
- 平台:iOS
- 构建类型:开发构建(development build)
- Expo工作流:裸工作流(bare)
问题现象
按通知配置指引操作或打开示例项目,点击发送通知按钮后,设备能正常显示通知,但点击通知无任何反应,addNotificationResponseReceivedListener监听器未触发,无法实现点击通知通过深度链接打开对应文章的需求。
预期行为
点击通知后触发监听器,弹出标题为"addNotificationResponseReceivedListener"的提示框,并可处理深度链接跳转至对应文章页面。
环境信息
System: OS: macOS 14.4.1 Shell: 5.9 - /bin/zsh Binaries: Node: 22.8.0 - /opt/homebrew/bin/node Yarn: 1.22.19 - ~/.yarn/bin/yarn npm: 10.8.2 - /opt/homebrew/bin/npm Managers: CocoaPods: 1.15.2 - /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: DriverKit 23.5, iOS 17.5, macOS 14.5, tvOS 17.5, visionOS 1.2, watchOS 10.5 IDEs: Xcode: 15.4/15F31d - /usr/bin/xcodebuild npmPackages: @expo/metro-config: ^0.18.11 => 0.18.11 expo: ~51.0.31 => 51.0.32 react: 18.2.0 => 18.2.0 react-native: 0.74.5 => 0.74.5 npmGlobalPackages: eas-cli: 7.2.0 expo-cli: 6.3.10
解决方案
1. 完善AppDelegate通知处理配置(裸工作流必填)
在iOS项目的AppDelegate.m或AppDelegate.swift中,集成Expo通知处理逻辑,实现UNUserNotificationCenterDelegate的响应方法:
Objective-C 示例(AppDelegate.m):
#import <ExpoModulesCore/EXModuleRegistry.h> #import <UserNotifications/UserNotifications.h> @interface AppDelegate () <UNUserNotificationCenterDelegate> @end @implementation AppDelegate // 保留原有代码,新增以下两个方法 - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { [EXNotificationHandler didReceiveNotificationResponse:response withCompletionHandler:completionHandler]; } - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { [EXNotificationHandler willPresentNotification:notification withCompletionHandler:completionHandler]; } @end
Swift 示例(AppDelegate.swift):
import ExpoModulesCore import UserNotifications class AppDelegate: EXAppDelegateWrapper, UNUserNotificationCenterDelegate { // 保留原有代码,新增以下两个方法 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { EXNotificationHandler.didReceive(response, completionHandler: completionHandler) } func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { EXNotificationHandler.willPresent(notification, completionHandler: completionHandler) } }
配置完成后重新构建iOS项目。
2. 确保推送负载包含正确的Expo标识
推送通知负载必须携带expo.experienceId字段,值为你的项目ID(格式:@用户名/项目Slug),否则Expo无法将通知路由到你的应用。示例负载:
{ "to": "你的Expo推送令牌", "title": "新文章通知", "body": "点击查看最新文章", "data": { "articleId": "123" }, "expo": { "experienceId": "@your-username/your-project-slug" }, "sound": "default" }
3. 正确注册通知监听器
在App根组件挂载阶段就注册监听器,避免延迟或未注册的情况:
import React, { useEffect } from 'react'; import { View, Alert } from 'react-native'; import * as Notifications from 'expo-notifications'; export default function App() { useEffect(() => { // 请求通知权限 async function requestPermissions() { const { status } = await Notifications.requestPermissionsAsync(); if (status !== 'granted') { Alert.alert('权限不足', '需要开启通知权限才能接收推送'); return; } // 获取推送令牌(用于测试推送) const token = await Notifications.getExpoPushTokenAsync(); console.log('Expo推送令牌:', token); } requestPermissions(); // 注册通知响应监听器 const responseListener = Notifications.addNotificationResponseReceivedListener(response => { const { articleId } = response.notification.request.content.data; // 处理深度链接跳转,例如导航到文章页面 Alert.alert('addNotificationResponseReceivedListener', `文章ID: ${articleId}`); }); // 组件卸载时移除监听器 return () => { Notifications.removeNotificationSubscription(responseListener); }; }, []); return <View />; }
4. 检查Xcode项目配置
- 打开Xcode项目,进入
Signing & Capabilities标签页; - 确认
Push Notifications能力已开启; - 开启
Background Modes能力,并勾选Remote notifications选项。
5. 验证开发构建的推送配置
开发构建中需确保:
- 设备已连接到Expo开发服务器;
- 推送令牌通过当前开发构建获取(不同构建类型令牌不通用);
- 测试推送使用Expo推送API发送,确保负载格式正确。
内容的提问来源于stack exchange,提问作者Jakobi
相关产品推荐
相关产品推荐

