Reputation: 1470
I have a UITableViewController
that, when presented from one screen, is presented with the standard 'show' segue from right to left, and when presented from another screen (a UIViewController
), is presented modally from the bottom. I got this to work properly with the help I got from a question I asked a few months ago (has screenshots).
The key was creating the segue from the UINavigationController
of my Settings screen to the shared UITableViewController
instead of creating it from the UITableViewCell
. Strangely though, even though it presents correctly from right to left, dismissing it closes it modally (top to bottom).
I'm making the presenting table view controller a delegate of the UITableViewController
it's presenting so it will handle the dismissal. Here's the protocol and extension it implements (Swift 2.3):
protocol DismissalDelegate : class {
func selectionDidFinish(controller: UIViewController)
}
extension DismissalDelegate where Self: UIViewController {
func selectionDidFinish(viewController: UIViewController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
And I set it in the segue defined in the presenting controller:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "goToLifts" {
let destination = segue.destinationViewController as! LiftSelectionTableViewController
destination.dismissalDelegate = self
} else {
return
}
}
The presented table view controller calls delegate?.selectionDidFinish(self)
when the user makes a selection (in didSelectRowAtIndexPath
):
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
guard (dismissalDelegate != nil ) else {
return
}
dismissalDelegate?.selectionDidFinish(self)
}
That calls this method in the presenting table view controller:
func selectionDidFinish(controller: LiftSelectionTableViewController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
I've looked through the APIs for presenting view controllers and haven't been able to find anything that exposes options to control this. The dismiss(animated:completion:)
API even says it's for dismissing a view controller presented modally, but I don't see anything else having to do with dismissal.
How can I get this thing to dismiss the same way it's presented when it's presented from my UITableViewController
(right to left, and back) but keep the modal behavior when presented from the other view (a UIViewController
)?
Upvotes: 1
Views: 601
Reputation: 42598
I'm a little confused here, it looks like you are using the delegate because the presenting view controller should know how LiftSelectionTableViewController
got presented.
So in the table view controller, you would have
func selectionDidFinish(viewController: UIViewController) {
self.navigationController?.popViewControllerAnimated(true)
}
In the other view controller, you should have
func selectionDidFinish(viewController: UIViewController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
If I'm wrong and you can't know how the view controller was presented, then I would try checking to see if the top view controller on the navigation controller is presented view controller. Pop the view controller if it is, dismiss the view controller if it isn't.
func selectionDidFinish(viewController: UIViewController) {
if self.navigationController?.topViewController == viewController {
self.navigationController?.popViewControllerAnimated(true)
} else {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Upvotes: 1