How to use the same ViewController for tabs in UITabBarController - ios

I need to have two different tabs for one UIViewController.
I implement UITabBarController programmatically.
Code below works like show me two different tabs, but when I select firstVC it has black screen, secondVC is good.
How can I use two different tabs for same ViewConetroller?
class VPTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let myWebView = WebKitViewController.storyboardInstance()
let mainVC = MainViewController.storyboardInstance()
mainVC?.tabBarItem.title = "Search"
mainVC?.tabBarItem.image = UIImage(named:"search")
let firstVC = myWebView
firstVC?.source = "first"
let accountNavigationVC = UINavigationController(rootViewController: firstVC!)
accountNavigationVC.tabBarItem.title = "First"
accountNavigationVC.tabBarItem.image = UIImage(named:"first")
let secondVC = myWebView
secondVC?.source = "second"
let myTripsNavigationVC = UINavigationController(rootViewController: secondVC!)
myTripsNavigationVC.tabBarItem.title = "Second"
myTripsNavigationVC.tabBarItem.image = UIImage(named:"Second")
let viewControllerList = [ mainVC, firstVC, secondVC ]
viewControllers = viewControllerList as? [UIViewController]
}
}

I guess you can hack it by creating two wrapper view controllers, that would contain in the view nothing else, just the myWebView's view that you want to have on both tabs. Now create two instances of this wrapper, that would both include the same myWebView as a subview.
Now you have to remember that the same view cannot be a subview of two different views (it can have only one superview). By adding the myWebView.view as a subview to a wrapper removes it from its previous superview. Therefore, you have to listen to tab changes in order to re-add it when a wrapper gets presented (each time a wrapper is presented, you have to add myWebView as a subview to the presented wrapper).

Related

Column style UISplitViewController not working properly when added to a Tab bar controller

I tried adding a split view controller with triple column style to a UITabBarController and it shows up in collapsed state. The same code works fine when I use the older style of the split view controller. How do I get the 3-column split view controller to show up correctly on a tab bar controller?
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// This works fine 🤷‍♂️
let splitViewController = SplitViewController()
splitViewController.viewControllers = [ UINavigationController(rootViewController: PrimaryViewController()) , UINavigationController(rootViewController: SecondaryViewController())]
// let splitViewController = SplitViewController(style: .tripleColumn)
// splitViewController.setViewController(UINavigationController(rootViewController: PrimaryViewController()), for: .primary)
// splitViewController.setViewController(UINavigationController(rootViewController: SecondViewController()), for: .secondary)
// splitViewController.setViewController(UINavigationController(rootViewController: SupplementaryViewController()), for: .supplementary)
// splitViewController.show(.primary)
// splitViewController.show(.secondary)
// splitViewController.show(.supplementary)
splitViewController.title = "First"
let secondViewController = SecondViewController()
secondViewController.title = "Second"
setViewControllers([
splitViewController,
secondViewController
], animated: false)
}
}
here is the link to the project: https://github.com/anirudhbandi96/SplitViewTest
This is how the new three column split view controller looks
This is how the old 2-column split view controller looks
I couldn't even get the 2 column one to work inside a UITabBarController. But, if I just make a new UIViewController, that adds as a childViewController a UISplitViewController, then everything works just fine.
class MyViewController: UIViewController {
let split = UISplitViewController(style: .doubleColumn)
override func viewDidLoad() {
super.viewDidLoad()
addChild(split)
view.addSubview(split.view)
// add in your constraints to fix to same size here
// -- here --
split.didMove(toParent: self)
}
}

Swift and Xcode. All UIViewControllers become black when added to TabBarController

I'm trying to create UITabBarController programmatically, adding multiple NavigationControllers to it. When UITabBarController contains one NavigationController - everything works as expected (see image)
But when i add multiple NavigationControllers to UITabBarController each screen becomes black (see another image )
The same black screen is shown when switching between tabs 1, 2, 3, 4 and 5.
Here's the code how UITabBarController is created
class TabBarViewController : UITabBarController{
override func viewDidLoad() {
super.viewDidLoad()
let controllers = [HistoryViewController.self, StatsViewController.self, DashboardViewController.self, ExpenseManagerViewController.self, ProfileViewController.self]
var navControllers: [UINavigationController] = []
controllers.forEach{ ctrl in
navControllers.append(getController(from: ctrl))
}
tabBar.tintColor = Color.green
viewControllers = navControllers
}
private func getController<TType: UIViewController>(from type: TType.Type) -> UINavigationController{
let ctrl = TType()
let navCtrl = UINavigationController(rootViewController: ctrl)
let ctrlName = String.init(describing: type.self).replacingOccurrences(of: "ViewController", with: String.empty)
navCtrl.tabBarItem.title = ctrlName
navCtrl.tabBarItem.image = UIImage(named: ctrlName)
navCtrl.navigationBar.topItem?.title = ctrlName
return navCtrl
}
}
Those UIViewControllers are created using "add Cocoa Touch Class" option and have assigned *.xib files with some minimum design (see one more image)
Any help regarding why all screens become black when multiple (2 and more) NavigationControllers added to TabBarController would be highly appreciated.
Thanks
Clearly you forget how to init the UIViewControllers with xib file:
private func getController<TType: UIViewController>(from type: TType.Type) -> UINavigationController{
let ctrl = TType(nibName: String.init(describing: type.self), bundle: nil)
let navCtrl = UINavigationController(rootViewController: ctrl)
First if you come from any screen then dont insert navigationbar in between that viewcontroller and tabbarcontroller and when you jump to tabbarcontroller set as rootview controller and any tab you want to open than place navigation controller in between. means dont open tabbar controller with navigationbar heirarchy but when u want to open controller with tabs then place navigation controller in between.

SwipeNavigationController framework from GitHub how to implement

so my question today is how can I add a view similar to Snapchat where you use gestures to swipe to other views: left, top, bottom, right. I'm trying to use this framework but I'm not sure how to really implement it as they haven't provided a sample project. The layout of my app is I have a signup/login view controller, from there I want it to go to another view (blue) and that's the view that I want to have the different gestures mentioned above. `import UIKit
import SwipeNavigationController
class BlueViewController: UIViewController {
let orangeVC = OrangeView()
let pinkVC = PinkView()
let greenVC = GreenView()
let purpleVC = PurpleView()
override func viewDidLoad() {
let swipeNavigationController = SwipeNavigationController(centerViewController: self)
swipeNavigationController.topViewController = self.pinkVC
swipeNavigationController.bottomViewController = self.purpleVC
swipeNavigationController.leftViewController = self.greenVC
swipeNavigationController.rightViewController = self.orangeVC
view.backgroundColor = UIColor.facebookBlueColor
}
}'
I'm also not using storyboards for this project.
The SwipeNavigationController is a UIViewController and can be pushed onto a stack or presented the same as any other UIViewController. Wherever you are creating and presenting BlueViewController, you should instead create the SwipeNavigationController as the top level object that contains BlueViewController and all of the direction view controllers. BlueViewController and all of the other directions should not know anything about the SwipeViewController. BlueViewController and all of the other directions should not know anything about each other. The SwipeNavigationController is the top level view controller, all of the view controllers associated with a direction are child view controllers of it. I'm assuming that you have a navigation controller somewhere in your flow that pushes the SwipeNavigationController. In that case, you would have something like this in whatever method you want to trigger the push. I've called it nextTapped, but I'm sure it'll be something different in your code:
func nextTapped() {
let swipeNavigationController = SwipeNavigationController(centerViewController: BlueViewController())
swipeNavigationController.topViewController = PinkViewController()
swipeNavigationController.bottomViewController = PurpleViewController()
swipeNavigationController.leftViewController = GreenViewController()
swipeNavigationController.rightViewController = OrangeViewController()
navigationController?.pushViewController(swipeNavigationController, animated: true)
}
And then remove everything from viewDidLoad in BlueViewController except for the line that sets the background color. This creates the SwipeNavigationController with all of the directional view controllers, keeping the BlueViewController as the center and then pushes it onto your view controller stack. If you don't have a UINavigationController in the view controller that is displayed before the SwipeNavigationController, you can present it modally by replacing the last line with this:
present(swipeNavigationController, animated: true, completion: nil)

navigation controller custom search bar not disappearing?

I created a custom search bar and embedding it in the navigation bar, it appears but after I push another view controller, the search bar does not get replaced with the title of the pushed view controller. The search bar stays persistent throughout all views, instead of getting replaced with a title. Perfect example is Instagram search tab, you search for a person and click on the cell, their profile is pushed and the search bar is replaced with the custom title, back button, etc.
First VC
self.customSearchBar.tag = 4
self.navigationController?.view.addSubview(customSearchBar)
Second VC
if let nav: UINavigationController = self.navigationController {
if let searchBar = nav.view.viewWithTag(4) {
searchBar.removeFromSuperview()
}
}
You shouldn't place the searchbar inside the navigationcontroller view as this view is the same instance on all pushed viewcontrollers.
Add the searchbar to the the depending view controllers ui.
To add a searchbar on navigationBar, this is the way.
self.navigationController?.navigationBar.addSubview(customSearchBar)
To remove it when you push it to other viewController. Write the following code in the secondVC that is pushed inside it's viewDidLoad() function. Also, set the tag of customSearchBar to any number (TAG)
if let nav: UINavigationController = self.navigationController {
let bar: UINavigationBar = nav.navigationBar
if let searchBar = bar.viewWithTag(TAG) {
searchBar.removeFromSuperview()
}
}
In the question, the customSearchBar is added to self.navigationController.view. To remove it, you can do the following:
if let nav: UINavigationController = self.navigationController {
if let searchBar = nav.view.viewWithTag(TAG) {
searchBar.removeFromSuperview()
}
}
Edit:
Adding and removing a UIViewController's view as a subview of other UIViewController
// for adding
let viewController: ViewController = ViewController()
self.addChildViewController(viewController)
self.view.addSubview(viewController.view)
viewController.view.bounds = self.view.bounds // better to use autolayout here
viewController.didMove(toParentViewController: self)
// for removing
if let vc = self.childViewControllers.last {
vc.willMove(toParentViewController: nil)
vc.view.removeFromSuperview()
vc.removeFromParentViewController()
}

Swift / How to fix: TableView bottom cells missing in size of the UINavigationBar

I'm using this Framework to have a moving UINavigationBar. I have the following problem with every View (since every view has a UITableView or UICollectionView - Yes this bug appears with UICollectionView, too)
The bottom of every Screen is missing in the size of the UINavigationBar.
The controller is a subclass of UIViewController.
open class SLPagingViewSwift: UIViewController, UIScrollViewDelegate
The UIViewControllers are created globally:
var settingsVC: UserSettingsVC?
Instantiated within the class that creates the controller:
appDelegate.window = UIWindow(frame: UIScreen.main.bounds)
settings = settingsStb.instantiateViewController(withIdentifier: "UserSettingsVC") as? UserSettingsV
// among other VCs
self.setItems() //sets the images at the navigationbar
let items = [itemsArray]
let controllers = [arrayOfVCs] as [UIViewController]
controller = SLPagingViewSwift(items: items, controllers: controllers, showPageControl: false)
controller.indexSelected = 1
nav = UINavigationController(rootViewController: controller)
appDelegate.window?.rootViewController = nav
appDelegate.window?.backgroundColor = cachedBlack
appDelegate.window?.makeKeyAndVisible()
The example controller is a UITableViewController. Same bug appears in every other UIViewController with a UITableView as well as in one UITableViewController with a UICollectionView.
What am I missing? Help is very appreciated.
What you need to do is create a global constant and set the UIEdgeInsetsMake(), for example:
let collectionViewInset = UIEdgeInsetsMake(0, 0, 44, 0)
44 is the height of the navigation bar, and you need to start it after the navigationBar, so y = 44.0.
After doing that you need to set:
collectionView.contentInset = collectionViewInset
And that's it, sorted!

Resources