Unity iOS中CancelLocalNotification无法删除通知的问题求助
解决Unity iOS单个本地通知无法删除的问题
我之前在Unity 2017.x版本配合iOS 11+开发时,也遇到过CancelLocalNotification(nt)失效的情况,下面是几个亲测有效的解决思路和代码调整建议:
1. 修复遍历删除的逻辑问题
首先要注意,NotificationServices.scheduledLocalNotifications返回的是当前调度通知的数组副本,而非实时引用。你直接在正向遍历副本时调用删除方法,可能因为对象引用不匹配导致操作失效。建议先批量收集需要删除的通知,再统一处理:
public void UpdateMorningNotifications() { // 1. 先收集所有需要删除的morning类型通知 UnityEngine.iOS.LocalNotification[] scheduledNotifications = UnityEngine.iOS.NotificationServices.scheduledLocalNotifications; List<UnityEngine.iOS.LocalNotification> notificationsToCancel = new List<UnityEngine.iOS.LocalNotification>(); foreach (UnityEngine.iOS.LocalNotification nt in scheduledNotifications) { Debug.Log ("NotificationScheduler/UpdateMorningNotifications - notification type: " + nt.userInfo["type"] ); if (nt.userInfo != null && nt.userInfo["type"]?.ToString() == "morning") { Debug.Log ("Marking morning notification for deletion: " + nt.alertBody); notificationsToCancel.Add(nt); } } // 2. 逐个删除标记的通知 foreach (var nt in notificationsToCancel) { UnityEngine.iOS.NotificationServices.CancelLocalNotification(nt); Debug.Log ("Successfully canceled morning notification: " + nt.alertBody); } // ... 后续创建通知的代码 ... }
2. 给通知添加唯一标识,精准匹配删除
如果上面的方法仍然无效,可能是Unity的LocalNotification对象和系统底层通知实例的映射出现了偏差。可以给每个通知添加唯一标识,通过标识精准定位删除:
生成通知时添加唯一ID:
private UnityEngine.iOS.LocalNotification GenerateNotification(string title, DateTime fireDate, string type) { UnityEngine.iOS.LocalNotification nt = new UnityEngine.iOS.LocalNotification(); nt.alertBody = title; nt.fireDate = fireDate; // 用时间戳+类型生成唯一标识 string notificationId = $"{type}_{fireDate.Ticks}"; nt.userInfo.Add("id", notificationId); nt.userInfo.Add("type", type); return nt; }
删除时通过唯一ID重新查找并删除:
// 替换之前的删除逻辑 List<string> morningNotificationIds = new List<string>(); foreach (var nt in scheduledNotifications) { if (nt.userInfo != null && nt.userInfo["type"]?.ToString() == "morning") { morningNotificationIds.Add(nt.userInfo["id"].ToString()); } } // 重新遍历所有通知,匹配ID删除 foreach (var nt in scheduledNotifications) { if (nt.userInfo != null && morningNotificationIds.Contains(nt.userInfo["id"].ToString())) { UnityEngine.iOS.NotificationServices.CancelLocalNotification(nt); } }
3. 兼容iOS 11+的原生通知框架(推荐)
Unity 2017.2的NotificationServices基于iOS旧版通知API开发,而iOS 10+已经推出了UserNotifications框架,旧API在iOS 11上可能存在兼容性问题。可以通过Unity原生插件调用iOS原生代码实现精准删除:
第一步:在Unity中创建C#桥接类
public static class iOSNotificationHelper { #if UNITY_IOS && !UNITY_EDITOR [DllImport("__Internal")] private static extern void CancelNotificationByIdentifier(string identifier); #endif public static void CancelNotification(string identifier) { #if UNITY_IOS && !UNITY_EDITOR CancelNotificationByIdentifier(identifier); #endif } }
第二步:添加iOS原生代码(Xcode工程中)
创建一个.m文件,添加如下代码:
#import <UserNotifications/UserNotifications.h> void CancelNotificationByIdentifier(const char* identifier) { NSString *notificationId = [NSString stringWithUTF8String:identifier]; // 删除待调度的通知 [[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[notificationId]]; // 删除已展示的通知(可选) [[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:@[notificationId]]; }
第三步:生成和删除通知时使用标识
生成通知时将唯一ID同步到原生框架的identifier,删除时直接调用iOSNotificationHelper.CancelNotification(notificationId)即可。
额外发现:你的代码中的小bug
在设置通知时间时,AddHours方法会返回新的DateTime对象,不会修改原变量,导致通知时间设置失效:
// 错误写法: fireDate.AddHours(10); // 正确写法: fireDate = fireDate.AddHours(10);
这个问题会导致新创建的通知时间不符合预期,建议一并修复。
内容的提问来源于stack exchange,提问作者Jeppe Søndergaard
相关产品推荐
相关产品推荐

