I'm creating an iMessage extension where for the expanded presentation style I want to use a UINavigationController
. I'm trying to add the navigation controller as a subview of the MSMessagesAppViewController
using the function below:
private func present(viewController: UIViewController) {
viewController.view.frame = view.frame
addChildViewController(viewController)
viewController.didMove(toParentViewController: self)
view.addSubview(viewController.view)
}
I was expecting the navigation controller to be displayed in traditional fashion, with its navigation bar starting just below the top bar of iMessage itself. Please see the following illustration for my expected result:
However, it seems view.frame
actually extends underneath the iMessage top bar. As such, the navigation bar of my navigation controller is hidden underneath the top bar of iMessage. The content view of the scroll view itself is however positioned correctly without further customization. Please see the following illustration for the actual result:
Obviously, I could set the frame of the navigation controller to begin just below the top bar. However I'm looking for solutions that does not rely too much on hard coded positions. If doing this, the scroll view will also not continue underneath the iMessage top bar for that translucent effect.
Ideally the navigation bar will be displayed just below the iMessage top bar, just like the scroll view does by default.
Does anyone know a solution to this?
After a bit of deliberation, I have found one quite hacky solution. I'm still accepting feedback and other answers.
One can achieve the above by creating a preliminary layoutView
, which is constrained to the layout guides using AutoLayout
. Then, by setting the UINavigationController
's frame to match that of the layout view, it will in effect only occupy the visible area.
You can set up a view like mine using Storyboard
as follows:
Then in your container view controller (createStickerViewController
in my case) simply assign the frame of your UINavigationController
to that of your layout view as soon as the constraints have been satisfied:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Update frame after constraints have been satisfied for layoutView
pickAssetNavigationController.view.frame = layoutView.frame
}
The result is that the navigation controller only occupies that actual visible area, and as such the navigation bar is placed just below the iMessage top bar as expected (refer to figure 1 in original question).