在 Xamarin iOS 中的远程通知的“默认用户操作”上推送视图控制器
Posted
技术标签:
【中文标题】在 Xamarin iOS 中的远程通知的“默认用户操作”上推送视图控制器【英文标题】:Push View Controller on Remote Notification's 'Default User Action' in Xamarin iOS 【发布时间】:2019-02-19 20:58:24 【问题描述】:我已经设置了远程通知并向有效负载添加了一些自定义键,如果用户点击通知并想要阅读有关该主题的更多信息,这些键将提供在主页上推送特定详细信息 ViewController 的选项。
例如:linkType: "services"
和 linkPost: "main"
会告诉我的应用在应用进入前台时推送主服务页面。
我可以成功访问我的变量 topicValue
、linkType
和 linkPost
中的键和值,但是当用户点击通知时,我无法调试代码所采用的路径,因此我知道何时何地推送正确的 ViewController。我正在使用 Xamarin.Essentials 包,所以我可以 Get
和 Set
这些键值对。我可以在整个应用程序的任何地方访问它们。
public class MyNotificationCenterDelegate : UNUserNotificationCenterDelegate
public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
if (response.IsDefaultAction)
var userInfo = response.Notification.Request.Content.UserInfo;
string topicValue = userInfo.ObjectForKey(new NSString("topic")).ToString();
string linkType = userInfo.ObjectForKey(new NSString("linktype")).ToString();
string linkPost = userInfo.ObjectForKey(new NSString("linkpage")).ToString();
Preferences.Set("linkType", linkType);
Preferences.Set("linkPost", linkPost);
我最初尝试在 AppDelegate 的 FinishedLaunching
方法中使用 launchOptions
参数,但是当我设置断点时,当我点击远程通知时它们似乎没有命中。在 Xamarin.ios 中完成此任务的任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:两件事(后台状态或非活动状态)
如果您的应用在后台不可用并且您使用通知,那么您应该使用DidFinishLaunching
对于这种情况,您应该设置来自通知的密钥。您将从launchOptions 中获得该密钥。
比较HomeViewController
中viewWillAppear
中的那个键,如果键匹配,则输入RedirectScreen
代码。
例如:- linkType: "services"
如果您的应用在后台可用并且通知来了,则 DidReceiveNotificationResponse 调用,您可以重定向应用中的任何屏幕。
首先,您应该获取topMostViewController
,然后使用此控制器重定向到任何屏幕。
例如:- 获取topMostViewController
public static UIViewController GetTopViewController()
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
vc = vc.PresentedViewController;
if (vc is UINavigationController navController)
vc = navController.ViewControllers.Last();
return vc;
【讨论】:
谢谢尼莱什!当应用程序在后台时,这有助于解决DidReceiveNotificationResponse
中的问题。当用户在应用处于非活动状态时点击通知时,我的应用仍然崩溃。我正在使用 Microsoft App Center 检查崩溃日志,因为当您关闭要测试的应用程序时,调试模式在 VS for Mac 中停止。应用程序在DidReceiveNotificationResponse
方法中崩溃!因此,在我的 iOS12 设备上,DidReceiveNotificationResponse
在应用程序处于非活动状态时也会被调用。如果不能使用断点,很难调试它,所以我会在发现更多信息时更新线程。
当应用处于非活动状态时,应用在条件逻辑if (response.IsDefaultAction)
内DidReceiveNotificationResponse
内更具体地崩溃。该条件逻辑是我选择将哪个详细视图控制器推送到 Home NavigationController 或选择特定 TabBarController 索引来导航用户的地方。我假设我的窗口或 tabcontroller 或全部为空,因为应用程序来自非活动状态而不是后台状态......现在在没有调试和断点的情况下解决所有问题......
崩溃,因为当应用处于非活动状态而不是找不到最顶层控制器时,解决方案是检查状态!= 非活动确实收到远程通知,因此当应用来自非活动状态时,应用不会崩溃。 【参考方案2】:
这是针对我的特定用例的解决方案。再次感谢 Nilesh 帮助我到达这里 :)
public class MyNotificationCenterDelegate : UNUserNotificationCenterDelegate
UIViewController detailViewController;
public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
UIApplication application = UIApplication.SharedApplication;
if (response.IsDefaultAction)
var userInfo = response.Notification.Request.Content.UserInfo;
string linkType = userInfo.ObjectForKey(new NSString("linktype")).ToString();
string linkPost = userInfo.ObjectForKey(new NSString("linkpage")).ToString();
//I'm using Xamarin.Essentials package to manage my User Defaults Key Value pairs with the
// Preferences method. Then I can see if those keys are set or not in ViewDidLoad in
// my HomeViewController. This covers the case if the app had been closed
//when the notification is tapped.
Preferences.Set("linkType", linkType);
Preferences.Set("linkPost", linkPost);
var window = UIApplication.SharedApplication.KeyWindow;
var tc = window.RootViewController as UITabBarController;
if(tc != null)
//this is essential. if app was in background then `tc != null` and this logic can run here.
//If the app was closed and `tc == null` then this logic will be carried out at the end of my
// ViewDidLoad method in my HomeViewController instead of this method.
// carry out your logic for your app to either push a view controller or
// select a TabBarController index ...
//if you are pushing a detail view controller on your Home Navigation Controller
var homeNavController = tc.ChildViewControllers[0] as UINavigationController;
homeNavController.PushViewController(detailViewController, true);
tc.SelectedIndex = 0; //select my HomeViewController via TabBarController index
//HomeViewController is where I'm pushing the detail controller so I want to make to navigate in case the user backgrounded the app on another TabBarController index.
completionHandler();
因此,除此之外,我还需要在我的ViewDidLoad
方法的末尾在HomeViewController
中执行相同的导航逻辑(选择要推送的视图控制器或要选择的TabBarController 索引)。您可以访问设置的首选项键以选择导航位置。这涵盖了当用户点击通知时应用程序被关闭的情况。
希望这可以帮助其他人尝试在 Xamarin.iOS 中通过远程通知完成这种类型的“深度链接”!
【讨论】:
以上是关于在 Xamarin iOS 中的远程通知的“默认用户操作”上推送视图控制器的主要内容,如果未能解决你的问题,请参考以下文章