I am having a problem with managing more than one UINavigationControlller.
I have a UITabBar and in every tab I have a separate UINavigationController. So If I switch in UITabBar by
tabBar.selectedIndex = i; // where i is index of tabbar.
and when I go back to previous tab by
tabBar.selectedIndex = previousIndex;
I go to the root of the UINavigationController, not the viewcontroller which I left previously.
I want to go to the viewcontroller from which I jump to another tab, without calling -viewDidLoad: or -viewWillAppear:.
I need a method which show either UINavigationController or my viewController.
The following method when implemented in your AppDelegate.m file will be fired whenever u try to switch the tabs
- (BOOL)tabBarController:(UITabBarController *)tbc shouldSelectViewController:(UIViewController *)viewController {
}
specify in your appDelegate class as the delagate of your tabbarcontroller
ie.( TabBarController.delegate = self) in appDidFinishLaunching method
Related
I created my iOS app with Tab Bar template, so here is UITabBarController with bar buttons. An issue is how to set it as delegate. I found at SO that it has to be set programmatically in AppDelegate, but I believe it's impossible, because I've got no access to Tab Bar Controller as outlet.
I added proper value to #interface (both ViewController and AppDelegate), but doesn't know what to do next.
#interface ViewController : UIViewController <UITabBarControllerDelegate>
I hope I don't have to get rid of whole app template and it's possible to set Tab Bar Controller created in IB to be delegate.
Exactly I want to make it delegate to create on tab select event like this:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
Any idea?
You can quickly and easily create a new TabBarController Delegate class and connect it as the delegate in the storyboard.
Create a new class :
class TabBarControllerDelegate: NSObject, UITabBarControllerDelegate {
In IB, add an object from the object library to the list of View Controller on the left (note: search "object", it's a yellow cube).
Change the class of this object (your yellow cube in IB) to TabBarControllerDelegate
In IB navigate to your Tab Bar Controller Scene. From the Connection Inspector, drag the delegate circle to the new object you added in Step 3.
Implement your delegate methods in your TabBarControllerDelegate class. Done!
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController)->Bool {
println("Selected a new tab")
}
I don't remember exactly the Xcode's Tab Bar template set up, but in your AppDelegate you can access to your window's rootViewController, cast it to a UITabBarController, and then set its delegate to your AppDelegate or to any other view controller.
Something like this:
UITabBarController *tabBarController =
(UITabBarController *)[[self window] rootViewController];
[tabBarController setDelegate:self]; // In this example your app delegate would implement the UITabBarControllerDelegate protocol.
EDIT
If you want to set your ViewController instance as the delegate:
UITabBarController *tabBarController =
(UITabBarController *)[[self window] rootViewController];
// I assume you have your ViewController instance set as the first view controller of your tab bar controller
// No need for a cast here since objectAtIndex: returns id, but of course you must implement the UITabBarController protocol in your ViewController.
[tabBarController setDelegate:[[tabBarController viewControllers] objectAtIndex:0]]];
EDIT 2
From your ViewController itself you can set the tab bar controller's delegate as rdelmar comments.
Just keep in mind that this cannot be done in the init method because the view controller is not in the tab bar controller yet. The proper place would be viewDidLoad but therefore it will not be executed until the ViewController view loads...
self.tabBarController.delegate = self;
0 lines of code
Drag an Object and subclass it
Xcode > Show File Inspector > Custom Class.
Class: TabBarControllerDelegate.
Set delegate to that Object
Put your existing code in that Object
This is the code you already have in your current UITabBarControllerDelegate.
class TabBarControllerDelegate: NSObject, UITabBarControllerDelegate {
// Delegate code goes here
}
What about create a viewController lets say MyTabController subclass UITabBarController
#interface MyTabController : UITabBarController<UITabBarControllerDelegate>
and set the tab Controller's class in you storyboard to MyTabController instead of UITabBarController, then put self.delegate = self; in your viewDidLoad
implement:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
and here you are.
Edit:
If you find self.delegate = self; is odd, which it is, you can create an outlet in your MyTabController
IBOutlet UITabBarController *tabBarController; and connect it to the tab controller in your storyboard.
Then you can put tabBarController.delegate = self;
In my App i have a situation where i Programmatically change the selected index of a tabBarController like this
[self.tabBarController setSelectedIndex:0];
and go back to my tab containing a UITableView' at this point i need to make some actions on my tableView
i tried to use viewWillAppear and it didn't get there, i tried to make the view delegate like this
#interface ThirdViewController : UITableViewController < UISearchBarDelegate,UINavigationControllerDelegate, UITabBarDelegate>
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
it didn't work
any one know how to do it?
I noticed that your class ThirdViewController implements UITabBarDelegate, while tabBarController:didSelectViewController: is in fact a method of UITabBarControllerDelegate protocol.
Try this below code:
self.tabBarController.selectedIndex = 1;
or
[self.tabBarController setSelectedIndex:1];
Thanks..!
UPDATE :
you can set delegate for tabBarcontroller viewdidLoad method below code:
tabBarController.delegate=self;
the solution for me was to make [[controller alloc]init] and activate a function doing the things i need in the controller im moving to
I've made this simple function to select programmatically view controllers inside my UITabBarController.
-(void)selectVCfromIndex:(int)index{
self.selectedIndex = index;
[self tabBarController:self shouldSelectViewController:[self.viewControllers objectAtIndex:index]];
}
In the shoudSelectViewController protocol i have specific code for presenting view controllers and in this way it runs when tabs change both programmatically and by user interaction.
i have a navigation application with a tab bar and there is a web view in first view which is related with first tab bar item . with a button web view appears and i want to hide it when i touch the first tab bar item .. Please help thx
To get the controller, just:
[[tabBarController viewControllers] objectAtIndex:indexOfTheTab]
tabBarController refers to UITabBarController *tabBarController in you AppDelegate.
EDIT 1: add this to your AppDelegate.h
-(UITabBarController*)getTabBarController;
add this to your AppDelegate.m
-(UITabBarController*)getTabBarController { return tabBarController; }
Now, you can access it from everywhere:
[(AppDelegate*)[[UIApplication sharedApplication] delegate] getTabBarController]
Don't forget #import "AppDelegate.h"
EDIT 2: In you AppDelegate.m
In the first method, just add: self.tabBarController.delegate = self;
Then, override:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
//something like : [tabBarController hideTheStuffs];
}
With EDIT 2 you can listen to the user touches in the tab bar, even if the tab item is already the current one. With EDIT 1 you can access your delegate from everywhere if needed.
EDIT 3:
Do you have a IBOutlet UIWebView *myWebView in you ControllerView.h (the one with the view that shows the web view).
If not, add this outlet, then connect it to your webview in interface builder.
In the controller, add a method in .h and .m :
-(void)hideTheWebView { myWebView.hidden = YES; }
As this method is declared in the interface (.h), you can call it from the AppDelegate, method tabBarController:didSelectViewController.
I have a tabBarController that I add by placing the following code into:
AppDelegate.h:
...
UITabBarController IBOutlet *tabBarController;
}
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
AppDelegate.m:
...
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
[tabBarController setDelegate:self];
I then use the following code to present a modal barcode scanning View Controller:
- (void)tabBarController:(UITabBarController *)tbc didSelectViewController:(UIViewController *)vc {
// Middle tab bar item in question.
if (vc == [tabBarController.viewControllers objectAtIndex:2]) {
ScanVC *scanView = [[ScanVC alloc] initWithNibName:#"ScanViewController" bundle:nil];
// set properties of scanView's ivars, etc
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:scanView];
[tabBarController presentModalViewController:navigationController animated:YES];
[navigationController release];
[scanView release];
}
}
When it does actually get presented I think this method isn't visually appealing, because when I dismiss the modal view I am brought back to an empty view.
A lot of barcode scanning applications or applications that simply display an image picker for example; do this quite successfully. I'm just wondering what kind of implementation they would use in order to achieve such an effect.
This is a screenshot of an application called Path, which has the exact same functionality I'm after:
I also noticed that in these applications, if you are on any other tab bar item other than the middle one let's say, and you click on the tab bar item that presents the modal view, once it gets dismissed it doesn't actually bring them back to an empty view it dismisses like normal, however the actual tab bar item that presents the modal view is never selected. I would be happy with this type of functionality if that's the only way to implement this type of effect.
Any help would be greatly appreciated as I've been stuck in this for quite some time. Also I'm not even sure whether it's the right way to put all of this code in my AppDelegate in order for the View Controller to be presented as a modal. It all seems, just, wrong.
Not entirely what I'm after, but I think I can move forward from this:
http://idevrecipes.com/2010/12/16/raised-center-tab-bar-button/
When you dismiss the modal view controller, tell the tab bar to select whatever tab was originally selected.
- (void)dismissModalViewControllerAnimated:(BOOL)animated
{
// do whatever you need to do when dismissing
// savedTabIndex is an int ivar
// tabBarController is a reference, set when showing the modal view
[[self tabBarController] setSelectedIndex:savedTabIndex];
}
You would have to save the original tab bar selection in a variable at the start of tabBarController:didSelectViewController:.
- (void)tabBarController:(UITabBarController *)tbc
didSelectViewController:(UIViewController *)vc
{
// Save the tab bar index (if it's not the photo tab)
if ([tabBarController selectedIndex] != 3]) {
savedTabIndex = [tabBarController selectedIndex];
}
}
There could be mistakes in this code, I just typed it without testing.
I found a really easy solution by playing around UITabBarControllerDelegate--I only tried this in iOS 7 though.
First, subclass UITabBarController, make it its own UITabBarControllerDelegate, and create a property that'll hold a reference to the tab you want to launch a modal with. In my app, it's called the "Sell" tab.
#property (strong, nonatomic) UIViewController *sellTab;
Then, in your init method, just create that view controller and add it to the tabs.
_sellTab = [[UIViewController alloc] init];
_sellTab.title = #"Sell";
self.viewControllers = #[homeTab, historyTab, _sellTab, bookmarksTab, profileTab];
Now here's where the magic is: override the following tab bar controller delegate methods. Code is pretty self-explanatory.
#pragma mark - Tab bar controller delegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
return viewController != self.sellTab;
}
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
if (item == self.sellTab.tabBarItem) {
[self presentViewController:[[UINavigationController alloc] initWithRootViewController:[[PostAdViewController alloc] init]] animated:YES completion:nil];
}
}
This will launch a modal which, upon dismissal, shows the same tab you were in before launch.
You shouldn't present a modal view, when the user clicks on a tab bar item.
You could instead present a modal view from within a view that's presented by one of the tabs.
Or, if you just have a single main view and the scan view you want to present modally, you should just use a button to present the scan view from within your main view. You could for instance use a toolbar with a single button in it, instead.
Can any one help me,
when i am using my UITabBarController delegate it is not working..
I called a delegate method like this..
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
[self.navigationController popToRootViewControllerAnimated:NO];
}
If what you're doing is subclassing a UITabBarController, then... oddly enough... you can get it working by setting itself as a delegate:
- (void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
}
Then the didSelectViewController action will fire normally:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSLog(#"View Changed");
}
Don't forget to add your UITabBarControllerDelegate class to your .h file:
#interface MyTabBarController : UITabBarController <UITabBarControllerDelegate>
#end
If you are using tab bar customizing by extending UITabBarController and trying to change tab bar selected index programmatically then it will not call delegates.
Please see the note inside "UITabBarDelegate":
// Note: called when a new view is selected by the user (but not programmatically)
This might help you
-(void)applicationDidFinishLaunching:(UIApplication *)application {
tabBarController.delegate=self;
// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
}
specify
UITabbarcontrollerDelegate in .h file
then
-(void)applicationDidFinishLaunching:(UIApplication *)application {
tabBarController.delegate=self;
// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
}
Read the documents to get a deeper understanding of the relationships between navigation controllers, tabBar controllers, and the view and navigation hierarchy.
Then review the code you've provided. Which view/controller is the container? You are popping the navigationController of self, which is not the same as the tabBarController. I don't think you actually need this method if you are looking to switch between tabs.
Try commenting out this method. It is an optional method in the UITabBarController delegate protocol. If you comment it out, you should get the default behavior of the tab controller, which should be to select the appropriate viewController and switch to the new view.
You typically only need to use this method if you want some action taken as you switch between view controllers.