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
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.