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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:02:10