ios/objective-c: Detect tabbarbutton pressed event - ios

I would like to prevent users from going to certain view controllers accessible through tab bar bar buttons and instead ask them to log in with an alert. I can disable the buttons, however, the only way to detect a button press on a disabled tab bar button (in order to fire the alert) seems to be to embed the button in another view with a gesture recognizer which seems complicated.
Alternatively, if I leave the buttons enabled, upon press they launch the view controller to which they are assigned with no way to launch the alert.
Is there a way to detect the press and pre-empt the segue to the view controller so I can launch an alert?
I have tried using the following method in my app delegate and in viewdidload of individual view controllers (that subscribe to uitabbarcontroller delegate protocol) but it is not getting fired.
- (void)tabBarController:(UITabBarController *)theTabBarController didSelectViewController:(UIViewController *)viewController
{
NSUInteger indexOfTab = [theTabBarController.viewControllers indexOfObject:viewController];
NSLog(#"Tab index pressed = %lu", (unsigned long)indexOfTab);
//launch alert
//prevent segue to view controller
}

The method you have to implement in your UITabBarController is :
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
If user is logged you return YES, if he's not, show an alert and return NO. You can check for which item was pressed by comparing viewController with the one(s) you want user to be logged.
You don't have to implement this method in a controller that subscribes to UITabBarController delegate protocol BUT to implement it in a subclass of your UITabBarController.

Related

share button as tab bar item on UITabBarController with no controller associated

I have a UITabBarController with five tab bar items, one of them is share button action (to share the itunes store link - tell a friend). My issue is when I click on this tab, the UIActivityViewController has displayed with blank controller, I need to show the share window (UIActivityViewController) to appear above the last tab bar view selected to avoid the blank view of this tab bar item.
You can implement the UITabBarControllerDelegate protocol and use the
- tabBarController:shouldSelectViewController: method to intercept the tap on the share tab like this:
- (BOOL) tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if (viewController == [tabBarController.viewControllers objectAtIndex:/*share button index*/]){
//show UIActivityViewController
return NO;
}
return YES;
}

intercept UITabBar tap

I need to intercept a UITabBar tap precisely so I can conditionally abort moving to the intended ViewController (i.e. conditionally dismiss the tap).
I create my UITabBar in the storyboard. The UITabBar is the root view of my entire app. One of the tabBar items is a profile page (so to speak). If a user does not yet have an account, I want to ignore their clicking on that specific tabBar item. The behavior I seek is that the user will not leave the present ViewController they are in to go to the Tab selected. But instead, I want them to segue to the registration page. Any ideas how I might do this interception?
UPDATE
I have managed to add the following method in my AppDelegate. The method is called, but the transition is not intercepted. How do I intercept and abort the transition?
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
NSLog(#"Intercept tabBarController in app delegate tap gesture but then do nothing");
}
The NSLog line is printed, but transition still occurs.
Sounds like you are on the right path. But you should use
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
If you need more help, let me know.
You need to go with the UITabBar delegate of tabBar:didSelectItem:
Ex:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
// Use the item to do further
}

Prevent UINavigationController from popping on double tap of UITabBarController

I have a UITabBarController in the root of my storyboard with three tabs. One of the tab is used to display the user information. I have set this tab to transition to the register/login page if the user has not registered. But the ViewController gets popped(and corrupts the Navigation Bar) when I double tap the tab icon. I cannot use the modal transition as it hides the TabBarController. What is the best solution to solve this issue?
You can use 'shouldSelectViewController' delegate of TabViewConroller to check if the selected viewController is same as the clicked one and skip it accordingly.
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if(viewController == tabBarController.selectedViewController)
{
return NO;
}
}

Why does my tabbar controller execute code from a different view controller than the active one?

Firstly, I have set both viewcontrollers to be UITabBarController delegates. Both are part of a tab bar controller. I did this by putting the following code into each viewDidLoad:
self.tabBarController.delegate = self;
Then I added the following delegate method to CalculatorsViewController:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
[self presentCalculatorsView];
}
Where presentCalculators view simply reveals a subview within the same view controller.
I also added the following delegate method to the OptionsViewController:
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
[self presentHomeScreen];
}
Again this method simply reveals another subview within the viewController.
The problem I am having is that the OptionsViewController presentHomeScreen method is only called if I do not visit the CalculatorsViewController. Once I do visit the CalculatorsViewController in the app and then return to OptionsViewController,
[self presentHomeScreen]
is never called. In fact, it appears that it still calls the method from the CalculatorsViewController. I tested it with an NSLog statement.
Any ideas why one method overrides the other? Or why the tab bar button executes code from another viewController, other than the one that is active?
EDIT* It is almost as if the one viewController 'steals' the delegate from the other.
By calling self.tabBarController.delegate = self; on each viewDidLoad method, you are basically telling the tab bar controller to use abandon the current delegate and use the current view controller as delegate.
Note that the viewDidLoad method is called only once under normal circumstances. (It may be called again when the view of your view controller is unloaded due to memory warning, for example, then you access the view of your view controller again, which calls loadView/awakeFromNib and viewDidLoad. I'm not entirely sure on this scenario though.) In your scenario:
Open OptionsViewController for the first time - tab bar controller's delegate is OptionsViewController
Open CalculatorsViewController for the first time - tab bar controller's delegate is now CalculatorsViewController
Go back to OptionsViewController - tab bar controller's delegate is still CalculatorsViewController, as the viewDidLoad is not called again
If you must change the delegate, you can do it instead in the viewWillAppear method.

How do i reset my tab to default view?

I have UITabViewController running with UINavigationController. In each tab i have a different TableViews that are roots of my application tree.
When i click an item of table, it goes to next level viewing another, detailed TableView, still having TabBar and NavigationBar on screen. It works perfectly, except for one thing. If i'm viewing details in one tab, then switch to another tab, and go back again, then i still see my detail. What i want to achieve, is to reset tab after leaving it.
I expect that i have to put something in viewDidUnload or simmilar, but couldn't find the right solution.
Hope you can help.
at
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
do
[viewController.navigationController popToRootViewControllerAnimated:YES];
That will navigate the tab's view controller to the root view whenever the tab is selected.
That's completely OK to keep your main window view controller (tab bar controller) instance at application delegate.
What you need to add is to set the delegate or whatever other initialized class to be the tab bar controller's delegate like this:
myTabBarController = [UITabBarController alloc ...
myTabBarController.delegate = self; // the app delegate will be also the tab bar delegate
in the app delegate, then you add the following method to the app delegate:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
[viewController.navigationController popToRootViewControllerAnimated:YES];
}
The tab bar controller will call this method whenever it's tab is selected.
You will also want to make the application delegate confirm UITabBarControllerDelegate this way:
#interface PSAppDelegate : UIResponder <UITabBarControllerDelegate>
that will let the compiler know that app delegate must or might have the methods declared in the protocol and will also give you so convenient auto-complition of this method.
One way to do this is to get the view controllers associated with the tabviewcontroller and then create new objects.
self.tabBarController?.viewControllers! will get an array of viewControllers for the tab bar. In my case they are a UINavigationControllers but they could be anything. I then get the viewController associated with that and reset that.
If you don't have navigation controllers you can just create new view controller objects and go with that.
below is the solution in my case (with the navcontroller)
let vc = self.tabBarController?.viewControllers![0] as! UINavigationController
let newVC = YourViewControllerClass()
vc.viewControllers[0] = newVC as UIViewController
This replaces the old (populated) vc with a new one!

Resources