0

I need to do some UI tasks when user selects a UI tab item. Following delegate is available,

-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item

Although, to answer for my particular question the internal UI transition issue is not important here, I am still sharing a overview code snippet.

-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
    AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
    [delegate.rootTabBarController showConsentErrorPage];
}

However, my UI task inside this delegate shows a glitch on the transition as it does the work after the tab is already shown. I want to perform the UI task first before the UI being visible. Any such delegate of trick to resolve this issue?

Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
  • Very vague description of the problem. Best if you post enough code to reproduce the issue - see [mre]. – DonMag Jan 03 '22 at 18:00
  • @DonMag this is not an issue, this is simply a query. What part you didn't get of the query? – Sazzad Hissain Khan Jan 03 '22 at 20:42
  • *"shows a glitch"* ... what glitch? *"showConsentErrorPage"* ... what does that do? Are you trying to present a different view controller? Are you adding a VC as a child? Are you setting up view objects in the target controller? Have you looked at `UITabBarControllerDelegate` and `shouldSelectViewController` and / or `didSelectViewController`? Do you ***really think*** you've provided enough information to convey what you're trying to do and what you're experiencing? – DonMag Jan 03 '22 at 21:04
  • I am trying to present a different view controller. May actual question is `Is there any delegate that serves the purpose of tabBar willSelectItem?`. I will add more information if required @DonMag – Sazzad Hissain Khan Jan 03 '22 at 21:07
  • There is no `willSelectItem` delegate method. `didSelectItem` is called *after* the tap on the tab bar item is finished. Implementing `UITabBarControllerDelegate` and `shouldSelectViewController` and / or `didSelectViewController` *may* help you... Are you trying to show a "yes/no consent" question, and *not* show the tab's controller if the user answers No? – DonMag Jan 03 '22 at 21:25
  • @DonMag something similar kind of flow. You got it right. – Sazzad Hissain Khan Jan 03 '22 at 21:34
  • 1
    I really don't understand your hesitancy to fully explain what you want to do. However, I posted an answer which ***MAY*** help you. – DonMag Jan 03 '22 at 22:08

1 Answers1

1

This may help you (without additional information, I can't really say).

  • subclass UITabBarController conforming to <UITabBarControllerDelegate>
  • in that new custom UITabBarController , be sure to set self.delegate = self; in viewDidLoad
  • implement shouldSelectViewController
  • if that controller is your "needs consent to see" view controller,
    • check if the user has already given consent
    • if so, return YES (i.e. allow the tab to be selected)
    • if not, present your "Ask Consent" controller and return NO
    • if the user gives consent, navigate to that tab

Here is some sample code...

With this option, we present the "Ask Consent" controller, and only navigate to the "needs consent to see" tab when the user selects "Yes":

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    
    if ([viewController isKindOfClass:NeedsConsentViewController.class]) {
        
        NeedsConsentViewController *vc = (NeedsConsentViewController *)viewController;
        
        // whatever you're using to track the user's consent
        if (vc.hasConsent) {
            // allow the tab to be selected
            return YES;
        }
        
        // configure / instantiate your "Consent" view controller
        UIAlertController * alert = [UIAlertController
                                     alertControllerWithTitle:@"Yes/No"
                                     message:@"Need your consent..."
                                     preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction* okButton = [UIAlertAction
                                   actionWithTitle:@"Yes"
                                   style:UIAlertActionStyleDefault
                                   handler:^(UIAlertAction * action) {
            
            // however you're setting your user consent tracking
            vc.hasConsent = YES;
            
            // show that tab
            [self setSelectedViewController:vc];
            
        }];
        
        [alert addAction:okButton];
        
        UIAlertAction* noButton = [UIAlertAction
                                   actionWithTitle:@"No"
                                   style:UIAlertActionStyleDefault
                                   handler:^(UIAlertAction * action) {
            
            // user said NO... nothing else to do

        }];
        
        [alert addAction:noButton];
        
        [self presentViewController:alert animated:YES completion:nil];
        
        // don't show the tab
        return NO;
    }
    
    // all other tabs
    return YES;
}

With this option, we present the "Ask Consent" controller and navigate to the "needs consent to see" tab behind it. If the user answers "No" we navigate back to the previously selected tab:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    
    NSInteger curTabIDX = self.selectedIndex;
    
    if ([viewController isKindOfClass:NeedsConsentViewController.class]) {

        NeedsConsentViewController *vc = (NeedsConsentViewController *)viewController;

        // whatever you're using to track the user's consent
        if (vc.hasConsent) {
            // allow the tab to be selected
            return YES;
        }

        // configure / instantiate your "Consent" view controller
        UIAlertController * alert = [UIAlertController
                                     alertControllerWithTitle:@"Yes/No"
                                     message:@"Need your consent..."
                                     preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction* okButton = [UIAlertAction
                                   actionWithTitle:@"Yes"
                                   style:UIAlertActionStyleDefault
                                   handler:^(UIAlertAction * action) {
            
            // however you're setting your user consent tracking
            vc.hasConsent = YES;
            
            // we've already navigated to the tab, with the Consent VC presented on top of it
            //  so nothing else to do
            
        }];
        
        [alert addAction:okButton];
        
        UIAlertAction* noButton = [UIAlertAction
                                   actionWithTitle:@"No"
                                   style:UIAlertActionStyleDefault
                                   handler:^(UIAlertAction * action) {
            
            // user said NO, so return to the previous tab
            [self setSelectedIndex:curTabIDX];
            
        }];
        
        [alert addAction:noButton];
        
        [self presentViewController:alert animated:YES completion:nil];

        // show the tab behind the Consent VC
        return YES;
    }
    
    // all other tabs
    return YES;
}

Note: This is Example Code Only and is not intended to be, nor should be considered, "production ready."

DonMag
  • 69,424
  • 5
  • 50
  • 86