Custom rightBarButtonItem disappearing

前端 未结 1 1951
南旧
南旧 2021-01-27 23:44

I have a strange bug with a custom rightBarButtomItem in the NavBar. I have a TabBar application. If the app is loaded the button shows up correct. If i click through the tabs t

1条回答
  •  北海茫月
    2021-01-28 00:26

    It strikes me that creating a new CustomTabBarController for every view controller is fundamentally wrong, especially if it's to solve the problem that your right button isn't appearing. The issue is that you're creating new, phantom tab bar controllers, and worse, losing the reference to the view controller's real tab bar controller.

    Your solution gets to the kernel of the problem, which is that, because you're adding subviews for your button, namely creating the UIBarButtonItem with initWithCustomView, etc., that you cannot share the button with multiple navigation controllers. The shared, common right bar button works if you create a simple UIBarButtonItem with initWithTitle (or other simple variations like that), but it doesn't work if you do it with a custom view for your button.

    The right solution is to create a new UIBarButtonItem instance that has the behavior and appearance that you need. Then, any view controller that needs that bar button item can create an instance of that button. Thus, the new custom RightBarButtonItem might look like:

    RightBarButtonItem.h:

    @interface RightBarButtonItem : UIBarButtonItem
    
    - (id)initWithTarget:(id)target action:(SEL)action;
    
    @end
    

    RightBarButtonItem.m:

    @interface RightBarButtonItem ()
    @property (nonatomic, strong) EZBadgeView *badgeView;
    @end
    
    @implementation RightBarButtonItem
    
    - (id)initWithTarget:(id)target action:(SEL)action
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(0, 0, 46, 30);
    
        self = [super initWithCustomView:button];
    
        if (self)
        {
            _badgeView = [[EZBadgeView alloc] init];
            CGRect badgeFrame = self.badgeView.frame;
            badgeFrame.origin.x = 31.0f;
            badgeFrame.origin.y = -6.0f;
            badgeFrame = CGRectIntegral(badgeFrame);
            _badgeView.frame = badgeFrame;
            _badgeView.badgeBackgroundColor = [self colorWithRGBHex:kRed withAlpha:1.0f];
            _badgeView.userInteractionEnabled = NO;
            _badgeView.badgeTextFont = [UIFont fontWithName:@"BrownStd-Bold" size:12];
            _badgeView.shouldShowGradient = NO;
            _badgeView.shouldShowShine = NO;
    
            [button setBackgroundImage:[UIImage imageNamed:@"button_mixer.png"]         forState:UIControlStateNormal];
            [button setBackgroundImage:[UIImage imageNamed:@"button_mixer_pressed.png"] forState:UIControlStateHighlighted];
            [button setBackgroundImage:[UIImage imageNamed:@"button_mixer_active.png"]  forState:UIControlStateSelected];
    
            [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
            [button setBackgroundColor:[UIColor clearColor]];
            [button addSubview:_badgeView]; //Add NKNumberBadgeView as a subview on UIButton
    
            _badgeView.badgeValue = @"0";
            _badgeView.hidden = YES;
    
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(updateBadgeNumber:)
                                                         name:@"updateBadgeNumber"
                                                       object:nil];
        }
    
        return self;
    }
    
    - (void)dealloc
    {
        // don't forget to have mechanism to remove the observer when this button is deallocated
    
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:@"updateBadgeNumber"
                                                      object:nil];
    }
    
    - (void)updateBadgeNumber:(NSMutableArray *)soundArray
    {
        self.badgeView.badgeValue = [NSString stringWithFormat:@"%i",[soundArray count]];
        self.badgeView.hidden = ([soundArray count] == 0);
    }
    
    - (UIColor *)colorWithRGBHex:(UInt32)hex withAlpha:(float)alpha
    {
        int r = (hex >> 16) & 0xFF;
        int g = (hex >> 8) & 0xFF;
        int b = (hex) & 0xFF;
    
        return [UIColor colorWithRed:r / 255.0f
                               green:g / 255.0f
                                blue:b / 255.0f
                               alpha:alpha];
    }
    
    @end
    

    Then, the CustomTabBarController is greatly simplified:

    CustomTabBarController.h:

    @interface CustomTabBarController : UITabBarController
    
    - (UIBarButtonItem *)rightBarButton;
    
    @end
    

    CustomTabBarController.m:

    #import "RightBarButtonItem.h"
    
    @implementation CustomTabBarController
    
    - (UIBarButtonItem *)rightBarButton
    {
        return [[RightBarButtonItem alloc] initWithTarget:self
                                                   action:@selector(clickedTest:)];
    }
    
    - (void)clickedTest:(id)sender
    {
        NSLog(@"%s", __FUNCTION__);
    }
    
    @end
    

    And, finally, all of the view controllers that are added to the tab bar controller, can simply do:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        CustomTabBarController *tabBarController = (id)self.tabBarController;
    
        self.navigationItem.rightBarButtonItem = [tabBarController rightBarButton];
    }
    

    All of this achieves the critical part of your proposed solution, namely to ensure that we have a unique instance of the right bar button item, but without the problem of creating redundant tab bar controllers.

    0 讨论(0)
提交回复
热议问题