Opening ViewController In AppDelagate While Keepin

2019-01-20 13:49发布

In my Xcode project when a user taps on a notification I want to first send them to a certain item in my tabBar then I want to instantiate a view controller and send an object over to that view controller. I have code the that sends them to the tabBar I want, but I do not know how to instantiate them to the view controller while keeping the tabBar and navigation bar connected to the view controller. All the answers on this require you to change the root view controller and that makes me lose connection to my tabBar and navigation bar when the view controller is called.

A Real Life Example of this: User receives Instagram notification saying "John started following you" -> user taps on notification -> Instagram opens and shows notifications tab -> quickly send user to "John" profile and when the user presses the back button, it sends them back to the notification tab

Should know: The reason why I'm going to a certain tab first is to get that tab's navigation controller because the view controller I'm going to does not have one.

Here's my working code on sending the user to "notifications" tab (I added comments to act like the Instagram example for better understanding):

if let tabbarController = self.window!.rootViewController as? UITabBarController {
    tabbarController.selectedViewController = tabbarController.viewControllers?[3] //goes to notifications tab
    if type == "follow" { //someone started following current user                            
        //send to user's profile and send the user's id so the app can find all the information of the user                    
    }
}

3条回答
Fickle 薄情
2楼-- · 2019-01-20 14:26

In my last live project, I'm using the same approach like yours. So even though I doubt this method is the correct or ideal for handling a push notification from the AppDelegate (I still got a lot of stuff to learn in iOS

查看更多
叼着烟拽天下
3楼-- · 2019-01-20 14:34

I can think of two ways to do that:

1) If that view controller is a UINavigationController you can simply push the profile from wherever you are:

if let tabNavigationController = tabbarController.viewControllers?[3] as? UINavigationController {
    tabbarController.selectedViewController = tabNavigationController
    let profileViewController = ProfileViewController(...)
    // ... set up the profile by setting the user id or whatever you need to do ...
    tabNavigationController.push(profileViewController, animated: true)    // animated or not, your choice ;)
}

2) Alternatively, what I like to do is control such things directly from my view controller subclass (in this case, PostListViewController). I have this helper method in a swift file that I include in all of my projects:

extension UIViewController {
    var containedViewController: UIViewController {
        if let navController = self as? UINavigationController, let first = navController.viewControllers.first {
            return first
        }
        return self
    }
}

Then I would do this to push the new view controller:

if let tabViewController = tabbarController.selectedViewController {
    tabbarController.selectedViewController = tabViewController
    if let postListViewController = tabViewController.containedViewController as? PostListViewController {
        postListViewController.goToProfile(for: user)    // you need to get the user reference from somewhere first
    }
}
查看更多
混吃等死
4楼-- · 2019-01-20 14:43

First of all, you'll to insatiate a TabBarController:

let storyboard = UIStoryboard.init(name: "YourStoryboardName", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourTabBarController") as! UITabBarController

And then insatiate all of the viewControllers of TabBarController. If your viewControllers is embedded in to the UINavigationController? If so, you'll to insatiate a Navigation Controller instead:

let first = storyboard.instantiateViewiController(withIdentifier: "YourFirstNavigationController") as! UINavigationController
let second = storyboard.instantiateViewiController(withIdentifier: "YourSecondNavigationController") as! UINavigationController
let third = storyboard.instantiateViewiController(withIdentifier: "YourThirdNavigationController") as! UINavigationController

Also you should instantiate your desired ViewController too:

let desiredVC = storyboard.instantiateViewController(withIdentifier: "desiredVC") as! ExampleDesiredViewController

Make all of the NavigationControllers as viewControllers of TabBarController:

tabBarController.viewControllers = [first, second, third]

And check: It's about your choice.

if tabBarController.selectedViewController == first {

// Option 1: If you want to present
first.present(desiredVC, animated: true, completion: nil)

// Option 2: If you want to push
first.pushViewController(desiredVC, animated. true)

}

Make tabBarController as a rootViewController:

self.window = UIWindow.init(frame: UIScreen.main.bounds)   
self.window?.rootViewController = tabBarController
self.window?.makeKeyAndVisible()

Finally: It's your completed code:

func openViewController() {

let storyboard = UIStoryboard.init(name: "YourStoryboardName", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourTabBarController") as! UITabBarController

let first = storyboard.instantiateViewiController(withIdentifier: "YourFirstNavigationController") as! UINavigationController
let second = storyboard.instantiateViewiController(withIdentifier: "YourSecondNavigationController") as! UINavigationController
let third = storyboard.instantiateViewiController(withIdentifier: "YourThirdNavigationController") as! UINavigationController

let desiredVC = storyboard.instantiateViewController(withIdentifier: "desiredVC") as! ExampleDesiredViewController

tabBarController.viewControllers = [first, second, third]

if tabBarController.selectedViewController == first {

// Option 1: If you want to present
first.present(desiredVC, animated: true, completion: nil)

// Option 2: If you want to push
first.pushViewController(desiredVC, animated. true)

}

self.window = UIWindow.init(frame: UIScreen.main.bounds)   
self.window?.rootViewController = tabBarController
self.window?.makeKeyAndVisible()

}

If you want to present or push ViewController when the notification is tapped? Try something like that:

extension AppDelegate: UNUserNotificationCenterDelegate {

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        switch response.actionIdentifier {
        case UNNotificationDefaultActionIdentifier:
            openViewController()
            completionHandler()

        default:
            break;
        }
    }
}
查看更多
登录 后发表回答