I am using a tab bar controller and I wonder if there is a way to check which tab is being clicked?
If the user clicks on the "account" tab and is not logged in I want to redirect to a full screen modal login screen instead of the account VC.
You can do it in your custom UITabBarController or somewhere, and override the 'didSelectItem' function.
import UIKit
class TabbarViewController: UITabBarController {
override func viewDidLoad() {
}
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
print("Selected Index :\(self.selectedIndex)");
}
}
In the scenario you outlined, I would check to see if current user is logged in or not, and if not segue to the appropriate screen of your application.
UITabBarDelegate's didSelectItem
The options that others have provided are fine, but I wanted to let you know of another way. In the viewWillAppear, viewDidAppear, or viewDidLoad functions, you can call what you need to segue to a login ViewController
Related
Can I show six TabBarItem in UITabBar, I try to resize TabBarItem but it can't.
uitabbar
With default UITabBarController you can not because it will add More tab like shown below:
and you need to click on More tab to show another options.
But you can use third party library like AZTabBarController which will populate all six options as shown below:
More libraries for tab bar can found HERE.
This is against "Human Interface Guidelines", but it is possible to have as many TabBarItems as you want using tabBar without tabBarController. You may lay out tabBar and items in storyboard. To respond to taps conform to UITabBarDelegate and implement at least didSelectItem.
import UIKit
class AdminViewController: UIViewController, UITabBarDelegate {
#IBOutlet weak var tabbar: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
tabbar.delegate = self;
}
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem!) {
print(item.tag);
switch item.tag { // switching by tag is not required, just an option
case 1:
// segue or push or present something
case 2:
// segue or push or present something
default:
break
}
}
I want to perform an action when the user clicked on some tabs in UITabBar without opening another view. For example, setting tab or share.
Here is what I did :
class ViewTabBarController: UITabBarController,UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
// Do any additional setup after loading the view.
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print("do something")
}
}
This code works fine if the UITabBar has just 5 items.
But the problem here is that if UITabBar has more than 5 items those that are under the "More Tab" did not call the tabBar() function when clicked.
From the documentation description of the didSelect method of UITabBarControllerDelegate:
Tells the delegate that the user selected an item in the tab bar.
What that means is that the method is called when the user taps on one of the buttons in the bar. When you have a 'more' button then that is the button in the tab bar so tapping 'more' fires that method.
The view controllers in the 'more' section are actually processed in a different way involving the use of a UINavigationController. With these views they don't have a button in the tab bar and therefore this even is not fired.
I am working in storyboard and also programmatically do some things. First, I have created a viewController controller which is login page (first view) programmatically. But in storyboard I have a NavigationController whose root is ViewController. Everything (methods forgotPassword and loginDidFinish) worked fine, except that ViewController was viewed before controller immediately after launching the app.
So I have changed the root of NavigationController to controller, and after that my functions does not work. I've tried several things like deleting navcontrol in storyboard, etc. You can see my project here: https://github.com/ardulat/SPE
I will provide you a basic example of a Login scenario, hope it can help you with your issue, what I would do first is set right the navigation between ViewControllers like this:
I have two view controllers in my project (LoginViewController.swift and MainViewController.swift):
So in my storyboard I create two ViewControllers, the first one embedded with NavigationController then I set a segue from my first ViewController to my second ViewController:
Then I give a name to the segue I created like so:
And in order to navigate from Login to Main ViewController, I call the performSegue method inside the loginButtonTapped action that is triggered when the login button is touched.
LoginViewController.swift:
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func loginButtonTapped(_ sender: AnyObject) {
// TODO: validate your login form
performSegue(withIdentifier: "LoginToMain", sender: nil)
}
}
I have a tableView into a viewController on tab Bar. When I click into tabBar item the tableView isn't refreshing. But I have the viewWillAppear function:
override func viewWillAppear(animated: Bool) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
I'm trying call this function with tab bar delegate, but not works:
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
Why not reload?
Thanks!
You do not need to involve the tab bar controller in this. To do so would be overkill. You'll create confusing code that somebody will want to rip out later. Updating the table view in viewWillAppear(_:) is almost always the best approach.
If everything is set up properly, your view controller's viewWillAppear(_:) method will get called each time the user selects that tab and your view becomes visible. So if it's not getting called, you have a problem somewhere in the design of your tab bar and its view controllers.
Create a new project and select the Tabbed Application template. Open the SecondViewController file and add a viewWillAppear(_:) method. Add a breakpoint there. You'll see it's called every time you switch to the second tab.
Some other thoughts...
You'll notice in the viewWillAppear(_:) documentation that it says you must always call super. You're not. You should. But this is unrelated to your problem.
Also, there's no need to switch to the main queue. viewWillAppear(_:) will always be called on the main queue.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
Answer for swift 5.0
Reload UITableView in main thread and then check. I hope this will work for you.
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
You can find the answer here:
open viewcontroller from tab like in instagram camera page on IOS
Basically, you need to create a controller which inherits from UITabBarController and set it in the Storyboard to the custom class of your tabBarView.
Then set Tags to each Tab via the Storyboard.
Afterwards you can use the delegate method to call an action if a specific tab was clicked.
The delegate method should look like this:
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
switch item.tag{
case 1: //code here
break
default: break
}
}
I am trying to get the tab title at application launch.
I can do this to read the tabBarItem.title when the user changes tabs:
func tabBarController(
tabBarController: UITabBarController,
didSelectViewController viewController: UIViewController) {
UserActivity.trackScreen(name: viewController.tabBarItem.title)
}
This method does not fire for the initial selection. I tried this approach in UITabVarController's viewDidLoad method.
override func viewDidLoad() {
super.viewDidLoad()
UserActivity.trackScreen(name: self.selectedItem.title) // I think this is not set yet, it is nil.
}
This does not work.
How do I get the selected tab bar item, or the tab bar item that will be selected, on app launch?
Doing an action on the "selected" tab is a special case for the first launch, because the delegate method didSelectViewController does not fire.
If (and this might be a big "if") you can assume the first tab is the one that is selected on app launch, this code will work for handling the first-launch case:
if let vcs = self.viewControllers {
var firstVC = vcs[0] as UIViewController
UserActivity.trackScreen(name: firstVC.tabBarItem.title)
}
This works for me. Open to better answers.