I am new to iOS development, and am trying to learn storyboarding, Swift, and the new features of iOS 8 at the same time.
I have created a very simple storyboard that uses a Popover presentation segue to display another view. On the simulator, if I run this for an iPad, it works as expected. However, if I run it for an iPhone, instead of a popover, it displays a full-screen view, on top of the original view. This is fine; however, there is no way to dismiss it and go back to the original screen.
I have watched the WWDC 2014 video "228 A Look inside presentation controllers" and they can show a dismiss button if they build the user interface entirely with code.
I have also watched the "411 What's new in interface builder" session, where they say that this can be done in Interface Builder, but they do not show it, promising to show how to do it in the lab, if anyone is interested. Unfortunately, I did not attend WWDC 2014, or know anyone who has. My Google searches have not returned anything helpful either.
In my case, I had a small popup that I wanted to be a popup on both an iPhone and iPad - and wanted to avoid using a navigation bar with a Dismiss. Discovered that one needed to implement two delegate calls (Swift 3.0):
I am not sure why you need to do storyboard setup for the Done button, all the work can be done programmatically with few lines of code. The important part is to implement some
UIAdaptivePresentationControllerDelegate
protocol methods exactly like below:Then, a simple method to implement the dismissing behavior for the popover in case it was presented in full screen:
and you done!
Its possible to do it with mimimal code whilst putting the logic into the storyboard instead. In the view controller that presents the popover, just put in the marker method
It does not need any code but needs to be present so you can control drag to the Exit icon later on when you use interface builder.
I have my popover content not take up the entire background view but have a small margin around it. This means you can use interface builder to create a tap gesture recogniser for this view. Control drag the gesture recogniser to the Exit icon which then pops up some Exit choices, one of which is the unwindToContainerVC method as seen above.
Now any tap around the edge (such as in an iPhone 4S scenario) takes you back to the presenting view controller.
Here is the connections inspector for the gesture recogniser:
You could add the navigation controller like this-
If you really do want your view controller to always be a popover leave your storyboard the way it is and add something like this to your view controller that presents the popover-
The view controller presenting the popover will also need to respond to this
UIPopoverPresentationDelegate
methodLastly, you could do the following to only add the navigation controller to the modal presentation of your view controller on the iPhone and leave the popover on iPad without a navigation controller.
The proper place to inject the navigation controller is in
- (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style
. In order for this to be called we must set ourselves as the delegate of theUIPopoverPresentationController
. Once again we will do this inprepareForSegue:
Then we will do this in the delegate method that I mentioned above
Good Luck!
If what you want is a popover on your iPad but a modal sheet with a close button on your iPhone then you can do it without creating an extra navigation controller in storyboard for the popover.
In Xcode 6.3 storyboard, you simply hook up a view controller and designate the segue as a "Present as Popover"
The code below should go in the view controller that segues to the popover, not in the popover itself:
First you set up the popover delegate:
Then you add the delegate extension (below your view controller's code) and create the navigation controller / close button on the fly:
Then you add your dismiss function and you should be good to go: