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

iOS点击通知后向ViewController传递Fence对象实现方案咨询

iOS实现通知点击传递Fence对象到ViewController

问题背景

已实现地理围栏进入时的通知创建与注册,需要实现点击通知时向ViewController传递Fence对象完成签到,对应Android中Intent+Extras的传参逻辑。

现有iOS通知代码

UNMutableNotificationContent notificationContent = new UNMutableNotificationContent();
notificationContent.Title = "Entered region";
notificationContent.Body = "You have entered region " + fence.title + ". Touch here to check-in.";
RegisterNotification(notificationContent, "LocationStatus");

public static void RegisterNotification(UNMutableNotificationContent notificationContent, string identifier)
{
    UNUserNotificationCenter center = UNUserNotificationCenter.Current;
    notificationContent.Sound = UNNotificationSound.Default;
    UNNotificationRequest request = UNNotificationRequest.FromIdentifier(identifier, notificationContent, null);
    center.AddNotificationRequest(request, (NSError obj) =>
    {
    });
}

Android参考实现(Intent传参)

string message = "You have entered " + k.title + ". Touch here to check-in.";
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.SingleTop | ActivityFlags.ClearTop);

if (action != null)
{
    intent.PutExtra("fence", Newtonsoft.Json.JsonConvert.SerializeObject(new FenceAction()
    {
        action = action,
        publicid = publicid
    }));
}

var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.UpdateCurrent);

Notification.Builder notificationBuilder = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
    .SetSmallIcon(Resource.Drawable.notification)
    .SetContentTitle("Smart Office")
    .SetContentText(message)
    .SetAutoCancel(true)
    .SetContentIntent(pendingIntent)
    .SetOngoing(false);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(NOTIFICATION_AlARM_ID, notificationBuilder.Build());

protected override void OnNewIntent(Intent e)
{
    base.OnNewIntent(e);
    if (e.Extras != null)
    {
        string fence = e.Extras.GetString("fence");
        if (!string.IsNullOrEmpty(fence))
        {
            LocationService.FenceAction action = Newtonsoft.Json.JsonConvert.DeserializeObject<LocationService.FenceAction>(fence);
            // 后续签到逻辑
        }
    }
}

iOS具体实现步骤

1. 给通知添加携带Fence数据的UserInfo

iOS通过UNMutableNotificationContent.UserInfo存储自定义数据,逻辑和Android Extras一致,先将Fence对象序列化为JSON字符串:

// 修改通知内容创建代码,添加UserInfo
UNMutableNotificationContent notificationContent = new UNMutableNotificationContent();
notificationContent.Title = "Entered region";
notificationContent.Body = "You have entered region " + fence.title + ". Touch here to check-in.";

// 序列化Fence对象为JSON字符串,存入UserInfo
string fenceJson = Newtonsoft.Json.JsonConvert.SerializeObject(fence);
notificationContent.UserInfo = new NSDictionary("fence", new NSString(fenceJson));

RegisterNotification(notificationContent, "LocationStatus");

2. 配置通知点击的响应逻辑

设置UNUserNotificationCenter的代理,处理通知点击事件。在AppDelegate的FinishedLaunching方法中添加代理设置:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    // 其他初始化代码...
    
    UNUserNotificationCenter.Current.Delegate = this;
    return true;
}

实现UNUserNotificationCenterDelegate的核心方法,覆盖APP不同状态下的通知处理:

// APP在前台时收到通知的处理(可选,按需配置显示方式)
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
    // 允许显示通知横幅和声音
    completionHandler(UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Sound);
}

// 点击通知后的核心响应逻辑
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
    // 从UserInfo中取出Fence的JSON数据
    var userInfo = response.Notification.Request.Content.UserInfo;
    NSString fenceJson = userInfo.ValueForKey(new NSString("fence")) as NSString;
    if (fenceJson != null && !string.IsNullOrEmpty(fenceJson.ToString()))
    {
        // 反序列化为Fence对象
        Fence fence = Newtonsoft.Json.JsonConvert.DeserializeObject<Fence>(fenceJson.ToString());
        
        // 获取根ViewController,传递Fence对象完成签到
        UIWindow window = UIApplication.SharedApplication.KeyWindow;
        if (window.RootViewController is UINavigationController navController)
        {
            // 假设签到逻辑在CheckInViewController中
            if (navController.TopViewController is CheckInViewController checkInVC)
            {
                checkInVC.CompleteCheckIn(fence);
            }
            else
            {
                // 跳转至签到页面
                CheckInViewController newCheckInVC = new CheckInViewController();
                newCheckInVC.TargetFence = fence;
                navController.PushViewController(newCheckInVC, true);
            }
        }
        else if (window.RootViewController is CheckInViewController checkInVC)
        {
            checkInVC.CompleteCheckIn(fence);
        }
    }
    
    // 必须调用完成回调
    completionHandler();
}

3. 处理APP未启动时的通知点击

如果APP未启动时点击通知,启动参数会传入FinishedLaunching的options,需额外处理:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    UNUserNotificationCenter.Current.Delegate = this;
    
    // 处理未启动状态下的通知参数
    if (options != null)
    {
        // 处理旧版本地通知(iOS9及以下,可选)
        if (options.ContainsKey(UIApplication.LaunchOptionsLocalNotificationKey))
        {
            UILocalNotification notification = options[UIApplication.LaunchOptionsLocalNotificationKey] as UILocalNotification;
            if (notification != null)
            {
                NSString fenceJson = notification.UserInfo.ValueForKey(new NSString("fence")) as NSString;
                if (fenceJson != null)
                {
                    Fence fence = Newtonsoft.Json.JsonConvert.DeserializeObject<Fence>(fenceJson.ToString());
                    // 可将Fence存入全局变量,待ViewController初始化后传递
                }
            }
        }
    }
    
    return true;
}

4. ViewController中实现签到逻辑

在目标ViewController中添加接收Fence的方法或属性:

public class CheckInViewController : UIViewController
{
    public Fence TargetFence { get; set; }
    
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        if (TargetFence != null)
        {
            CompleteCheckIn(TargetFence);
        }
    }
    
    public void CompleteCheckIn(Fence fence)
    {
        // 实现具体签到逻辑,如提交服务器等
        Console.WriteLine($"完成区域签到:{fence.title}");
    }
}

关键说明

  • iOS的UserInfo仅支持符合NSCoding协议的对象,用JSON字符串序列化是最通用的兼容方案。
  • 代理方法必须添加[Export]标记,否则系统无法触发回调。
  • 需覆盖APP前台、后台、未启动三种状态的处理逻辑,确保参数传递无遗漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:35:58