Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 444
SagittariusA Avatar asked Mar 22 '26 19:03

SagittariusA


1 Answers

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)
}

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!