iOS 13 In Tab Bar child view controller viewWillAppear is not called - ios

I have a tab bar controller and I have added five view controllers in it like this:
class InfluencerMainTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let findWorkVC = UINavigationController.init(rootViewController: InfluencerFindWorkVC.instantiate(fromAppStoryboard: .Influencer))
findWorkVC.tabBarItem = UITabBarItem(title: nil, image: #imageLiteral(resourceName: "ic_home"), tag: 0)
let inboxVC = UINavigationController.init(rootViewController: InfluencerInboxVC.instantiate(fromAppStoryboard: .Inbox))
inboxVC.tabBarItem = UITabBarItem(title: nil, image: #imageLiteral(resourceName: "ic_inbox"), tag: 1)
let workDiaryVC = UINavigationController.init(rootViewController: InfluencerWorkDiaryVC.instantiate(fromAppStoryboard: .Influencer))
workDiaryVC.tabBarItem = UITabBarItem(title: nil, image: #imageLiteral(resourceName: "ic_work"), tag: 2)
let notificationsVC = InfluencerNotificationsVC.instantiate(fromAppStoryboard: .Influencer)
notificationsVC.tabBarItem = UITabBarItem(title: nil, image: #imageLiteral(resourceName: "ic_notification"), tag: 3)
let accountVC = InfluencerProfileVC.instantiate(fromAppStoryboard: .Influencer)
accountVC.tabBarItem = UITabBarItem(title: nil, image: #imageLiteral(resourceName: "ic_profile"), tag: 4)
let tabBarList = [findWorkVC, inboxVC, workDiaryVC, notificationsVC, accountVC]
viewControllers = tabBarList
self.tabBar.tintColor = UIColor.appPurpleColor
self.tabBar.barTintColor = UIColor.white
}
}
Problem is my first controller, which is findWorkVC, its viewWillAppear is getting called but when I click on any other view controller, their viewWillAppear are not getting called.
It is working fine pre iOS 13 devices but on iOS 13 its not just getting called and also the height of navigation bar is lesser than iOS 12's navigation bar height, you can see the title in navigation bar is just overlapping the status bar text.

I created a new project and tested out everything, view controllers with tabs, everything was working there but not in my project so I started looking for the things which were different in my project than a newly created project.
Turns out, it was the root view controller. I was setting root view controller like this with animation
let controller = InfluencerMainTabBarController.instantiate(fromAppStoryboard: .Main)
UIView.transition(from: self.view, to: controller.view, duration: 0.6, options: [.transitionFlipFromTop], completion: { completed in
UIApplication.shared.keyWindow?.rootViewController = controller
})
So I simply presented the view controller with modalPresentationStyle = .fullScreen without animation and everything worked.
let controller = InfluencerMainTabBarController.instantiate(fromAppStoryboard: .Main)
controller.modalPresentationStyle = .fullScreen
DispatchQueue.main.async { UIApplication.shared.keyWindow?.rootViewController = controller }
Now I only have to look for how to set root view controller with animation. :|

If your presentation style is not the new default by Apple (sheet), than just set the presentation style for all your ViewControllers (NavigationController included) to FullScreen. This way the viewWillAppear method will be called again for every VC.

Related

iOS Swift navigation title is not showing up

I have a tabBarController under which I loaded some navigation controller. But the title of my navigation controller is not showing up. Even I noticed if I add buttons in my left and right navbar item, it doesn't show up as well.
My Tabbar Setup:
let quranNavigationController = UINavigationController()
// quranNavigationController.navigationBar.titleTextAttributes = textAttributes
// quranNavigationController.navigationBar.tintColor = Colors.primaryTextColor
// quranNavigationController.navigationBar.barTintColor = Colors.navigationBackgroundPrimary
let quranSnackBarController = AppSnackbarController(rootViewController: quranNavigationController)
quranSnackBarController.shouldExtend = false
quranSnackBarController.tabBarItem = UITabBarItem(title: "Books".localized(), image: UIImage(named: "quran"), tag: 1);
let menuViewController = TestViewController()
let quranController = QuranPrintController()
let sideMenuController = SideMenuController(contentViewController: quranController, menuViewController: menuViewController)
quranNavigationController.viewControllers = [sideMenuController]
tabBarController.viewControllers = [homeNavigationController2, quranSnackBarController, prayerNavigationController, duaSnackBarController]
window.rootViewController = tabBarController
QuranPrintController:
class QuranPrintController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Quran"
self.navigationItem.title = "Prayer Times"
}
}
This is what my output is. No title is shown. I tried adding buttons on the left and right sides. But didn't work as well
First make sure your tabbarcontroller is embedded with navigation controller and then your all controllers are connected with your navbar
like this
then embed your navigation controllers with your each view controller with seperate navigController
Try Add this in your ViewdidLoad() .
self.view.bringSubviewToFront(yourbuttonname)

UITabBarItem's title does not shown when using with Navigation controller

I'm having a trouble with my very simple app.
My app simply have 2 mains UIViewControllers called News and Category, each of them has their own UINavigationController.
So in AppDelegate.swift, I've done like this
window = UIWindow(frame: UIScreen.main.bounds)
let tabBarController = UITabBarController()
let newsVC = NewsVC()
// CREATE TAB BAR ITEM WITH TITLE ONLY
let newsVCTabBarItem = UITabBarItem(title: "News", image: nil, tag: 1)
newsVC.tabBarItem = newsVCTabBarItem
let categoryVC = CategoryVC()
// CREATE TAB BAR ITEM WITH TITLE ONLY
let categoryVCTabBarItem = UITabBarItem(title: "Category", image: nil, tag: 2)
categoryVC.tabBarItem = categoryVCTabBarItem
let rootViewControllers = [newsVC, categoryVC]
// CREATE NAVIGATION CONTROLLER FOR EACH OF THEM
tabBarController.viewControllers = rootViewControllers.map {
UINavigationController(rootViewController: $0)
}
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
When I run this simple application, the tab bar items do not show anything :(
But when I change the UITabBarItem to system's styles like this
let newsVCTabBarItem = UITabBarItem(tabBarSystemItem: .featured, tag: 1)
It's working perfectly! So hard to understand!
So does anyone know why my title-only tab bar item does not working? Have I missed something important?
Thanks in advance!
Add title property to the ViewControllers to show the title in UITabBarItem.
var title: String? { get set }
Set the title to a human-readable string that describes the view. If
the view controller has a valid navigation item or tab-bar item,
assigning a value to this property updates the title text of those
objects.
let newsVC = ViewController()
newsVC.title = "News"
.....
let categoryVC = ViewController2()
categoryVC.title = "Category"
.....
Or
Assign an image to the UITabBarItem to see the result.
let newsVCTabBarItem = UITabBarItem(title: "News", image: UIImage(named: "news.png"), tag: 1)
....
let categoryVCTabBarItem = UITabBarItem(title: "Category", image: UIImage(named: "category.png"), tag: 2)
.....
Update:
Tab bar items are configured through their corresponding view
controller. To associate a tab bar item with a view controller, create
a new instance of the UITabBarItem class, configure it appropriately
for the view controller, and assign it to the view controller’s
tabBarItem property. If you don't provide a custom tab bar item for
your view controller, the view controller creates a default item
containing no image and the text from the view controller’s title
property.

Load a Tabbarcontroller when button is clicked

Im doing an application which is a tab bar controller app with tab bar items (Search, Login, More). After successful login of user tab bar changes to (Search, Account, More) with a Logout button in More. The problem is when Logout is clicked it should load SearchViewController and if again Login is clicked in tab bar the corresponding Login page doesn't show. It shows a black screen.
#IBAction func btnLogOutClicked(_ sender: UIButton)
{
let hm = SearchVC()
let tabOneBarItem = UITabBarItem(title: "Search", image: UIImage(named: "TabHome.png"), selectedImage: UIImage(named: "TabHome.png"))
hm.tabBarItem = tabOneBarItem
let lgn = LoginVC()
let tabOneBarItem1 = UITabBarItem(title: "Login", image: UIImage(named: "tabAcc.png"), selectedImage: UIImage(named: "tabAcc.png"))
lgn.tabBarItem = tabOneBarItem1
let mropt = MoreVC()
mropt.tabBarItem = UITabBarItem(tabBarSystemItem: .more, tag: 2)
let controllers = [hm, lgn, mropt]
self.tabBarController?.viewControllers = controllers
self.tabBarController?.selectedIndex = 0
}
How would I make a tab bar controller display when Logout is clicked and clicking the tab bar item should display corresponding view controller.
You have to load every vc like this after giving each one a storyboard identifier
let hm = storyBoard.instantiateViewController(withIdentifier: "SearchVC") as! SearchVC
This
let hm = SearchVC()
Is used when the vc is created programmatically , and it's the main reason for black screen as the vc is loaded without it's layout
There are some ways to load view of view controllers:
from nib files (use public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?))
from storyboards (use UIStoryboard to instantiate view controller)
load it directly (usually programmatically) by overriding loadView()
The default init method such as SearchVC() will call init(nibName: nil, bundle: nil) for you. What's going on in this case is here.
You have to use only first two option to load view from nib or storyboard correctly.
View Management is here to see more.

Segue not working after setting up custom navigationBar

I am performing a segue from my loadVC to containterVC in which I set up a navigationController and set it's rootViewController to mainVC
Code in viewDidLoad in containterVC:
override func viewDidLoad() {
super.viewDidLoad()
mainVC = UIStoryboard.mainVC() //This is an extension to UIStoryboard
//Setting up the delegate:
mainVC.delegate = self
//rootViewController - ten najbardziej na dole
myNavigationController = UINavigationController(rootViewController: mainVC)
//Storing the root view as currentViewController:
self.currentViewController = mainVC
myNavigationController.addChildViewController(mainVC)
self.view.addSubview(myNavigationController.view)
addChildViewController(myNavigationController)
myNavigationController.didMoveToParentViewController(self)
//Trying to set up the navigation bar
let bar = myNavigationController.navigationBar
//Navigation bars:
bar.barTintColor = UIColor.blackColor()
bar.tintColor = UIColor.whiteColor()
bar.translucent = false
}
I launch the project. And? Everything works properly.
Then I try to add these under "bar.translucent = false" line:
print("statement1")
let menuButton = UIBarButtonItem(title: "Menu", style: UIBarButtonItemStyle.Plain, target: self, action: "")
print("statement2")
let item = myNavigationController.navigationItem
print("statement3")
item.leftBarButtonItem = menuButton
print("statement4")
bar.items = [item]
print("statement5")
After launching the project print statements up to 4 are displayed and the 5th is not. So it seems that the segue between loadVC and containterVC is done, but I don't see the mainVC screen that was set up as a rootViewController.
When I delete "bar.items = [item]" line the project is run as it should be, but there is no "Menu" button in the navigation bar.
What am I doing wrong?
You can just use a "container view" from the storyboard and embed a UINavigationController with your mainVC directly within the storyboard.
Anyway i think that myNavigationController.addChildViewController(mainVC) not necessary.
Also the bar items should be set to the mainVC's navigationItem, not the navigationController's one.
Also you did not mention what kind of segue are you using.

Programmatically embed view instance into navigation controller

I created a tab bar controller in which I used in the code:
let TV0000 = self.storyboard!.instantiateViewControllerWithIdentifier("V0003") as! V0003
self.setViewControllers([TV0000], animated: true)
let T0000 = UITabBarItem(title: D0000, image: nil, tag: 0)
TV0000.tabBarItem = T0000
But now i would like to have TV000 embedet into a navigation controller how I tryed to do it is by : (N is my custum nav controller class)
let N = self.storyboard!.instantiateViewControllerWithIdentifier("N") as! N
N.pushViewController(viewController: TV0000, animated: true)
self.setViewControllers([N], animated: true)
let T0000 = UITabBarItem(title: D0000, image: nil, tag: 0)
N.tabBarItem = T0000
All of this works fine the problem that I'm having is that the push of the navigation controller only seems to be non permanent and does not act like being embedded because when I go to another tab and come back the navigation bar is gone or it crash.
How could I make a Programmatic version of embeding the view controller instance into a new navigation controller instance ?

Resources