I have created a simple tab bar with three views in storyboard. The tab bar works well, but when I try to show another view controller from a button within a tab, the new view is placed over the whole screen and also over the tab bar.
This is how I present the view so far when a button is pressed:
@IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.present(newVC!, animated: true, completion: nil)
}
The other idea I had was this:
self.tabBarController?.present(vc!, animated: true, completion: nil)
But not to my surprise this didn't work either.
So how can I present another view controller within the tab bar (so that the bottom bar is still shown)?
When you present a view controller modally, its presentation style will be "Full Screen" by default. What you want to do is have it do in this case is just cover part of the screen (the part where the presenting view controller is drawn.
One way to accomplish this is to:
Set the modalPresentationStyle
for the presented view controller to be .currentContext or .overCurrentContext
In the view controller that will be presenting the modal, set its definesContext
property to true.
These steps can be done either in Interface Builder by setting attributes on the segue and the view controller, or you can modify your code to include the following:
@IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.definesPresentationContext = true
newVC?.modalPresentationStyle = .overCurrentContext
self.present(newVC!, animated: true, completion: nil)
}
What this combination of properties does is:
Indicate for the presented view controller that you want it to be presented in a non-full screen context (some specific section of the screen)
Indicate that the presenting view controller is is the section of the screen / the context you want the modal to be drawn according to.
More details can be found in the Apple Documentation