如何让你的推送通知打开某个视图控制器?
Posted
技术标签:
【中文标题】如何让你的推送通知打开某个视图控制器?【英文标题】:How to make your push notification Open a certain view controller? 【发布时间】:2016-06-10 16:27:53 【问题描述】:我查看了 SO,但我找不到任何讨论当您收到推送通知时如何打开特定视图控制器的问题。 例如,如果您正在创建一个像 WhatsApp 这样的应用程序并且您收到两个不同的推送通知,即来自两个不同用户的消息,您将如何从应用程序委托定向到各自的 viewController?
据我所知,appDelegate 为您提供的 userinfo 字典中,您可以为特定的 viewController 提供一个 ID,但我不知道如何向特定的 viewController 致敬,以便您可以再次指导到那个viewController。 请在您的答案中附上代码 sn-p
**** Swift 或 Objective-C 的答案都是可以接受的 ****
【问题讨论】:
【参考方案1】:您可以使用应用委托中的此代码检测应用是否从通知中打开。当应用程序状态为UIApplicationStateInactive
时,您需要在应用程序激活之前设置初始视图控制器。您可以在那里执行任何逻辑来决定应该打开哪个视图控制器以及应该在该视图控制器中显示哪些内容。
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
if(application.applicationState == UIApplicationStateActive)
//app is currently active, can update badges count here
else if(application.applicationState == UIApplicationStateBackground)
//app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
else if(application.applicationState == UIApplicationStateInactive)
//app is transitioning from background to foreground (user taps notification), do what you need when user taps here
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *viewController = // determine the initial view controller here and instantiate it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
【讨论】:
非常感谢。第三个 id 语句是您实际上从后台到前台的位置...前两个仅在没有任何 UI 交互的情况下更新模型。 对吗?。所以基本上你通过viewController的标识符链接正确吗? 对不起,我花了几天时间发表评论,这是正确的。 重新分配self.window.rootViewController
是个好主意吗?看看你的tabBar然后分配正确的selectedIndex不是更好吗?我的意思是如果你有内存泄漏然后重新分配你的标签栏,整个对象可能会留在内存中......
@Honey 是的,你是对的,但我认为即使你确实有内存泄漏并导航到正确的 selectedIndex,你仍然需要在某个时候解决内存泄漏。 p.s.我喜欢你两年后的评论:)【参考方案2】:
这是带有 switch/case 而不是 if/else 的 Swift 3 版本
open func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any])
switch application.applicationState
case .active:
print("do stuff in case App is active")
case .background:
print("do stuff in case App is in background")
case .inactive:
print("do stuff in case App is inactive")
【讨论】:
【参考方案3】://This method is called when user tap on the notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
print("user clicked on the notification")
let userInfo = response.notification.request.content.userInfo
print(userInfo)
//check your response and navigate to specific view controller
moveToNextViewController()
func moveToNextViewController()
//Add code for present or push view controller
let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier:"ViewController") as! ViewController
self.navigationController?.pushViewController(vc, animated: true)
【讨论】:
【参考方案4】:当用户点击通知时调用此方法。在 appdelegate 中实现
var navigationC: UINavigationController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
if USERDEFAULT.value(forKey: "isLogin") != nil
let tabbarvc = MainStoryboard.instantiateViewController(withIdentifier: "TabBarVC") as! TabBarVC
self.navigationC = UINavigationController(rootViewController: tabbarvc)
else
let loginvc = MainStoryboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
self.navigationC = UINavigationController(rootViewController: loginvc)
self.navigationC?.setNavigationBarHidden(true, animated: false)
self.window?.clipsToBounds = true
self.window?.rootViewController = navigationC
self.window?.makeKeyAndVisible()
return true
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any])
print("-------------\nUser info in notification -> \(userInfo)\n-------------")
let dict = userInfo["aps"] as? NSDictionary ?? [:]
if USERDEFAULT.value(forKey:"isLogin") != nil
let type = dict["type"] as? Int ?? 0
switch type
case 0:
break
case 1:
for vc in self.navigationC!.viewControllers
if vc is TabBarVc
let exam = dict["exam"] as? String ?? ""
if exam == ""
let TestVC = MainStoryboard.instantiateViewController(withIdentifier: "TestVC") as! TestVC
TestVC.chapterId = dict["chapter_id"] as? String ?? ""
TestVC.strSubTitle = dict["chapter"] as? String ?? ""
self.navigationC?.isNavigationBarHidden = true
self.navigationC?.pushViewController(TestVC, animated: true)
else if exam != ""
let ExamTestVC = MainStoryboard.instantiateViewController(withIdentifier: "ExamTestVC") as! ExamTestVC
ExamTestVC.examId = dict["exam_id"] as? String ?? ""
ExamTestVC.strSubTitle = dict["exam"] as? String ?? ""
self.navigationC?.isNavigationBarHidden = true
self.navigationC?.pushViewController(ExamTestVC, animated: true)
return;
break
case 2:
for vc in self.navigationC!.viewControllers
if vc is TabBarVc
let VideoListVC = MainStoryboard.instantiateViewController(withIdentifier: "VideoListVC") as! VideoListVC
VideoListVC.chapterId = dict["chapter_id"] as? String ?? ""
VideoListVC.video_id = dict["video_id"] as? String ?? ""
VideoListVC.strSubTitle = dict["chapter"] as? String ?? ""
VideoListVC.questionsCount = dict["question_count"] as? Int ?? 0
VideoListVC.testCount = dict["test_count"] as? Int ?? 0
self.navigationC?.isNavigationBarHidden = true
self.navigationC?.pushViewController(VideoListVC, animated: true)
return;
break
case 3:
break
default: break
else
let loginVC = SignupiPadStoryboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
SignupStoryboard = SignupiPadStoryboard
self.navigationC = UINavigationController(rootViewController: loginVC)
或者您可以直接打开视图控制器,例如whatsapp chat..等。
@available(ios 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
let userInfo = notification.request.content.userInfo
let dictAps = userInfo["aps"] as! NSDictionary
print(dictAps)
let notification_type = dictAps["notification_type"] as? Int ?? 0
if notification_type == 6
if isChatActive == false
completionHandler([.alert, .badge, .sound])
else
if USERDEFAULT.value(forKey:"isLogin") != nil
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ReloadChatMessages"), object: nil, userInfo: (dictAps as! [AnyHashable : Any]))
else
completionHandler([.alert, .badge, .sound])
else
completionHandler([.alert, .badge, .sound])
【讨论】:
以上是关于如何让你的推送通知打开某个视图控制器?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过推送通知显示带有 TabBarController 导航的视图控制器