Whats the programmatic opposite of showViewControl

2019-03-12 05:38发布

问题:

I'm writing an iOS 8 only app and I'm using the new adaptive presentations using a combination of the "Show" and the "Show Detail" segue and the showViewController:sender: and showDetailViewController:sender: methods.

My question is what is the programatic way to go back after calling showViewController:sender:? The way the view controller is shown depends on its parent context. E.g. in a UINavigationController showViewController:sender: pushes a new controller onto the navigation stack but if there is no UIKit container in the view controller graph then showViewController:sender: ends up doing a presentation instead.

Considering i could write my own arbitrary container controller it seems unfeasible to check

if (self.navigationController) {
    [self.navigationController popViewControllerAnimated:YES];
}
else if (self.presentingViewController){
...
else if ([self.parentViewController isKindOfClass:[CrazyCustomContainer class]]){
    [self.parentViewController someWackyUnwindMethod];
}
...

etc... so is there a generic way to reverse being shown? If not the only solution i see is to use unwind segues for everything. Not too much of a hassle but I'm curious.

回答1:

There is a chapter on how showViewController:sender: and showDetailViewController:sender: work in Programming iOS 8: Dive Deep into Views, View Controllers, and Frameworks.

When these methods are called, they call targetViewControllerForAction:sender: on themselves and call this method on the returned object. The target object can then display the view controller in an appropriate way. For example, a navigation controller pushes the view controller on its navigation stack.

So you can create a generic dismissVC: method and override it in different UIViewController subclasses.

extension UIViewController {
    func dismissVC(sender:AnyObject?) {
        if let presentingVC = targetViewControllerForAction("dismissVC", withSender: sender) as? UIViewController {
            presentingVC.dismissVC(self)
        }
    }
}

extension UINavigationController {
    override func dismissVC(sender: AnyObject?) {
        popViewControllerAnimated(true)
    }
}

extension CrazyCustomContainer {
    override func dismissVC(sender: AnyObject?) {
        someWackyUnwindMethod()
    }
}

This way, when you call dismissVC: method, if will always correctly dismiss the view controller depending on the context.



回答2:

Here is a trick I've used before showViewController existed that may help.

if let nav = navigationController {
    // We have a navigation controller so we'll have a back button
}
else {
    // no navigation controller, need a cancel button
    // ... Add Cancel Button
}

Basically you check for where you're at. Then after that you can put any save code in viewDidDisappear or something like that for it work for both. Another option is to check for presentationViewController but this doesn't always guarantee modal presentation.