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
相关产品推荐
相关产品推荐

