Embed multiple view controllers in navigation controller - ios

I'm making an app for iOS based partly on storyboards and programmatically setup. The root view controller (1) is a has a scroll view. In it is two view controllers (2 and 3), and they have further navigation deeper into the app. I want it to be able to make the edge swipe from left to navigate back. When I make the first view controller and "Embed in Navigation Controller" through the Interface Builder, it dosn't enable the back swipe.
Maybe it's because I add view controller 2 and 3 to view controller 1 programmatically? But it dosn't work either if I embed view controller 3 in a navigation controller, eventhoug I have connected everything from there on via segues.
View controller 1, 3 and 5 have scrollviews embedded, maybe the swipe functions of the scrollview overrides the swipe back function?
The view controllers 2 and 3 are embedded in view controller 1 like this:
scrollView.addSubview(ViewControllerThree.view)
I havn't tried to make the navigation controller programmatically, if that posible.
Any ideas?
EDIT
I've tried doing it programmatically like this:
I add the following code to app delegate application_didFinishLaunchingWithOptions, and remove the navigation controller from my storyboard. But I have the same problem, it seems that when I seque away from view controller 2 or 3, I loose the navigation controller.
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var viewController = storyboard.instantiateViewControllerWithIdentifier("New Landing Page")
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
var nav = UINavigationController(rootViewController: viewController)
self.window?.rootViewController = nav;
self.window?.makeKeyAndVisible();

Related

TabBarController disappears when I segue back to the view from another view

I have a viewController that is embedded in a nav controller. This nav controller is then embedded in a tab bar controller.
I have another viewController that is not supposed to be accessible from the tabBarController. It should only be accessible from the first viewController using a button. From the secondViewController, I made a UIBarButtonItem to move back to the original view. From the first view to the second view and vice versa, I used a Storyboard reference to move to and from from the views.
However, when I move from the first view to the second view, the tab bar controller disappears (like it should). When I move back to the first view, the tab bar controller disappears and I cannot move between tabs anymore.
I tried including:
self.hidesBottomBarWhenPushed = false
on the first view and
self.hidesBottomBarWhenPushed = true
on the second view
and nothing seems to work. The tab bar controller disappears every time i move from the second view to the first view.
You are following a wrong hierarchy. You are actually using seagues to go back and forth. This creates a new instance every time you try to come back to the first controller.
Let's make it clear:
You need to follow the below approach:
1 You have two controllers A and B.
2 Use self.hidesBottomBarWhenPushed = true in viewDidLoad or viewWillAppear of controller A.
3 Controller A is embedded in a navigation controller which is further embedded in a UITabBarController.
Tapping a button in controller A, you need to push to controller B. So you can use segue for this or you can do it programatically like:
let controllerB = B()
A.navigationController?.pushViewController(controllerB, animated: true)
4 Go Back to Controller A on the tap UIBarButtonItem. So your code in the action of UIBarButtonItem should be something like:
self.navigationController?.popViewController(animated: true)
Remember you should not should segue to go back to the previous controller.
you should use
override func viewWillDisappear(_ animated: Bool) {
self.tabBarController?.tabBar.isHidden = false
}
in that controller where the back button is placed, I am using the exact scenario in one of the my app.

Swift: present view controller in same context as other view controllers?

Ok, I have an issue that I cant understand trying to present a view controller (the same instance every time, just like other tab item VCs) from an overall tab bar controller VC. My tab bar controller VC has 3 view controllers that it is connected to via storyboard, so 3 tab bar items appear on the tab bar. When the selectedIndex is changed, these view controllers just appear right there below the subviews of the Tab Bar Controller VC.
These subviews that should always be on top are the nav bar at the top and tab bar at bottom:
And this is great for those 3 view controllers. Problem is I need to access 1 instance of ANOTHER view controller that is NOT shown in the tab bar buttons via a button in the nav bar here.
My problem is no matter how I present it, this VC always pops OVER the tab bar controller VC, covering the tab bar and nav bar.
here I make sure only 1 instance is made:
if podcastVC == nil {
//print("IT IS NIL")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
podcastVC = storyboard.instantiateViewController(withIdentifier: "podcast") as! PodcastViewController
//*NOTE: have to set other vars too, this is temp
podcastVC.urlStr = currentTrackUrl!
podcastVC.originalUrl = currentTrackUrl!
AudioPlayerManager.shared.play(urlString: podcastVC.urlStr)
}
self.show(podcastVC, sender: self)
podcastVC.modalPresentationStyle = .currentContext
podcastVC.definesPresentationContext = false
[1]: https://i.stack.imgur.com/1d6MZ.png
as shown by Swift: How to return to the same instance of my UIViewController
How can I make that VC present in the same context as the tab bar items? I have tried setting the layer of the nav bar to a z position much higher (like 10) but nothing works. What is wrong?
Modal view :
Can works for all view controllers
Is over all other view and need to be pop programatically (adding a button back manually for example)
Push View :
Only works in navigation controllers
Add automatically a back button in the navigationController
you should push VC and it will keep tabbar and nav
you can change modal present style

Swift 3 - How do I prevent instantiated view controllers from having their background disappear behind the tab and navigation bars?

I am using Swift 3, Xcode 8.2.
I have a Storyboard with a Navigation controller and a connected Table View Controller. This table has cells that, when clicked, link to custom table view controllers that I instantiate each time.
let detailVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "dvc") as! ResultsVC
detailVC.view.backgroundColor = UIColor.white
detailVC.edgesForExtendedLayout = [];
But this newly created VC seems to have its background disappear behind the top nav bar and bottom tab bar because its colors change. How do I prevent this from happening?
This is expected behavior (I'm assuming that you're pushing the newly-instantiated VC with your navigation controller). If your views are hidden behind the navigation bar, do one of two things: 1) change the frame of your new VC's view, so that the y coord is equal to your navigation bar's height, or 2) push the views from IB, not in code, and this will be handled for you.

Present View with Navigation intact : Swift

My app has a Tinder-like functionality where I have to show a view on receiving a notification. Problem is that I'm not being able to keep the navigation hierarchy intact. My flow right now is
view1 -> Navigation controller -> view 2 -> tab bar controller -> view3, view,4 view 5...view 5-> view6 -> view 7.
I want to present a view, View 8. which has two buttons ignore and accept. Accept should present view 6 and ignore should present view 5. View5 is at index 2 of the tab bar controller.
I have achieved this by regular segues but the navigation bar disappears.
Here is my code in app delegate to present View 8 upon receiving a notification
if notifType == Const.NOTIF_MATCH_FOUND
{
let storyboard = UIStoryboard(name: "in-tune-Main", bundle: nil)
let destinationController = storyboard.instantiateViewControllerWithIdentifier("matchVC") as? matchVC
self.window?.rootViewController = destinationController
}
This takes it to view8, and loads view 6 or 5 on clicking ignore or accept but the navigation disappears.
Any ideas?

Edit button not displayed in UITabBarController's MoreNavigationController

A UITabBarController is being pushed onto the stack:
let presenter = presentingViewController as! UINavigationController
let tabvc = UITabBarController()
tabvc.viewControllers = vcs
tabvc.customizableViewControllers = vcs
presenter.pushViewController(tabvc, animated: true)
Once presented the more tab button correctly shows, but the edit button to rearrange the tab bars does not. According to the docs on the MoreNavigationController:
The interface for the standard More item includes an Edit button that
allows the user to reconfigure the tab bar. By default, the user is
allowed to rearrange all items on the tab bar. If you do not want the
user to modify some items, though, you can remove the appropriate view
controllers from the array in the customizableViewControllers
property.
My guess is that the tab bar is not happy being in a navigation controller. Any ideas on bringing the edit button back?
You can have both a UINavigationController and a UITabBarController ; using Storyboard helps understand the issue better, any of these solutions will work:
Start out with a UITabBarController as initial view controller
Use presentViewController instead of pushViewController
Use a modal Storyboard segue to perform a modal presentation
Swap out the rootViewController dynamically
Initial View Controller Design
When the Tab Bar Controller is initial View Controller, the Edit button is displayed normally.
Pushed Design
Another Navigation Controller is initial View Controller, using one of 5 adaptive Action Segue:
Show
Custom
-> No Edit button, since it is in direct conflict with the parent UITableViewController.
Show Detail
Present Modally
Popover Presentation
-> Edit button displayed as expected.
Code
1. Program Modal
Using the exact code presented in the question, change the last line:
let presenter = presentingViewController as! UINavigationController
let tabvc = UITabBarController()
tabvc.viewControllers = vcs
tabvc.customizableViewControllers = vcs
presenter.presentViewController(tabvc, animated: true, completion: nil)
2. Storyboard Modal
keeping with the Storyboard theme, create a segue of the correct type, assign an identifier (i.e. presentModallySegue) and the 5 lines above become this single line:
self.performSegueWithIdentifier("presentModallySegue", sender: self)
3. root Swap
A more drastic solution involves swapping out the root view controller at the window level:
let tabvc = UITabBarController()
tabvc.viewControllers = vcs
tabvc.customizableViewControllers = vcs
self.view.window!.rootViewController = tabvc
Conclusion
Either change your design to adopt the Tab Bar Controller as the initial View Controller, or present the Tab Bar Controller modally.
The reason is that navigation bar of your presenter overlaps with the navigation bar of More section.
If you don't show the navigation bar for you navigation controller, you will be able to see the Edit button again when you tap on the More tab.

Resources