Andrew Ebling
Andrew Ebling

Reputation: 10283

Clean view controller dismissal on iPhone & iPad

I have a UIViewController subclass for editing object detail which is pushed onto a UINavigationController on iPhone.

On iPad it is the root view controller in a UINavigationController, presented with a presentationStyle of UIModalPresentationPopover. In other words, the presentation is push on iPhone and modal/popover on iPad.

So the presentation is done as follows in code:

iPhone:

self.navigationController.pushViewController(detailVC, animated: true)

iPad:


let nc = UINavigationController(rootViewController: detailVC)
nc.modalPresentationStyle = .popover
self.present(nc, animated: true)

I'm revisiting the code which dismisses this view controller; it needs to pop the navigation stack on iPhone or dismiss the popover on iPad.

At the moment the code is as follows:

        if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.phone {
            self.navigationController?.popViewController(animated: true)
        } else {
            self.presentingViewController?.dismiss(animated: true, completion: nil)
        }

But it strikes me there is almost certainly a cleaner solution - probably API call which does the right thing on both platforms, for both contexts, without having to switch behaviour according to the device idiom.

Is there a cleaner/non-device-specific/more idiomatic way to handle dismissal of this view controller on both iPhone & iPad?

I was hoping and expecting self.presentingViewController?.dismiss() to work for both cases, but it does not.

I appreciate the presentation code may need adapting for the most correct approach to both presentation and dismissal.

Upvotes: 1

Views: 86

Answers (1)

AamirR
AamirR

Reputation: 12208

I can't guess if following are cleaner ways, but non-device-specific and I intend to provide just other ways to do this

When presenting a UIViewController as UINavigationController's rootVC, you can check on dismissal action

if self.navigationController?.viewControllers.first === self {
    dismiss(animated: true, completion: nil)
} else {
    self.navigationController?.popViewController(animated: true)
}

Alternatively, you can have 2 actions for both cases

@objc func popAction() {
    self.navigationController?.popViewController(animated: true)
}

@objc func dismissAction() {
    dismiss(animated: true, completion: nil)
}

Upvotes: 1

Related Questions