Reputation: 198
I'm trying to remind user to save changes on current View Controller
let's say, i've got something like this:
here, inside TabBarController, and inside Navigation Controller I've got a "Favorites" tab. I want to display an alert, if user switches to "Contacts"
The issue is that Alert is shown over destination ViewController (Contacts), so it looks very weird for user.
Tested solutions:
first, i tried to use
override func viewWillDisappear(animated: Bool) {
self.leavingAlert()
}
//inside FavoritesViewController
next, I tried:
class FavoritesViewController: UIViewController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.delegate = self
}
func leavingAlert(){
let alert = UIAlertController(title: "Alert", message: "You forgot to do something here", preferredStyle: UIAlertControllerStyle.Alert)
let alertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
alert.addAction(alertAction)
self.presentViewController(alert, animated: true, completion: nil)
}
func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
self.leavingAlert()
}
}
Same effect
Then, i tried to reach the event through the TabBarViewController:
class TabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
if let navigationController = selectedViewController as? UINavigationController {
if let activeController = navigationController.visibleViewController as? FavoritesViewController {
activeController.leavingAlert()
}
}
}
}
And one more time - same effect.
Note, that I'm not going to interrupt this UITabBarController Segue. The idea is only to ask "Save or not to save?", and if "save", then do some stuff and continue switching tab, if "don't save" - switch the tab immediately.
Thank you for any help. If there is a solution in Obj-C, please also answer, i'll try to catch the idea.
Upvotes: 2
Views: 2116
Reputation: 14030
you should subclass your UITabBarController
and let it be its own delegate. something like this should work:
class TabBarController: UITabBarController {
var viewControllerToSelect: UIViewController?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
delegate = self
}
func showLeavingAlert() {
let leavingAlert = UIAlertController(title: "Warning", message: "Do you want to save before you leave?", preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Yes", style: .Default) { (action) in
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
// switch viewcontroller after one second delay (faked save action)
self.performSwitch()
}
}
leavingAlert.addAction(saveAction)
let cancelAction = UIAlertAction(title: "No", style: .Cancel) { (action) in
// switch viewcontroller immediately
self.performSwitch()
}
leavingAlert.addAction(cancelAction)
presentViewController(leavingAlert, animated: true, completion: nil)
}
func performSwitch() {
if let viewControllerToSelect = viewControllerToSelect {
// switch viewcontroller immediately
selectedViewController = viewControllerToSelect
// reset reference
self.viewControllerToSelect = nil
}
}
}
extension TabBarController: UITabBarControllerDelegate {
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
if let navigationController = selectedViewController as? UINavigationController, _ = navigationController.visibleViewController as? FavoritesViewController {
// save a reference to the viewcontroller the user wants to switch to
viewControllerToSelect = viewController
// present the alert
showLeavingAlert()
// return false so that the tabs do not get switched immediately
return false
}
return true
}
}
Upvotes: 1
Reputation: 5066
You can create delegate for UITabBarController, and overload method:
optional func tabBarController(_ tabBarController: UITabBarController,
shouldSelectViewController viewController: UIViewController) -> Bool
If user tried switch to the viewController (from FavoritesViewController) you return false from this method and show the alert.
In one of callbacks of the alert you can switch to destination programmatically.
unowned(unsafe) var selectedViewController: UIViewController?
Upvotes: 2
Reputation: 10517
One of solution is to replace segue with regular IBAction. your button Contacts must invoke IBAction on 'touch up inside' event where you display an alert and then in alert completion handler you call performSegueWithIdentifier method of your controller.
Upvotes: 0