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

.NET 7 MAUI iOS前台无法接收推送通知问题求助

.NET MAUI iOS前台推送通知不响应的解决方法

核心问题分析

从Xamarin.Forms迁移到MAUI后,iOS前台推送无响应的主要原因在于:

  • MAUI的MauiUIApplicationDelegate生命周期处理逻辑与Xamarin的FormsApplicationDelegate存在差异
  • 未确保UNUserNotificationCenter的Delegate实例不被GC回收
  • 未正确实现iOS 10+要求的WillPresentNotification方法(前台显示通知的核心入口)

正确实现方案

以下是经过验证的代码实现,直接在AppDelegate中处理通知逻辑,避免Delegate被回收的问题:

[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate, UNUserNotificationCenterDelegate
{
    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        // 1. 请求通知权限(必须包含Alert/Sound等权限)
        UNUserNotificationCenter.Current.RequestAuthorization(
            UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound | UNAuthorizationOptions.Badge, 
            (granted, error) =>
            {
                if (granted)
                {
                    // 在主线程注册远程通知
                    DispatchQueue.MainQueue.DispatchAsync(() =>
                    {
                        UIApplication.SharedApplication.RegisterForRemoteNotifications();
                    });
                }
            });

        // 2. 将当前AppDelegate设置为通知中心Delegate,确保不会被GC回收
        UNUserNotificationCenter.Current.Delegate = this;

        return base.FinishedLaunching(app, options);
    }

    // 获取DeviceToken(正常工作)
    [Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
    public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        // 转换token格式并发送到服务器
        var token = deviceToken.Description.Trim('<', '>').Replace(" ", "");
        Console.WriteLine($"Device Token: {token}");
    }

    // 前台接收通知的核心方法,必须实现才能显示通知
    [Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
    public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
    {
        // 根据iOS版本选择显示方式
        var presentationOptions = UIDevice.CurrentDevice.CheckSystemVersion(14, 0)
            ? UNNotificationPresentationOptions.Banner | UNNotificationPresentationOptions.Sound
            : UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Sound;

        // 必须调用completionHandler,否则系统不会显示通知
        completionHandler(presentationOptions);

        // 处理通知内容(如解析userInfo)
        var userInfo = notification.Request.Content.UserInfo;
        Console.WriteLine($"前台收到通知内容: {userInfo}");
    }

    // 用户点击通知时触发(前台/后台均生效)
    [Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
    public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
    {
        // 处理通知点击逻辑
        var userInfo = response.Notification.Request.Content.UserInfo;
        Console.WriteLine($"用户点击通知: {userInfo}");

        // 必须调用completionHandler
        completionHandler();
    }

    // 兼容iOS 10以下版本的旧通知接收方法(可选保留)
    [Export("application:didReceiveRemoteNotification:")]
    public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
    {
        Console.WriteLine($"收到远程通知(旧API): {userInfo}");
    }
}

关键注意事项

  1. Delegate实例持有:必须将UNUserNotificationCenter.Current.Delegate设置为长期存在的实例(如AppDelegate本身),避免使用临时创建的UserNotificationCenterDelegate对象(易被GC回收导致Delegate失效)
  2. completionHandler调用:WillPresentNotification和DidReceiveNotificationResponse中必须调用对应的completionHandler,这是iOS系统的强制要求,否则会导致通知处理异常
  3. 权限请求:启动时必须请求包含Alert的通知权限,否则即使收到通知也无法在前台显示
  4. API版本兼容:iOS 10+已使用UNUserNotificationCenter的Delegate方法替代旧的ReceivedRemoteNotification,前台通知只会触发WillPresentNotification

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:16:22