I want to launch segue from tab bar item. When user touches an item on the tab bar. I want to launch a segue.
To do this I writed this code:
class TabBarController: UITabBarController, UITabBarControllerDelegate {
#IBOutlet var tabs: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
if item.tag == 3 {
self.performSegueWithIdentifier("test123", sender: self)
}
}
}
Actually it works well except a problem. This is launching segue but also switching the tab. I don't want this. It should just launch start segue shouldn't switch the tab.
How can I prevent this problem?
Here's the minimal changes to get your code work
in your viewDidLoad() add
self.delegate = self
Then implement delegate method
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
let shouldSelectIndex = tabBarController.viewControllers?.indexOf(viewController)
if shouldSelectIndex == 2
{
self.performSegueWithIdentifier("test123", sender: self)
return false
}
return true
}
That should work.
However I think you have design issues.
Subclass as a delegate is strange. Better separate delegate.
Instead of tag/indecies use introspection or another delegation or something
Related
I have an item on my tabBar which I don't want to actually move to its view controller but instead when that item is clicked something happens (a popup dialog appears over the current view controller).
I currently have the current code:
class TabViewController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// tell our UITabBarController subclass to handle its own delegate methods
self.delegate = self
}
// called whenever a tab button is tapped
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if viewController is PostTabViewController {
... code here ...
}
}
}
The code at ..code here... runs just fine however the PostTabViewController is still shown. How would I go about stopping it?
You should do your checks in tabBarController(_, shouldSelect:)
func tabBarController(UITabBarController, shouldSelect: UIViewController) -> Bool {
guard viewController is PostTabViewController else {
return true
}
... code here ...
return false
}
I have gone through all the other posts about this topic but they don't seem to help me.
I have a UITabBarController that is launching two tabs. I want to pass data collected in tab1 to the UITabBar ViewController. I am trying to use delegete protocol for this but I am having trouble setting the delegate variable in the sending ViewController. The prepare for segue never gets called. I cannot even cycle through the viewcontrollers of the tabs inside the ViewDidLoad() of the Tabbar controller as they are not created yet and so nil.
I have used delegates before and it seems rather straightforward. Does it matter that I am using it in a Tabbar?
When I run the code the viewDidLoad() in TabBarViewController is called but not the preparefor segue.
The IBAction donePressed in the MeViewController is called but the delegate is not called as its not set.
Here is the code --
protocol DetailsDelegate: class {
func myDetailsGathered( myDetails: MyDetails )
}
/// RECEIVING VIEW CONTROLLER
class TabBarViewController: UITabBarController, DetailsDelegate
{
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
print("prepare for segue called\n");
if let destinationViewController = segue.destination as? MeViewController
{
destinationViewController.delegate = self
}
}
override func viewDidLoad()
{
print("ViewDidLoad Called \n")
}
func myDetailsGathered(myDetails: MyDetails)
{
self.myDetails = myDetails
print("My details gathered \n")
}
}
---------------
/// SENDING VIEW CONTROLLER
class MeViewController: UIViewController
{
weak var delegate: DetailsDelegate?
override func viewDidLoad()
{
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
// I have UIButton in the view and this is invoked when its pressed.
#IBAction func donePressed(_ sender: Any)
{
var infoToPass = MyDetails()
print("looks like we are done")
delegate?.myDetailsGathered(infoToPass: myDetails)
}
}
prepareForSegue is called when you perform a segue. Which you don´t do and that´s why it does not get called.
A segue defines a transition between two view controllers in your
app’s storyboard file.
You should use a singleton class to store variables and access them between different controllers. You declare one like this:
class Singleton {
static let sharedInstance = Singleton()
var name = ""
}
Assign to Singleton:
Singleton.sharedInstance.name = "Some name"
To read from it from whatever controller:
let name = Singleton.sharedInstance.name
First of all, why do you want your tabbarController to receive some info/data though?
The prepare for segue never gets called.
prepareForSegue method will be invoked right after the performSegue. So where's your performSegue method? Or are you sure that that kind of segue going to MeViewController is being performed?
One more option you have is to use NotificationCenter.
Currently I have a Tab Bar Controller that is connected to a tableview controller. I'm trying to go to the top of the tableview when I press the tab bar item. I know how to get to the top of the tableview. I just don't know how to do an action when the item is pressed.
You should use UITabBarDelegate with method didSelectItem. Use it as any standard delegate:
class yourclass: UIViewController, UITabBarDelegate {
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
//This method will be called when user changes tab.
}
}
And do not forget to set your tab bar delegate to self in view controller.
Here is an answer to this question
Basically you do this:
Make sure your view controller is subscribed to the UITabBarDelegate
Set tags in IB for each tab bar item
Implement the didSelectItem method, something like this:
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
if(item.tag == 1) {
// Code for item 1
}
else if(item.tag == 2) {
// Code for item 2
}
}
This will give you access to each tab item tapped event. Hope it helps!
In Swift:
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if(item.tag == 1) {
// Code for item 1
} else if(item.tag == 2) {
// Code for item 2
}
}
SWIFT 3
class yourclass: UIViewController, UITabBarDelegate {
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print("Test")
}
}
And do not forget to set your tabBar delegate to self in viewDidLoad
override func viewDidLoad(){
super.viewDidLoad()
<YOUR TAB BAR NAME>.delegate = self
}
I was having trouble implementing the other answers here. This is a fuller answer. It assumes you are using a UITabBarController (the default if you create a new Tabbed App). This solution will print a message every time a view controller tab button is tapped.
Code
Create a new Swift file called MyTabBarController.swift. Paste in the following code.
import UIKit
class MyTabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// tell our UITabBarController subclass to handle its own delegate methods
self.delegate = self
}
// called whenever a tab button is tapped
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if viewController is FirstViewController {
print("First tab")
} else if viewController is SecondViewController {
print("Second tab")
}
}
}
Interface Builder
On your storyboard select the Tab Bar Controller. Then in the Identity inspector, set the class name to MyTabBarController (that is, the name of the class in the code above).
That's all. You can run your app now and be notified whenever the user taps a tab bar item.
Notes
If you need to run a method on a tap, then you can do something like the following in didSelect method.
if let firstVC = viewController as? FirstViewController {
firstVC.doSomeAction()
}
You could do make the FirstViewController implement the delegate and handle everything there. That way you wouldn't need to make any custom UITabBarController subclass and set it in IB. However, having a child do the parent's work seems like the wrong place to do it. Anyway, here is is:
class FirstViewController: UIViewController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
tabBarController?.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
// ...
}
}
The didSelect method above gets called no matter which tab is tapped.
UITabBarControllerDelegate documentation
An alternate solution is to just do something in viewDidAppear in whichever View Controller the tab shows.
First Tab View Controller
import UIKit
class FirstViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("First tab")
}
}
Second Tab View Controller
import UIKit
class SecondViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("Second tab")
}
}
class TestViewController: UIViewController,UITabBarDelegate {
#IBOutlet weak var tabbar: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
tabbar.delegate = self
}
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print(tabBar.items![1]) // The number is tab index
}
}
I Use the following code to check which tab is selected in TabBar in UIViewController not using UITabBarController, But i don't know how to load the Particular ViewController in the View, Or is there any other way to achieve this
This is what i get from the Google and other forums, I use the Tag for the UITabBarItems to differentiate the buttons
import UIKit
class AdminViewController: UIViewController, UITabBarDelegate {
#IBOutlet weak var menuButton: UIBarButtonItem!
#IBOutlet weak var tabbar: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
menuButton.target = self.revealViewController();
menuButton.action = "revealToggle:";
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer());
}
tabbar.delegate = self;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem!) {
println(item.tag);
if(item.tag == 1)
{
//Want to load UIViewController into the CurrentViewController
}
}
}
I have another idea, But it is not good
Place the TabBar in all UIViewControllers and When the TabBarItem is Clicked i will Navigate to that UIViewController using PerformSegue & There also a TabBar
Yes #Oliver Borchert I used the tab bar controller
This solved my problem completely
TabBarController with SWRevealViewController
Thanks #Anbu.Karthik
I have problem with UITabBar. I need to make a custom action for Item (UITabBarItem). What do I need to add to make it working?
import UIKit
class ViewController: UIViewController {
#IBOutlet var TabBar: UITabBarItem!
#IBOutlet var Item: UITabBarItem!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationController?.navigationBarHidden
self.navigationItem.hidesBackButton = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tabBar(tabBar: UITabBar!, didSelectItem item: UITabBarItem!) {
var selectedTag = tabBar.selectedItem?.tag
println(selectedTag)
if selectedTag == 0
{
}
else
{
}
}
}
In each ViewController place this function:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//set inital view
}
Then put your code to execute in here and when the view appears it will execute.
Okay then, what I think you want then is not a UITabBar but instead a UIToolBar. From Apple:
"A tab bar is a control, usually appearing across the bottom of the screen in the context of a tab bar controller, for giving the user one-tap, modal access to a set of views in an app. Each button in a tab bar is called a tab bar item and is an instance of the UITabBarItem class. If you instead want to give the user a bar of buttons that each perform an action, use a UIToolbar object."
For the UIToolBar description see:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIToolbar_Class/index.html#//apple_ref/occ/cl/UIToolbar