简体   繁体   中英

Swift: how to close view controller and navigation controller launched from AppDelegate

My app iOS main skeleton works on a TabBarController . Anyway, there is an extra behavior when a notification arrives. My app does the following when a push notification is received:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    //application.applicationIconBadgeNumber = 0
    //application.cancelAllLocalNotifications()
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let notificationController = storyboard.instantiateViewControllerWithIdentifier("DynamicEventsViewController") as! DynamicEventsViewController
    notificationController.isLoadedFromNotification = true
    notificationController.eventTitle = userInfo["aps"]!["alert"] as! String
    notificationController.eventDescription = userInfo["aps"]!["message"] as! String
    let navigationController = UINavigationController()
    navigationController.pushViewController(notificationController, animated: true)
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    window!.rootViewController = navigationController
    self.window?.makeKeyAndVisible()

}

and this is the code of the relative instantiated view controller:

class DynamicEventsViewController:UIViewController {

@IBOutlet weak var upDistanceConstraint: NSLayoutConstraint!
@IBOutlet weak var dynamicEventTitle:UITextField!
@IBOutlet weak var dynamicEventDescription:UITextView!

var eventTitle:String? = nil
var eventDescription:String? = nil

var isLoadedFromNotification = false


override func viewDidLoad() {
    super.viewDidLoad()

        self.navigationItem.titleView = UIImageView(image: UIImage(named: "icons/bar.png"))
        self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()

        if (self.navigationItem.leftBarButtonItem == nil) {
            let leftButton = UIBarButtonItem(title: "Chiudi", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(DynamicEventsViewController.back(_:)))
            self.navigationItem.leftBarButtonItem = leftButton
        }

    if (self.eventTitle != nil && self.eventDescription != nil) {
        self.dynamicEventTitle.text = self.eventTitle?.uppercaseString
        self.dynamicEventDescription.text = self.eventDescription
    }
}

func back(sender: UIBarButtonItem) {
  self.navigationController?.popViewControllerAnimated(true)
}

}

Anyway if I tap the "Chiudi" button, the view controller does not close while I would like the app to come back to the TabBarController . Which is the correct way?

FINAL SOLUTION

From AppDelegate.swift in didReceiveLocal(Remote)Notification() I perform:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let notificationController = storyboard.instantiateViewControllerWithIdentifier("DynamicEventsViewController") as! DynamicEventsViewController
    notificationController.isLoadedFromNotification = true
    notificationController.eventTitle = userInfo["aps"]!["alert"] as? String
    notificationController.eventDescription = userInfo["aps"]!["message"] as? String
    notificationController.isLoadedFromNotification = true

    if let tabBarController = self.window?.rootViewController {
        tabBarController.presentViewController(notificationController, animated: true, completion: nil)
    }

while in my view controller I perform:

if (isLoadedFromNotification) {
        self.upDistanceConstraint.constant = 90

        let navigationBar:UINavigationBar = UINavigationBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 80))
        navigationBar.backgroundColor = UIColor.whiteColor()

        let navigationItem:UINavigationItem = UINavigationItem()

        let leftButton:UIBarButtonItem = UIBarButtonItem(title: "Chiudi", style: .Plain, target: self, action: #selector(DynamicEventsViewController.exit(_:)))

        navigationItem.titleView = UIImageView(image: UIImage(named: "icons/bar.png"))
        navigationItem.leftBarButtonItem = leftButton
        self.navigationItem.titleView = UIImageView(image: UIImage(named: "icons/bar.png"))

        navigationBar.items = [navigationItem]

        self.view.addSubview(navigationBar)

}

where self.upDistanceConstraint is a NSLayoutConstraint indicating the distance between the bar and the first widget in my view controller which, in my case, was a UITextField otherwise it would have been hidden by the bar.

When you receive the notification your TabBarController is already the rootViewController of your Application: you don't need to embed your notificationController into a navigation controller and can replace the code in your AppDelegate by the following:

    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let notificationController = storyboard.instantiateViewControllerWithIdentifier("DynamicEventsViewController") as! DynamicEventsViewController
    notificationController.isLoadedFromNotification = true
    notificationController.eventTitle = userInfo["aps"]!["alert"] as! String
    notificationController.eventDescription = userInfo["aps"]!["message"] as! String

    if let tabBarController = self.window?.rootViewController {
        tabBarController.presentViewController(notificationController, animated: true, completion: nil)
    }

}

Then you'll have to add a custom navigation bar on your DynamicEventsViewController (in your Storyboard) and link it to your class like so:

@IBOutlet weak var myNavigationBar: UINavigationBar

Finally you'll need to replace your back button event handler with the following:

func back(sender: UIBarButtonItem) {
        self.dismissViewControllerAnimated(true, completion: nil)
}

You can create navigation controller, but don't replace your root controller with it. Just present it from your tab bar controller without animation. When you need to hide navigation controller from notification, just dismiss it:

func showNavigation(){
    tabBarController.presentViewController(navController, animated: false) {  
    }
}

func hideNavigation() {
    tabBarController.dismissViewControllerAnimated(true) {
    }
}

tabBarController is your window?.rootViewController

Updated

Instead of

self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
window!.rootViewController = navigationController
self.window?.makeKeyAndVisible()

try this

rootTabBarController.presentViewController(navigationController, animated: true) {}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM