Пользовательские права BarButtonItem исчезают

У меня есть странная ошибка с пользовательским rightBarButtomItem в NavBar. У меня есть приложение TabBar. Если приложение загружено, кнопка отображается правильно. Если я нажимаю на вкладки, кнопка продолжает показываться. Если я вернусь к одной из вкладок, которая уже была показана, кнопка исчезнет. В конце кнопка отображается случайным образом только на одной из вкладок.

Мой код работает отлично, если я устанавливаю стандартный rightBarButtomItem программно. Но не с пользовательской графикой. Если ChildViewController нажат и выдвинут, кнопка появляется снова. Кажется, это все еще там, но не видно!

Я думаю, что моя ссылка на sharedRightButton в CustomTabBarViewController неверна!

Кто-нибудь может помочь?

CustomTabBarController.h

   #import <UIKit/UIKit.h>
    #import "EZBadgeView.h"

    @interface CustomTabBarController : UITabBarController
    {
        EZBadgeView *badgeView;
        UIButton *btn;
        UIImage *rightBarButtonItemImage;
        UIImage *rightBarButtonItemImageTapped;
        UIImage *rightBarButtonItemImageSelected;
    }

    @property (nonatomic, strong) UIBarButtonItem *sharedRightButton;
    @property (nonatomic, strong) EZBadgeView *badgeView;
    @property(nonatomic, strong) UIButton *btn;
    @property(nonatomic, strong) UIImage *rightBarButtonItemImage;
    @property(nonatomic, strong) UIImage *rightBarButtonItemImageTapped;
    @property(nonatomic, strong) UIImage *rightBarButtonItemImageSelected;

    @end

CustomTabBarController.m

    #import "CustomTabBarController.h"

    @interface CustomTabBarController ()

    @end

    @implementation CustomTabBarController

    @synthesize sharedRightButton, badgeView, btn, rightBarButtonItemImage, rightBarButtonItemImageSelected, rightBarButtonItemImageTapped;

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }

    - (void)viewDidLoad
    {
        [super viewDidLoad];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateBadgeNumber:) name:@"updateBadgeNumber" object:nil];

        if (self.badgeView && self.badgeView.superview)
        {
            [self.badgeView removeFromSuperview];
        }
        self.badgeView = [[EZBadgeView alloc] init];
        CGRect badgeFrame = self.badgeView.frame;
        badgeFrame.origin.x = 31.0f;
        badgeFrame.origin.y = -6.0f;
        badgeFrame = CGRectIntegral(badgeFrame);
        self.badgeView.frame = badgeFrame;
        self.badgeView.badgeBackgroundColor = [self colorWithRGBHex:kRed withAlpha:1.0f];
        self.badgeView.userInteractionEnabled = NO;
        self.badgeView.badgeTextFont = [UIFont fontWithName:@"BrownStd-Bold" size:12];
        self.badgeView.shouldShowGradient = NO;
        self.badgeView.shouldShowShine = NO;

        // Allocate UIButton
        self.btn = [UIButton  buttonWithType:UIButtonTypeCustom];
        self.btn.frame = CGRectMake(0, 0, 46, 30);

        self.rightBarButtonItemImage = [UIImage imageNamed:@"button_mixer.png"];
        [self.btn setBackgroundImage:rightBarButtonItemImage forState:UIControlStateNormal];
        self.rightBarButtonItemImageTapped = [UIImage imageNamed:@"button_mixer_pressed.png"];
        [self.btn setBackgroundImage:rightBarButtonItemImageTapped forState:UIControlStateHighlighted];
        self.rightBarButtonItemImageSelected = [UIImage imageNamed:@"button_mixer_active.png"];
        [self.btn setBackgroundImage:rightBarButtonItemImageSelected forState:UIControlStateSelected];

        [self.btn addTarget:self action:@selector(clickedTest:) forControlEvents:UIControlEventTouchUpInside];
        [self.btn setBackgroundColor:[UIColor clearColor]];
        [self.btn addSubview:self.badgeView]; //Add NKNumberBadgeView as a subview on UIButton

        // Initialize UIBarbuttonitem...
         self.sharedRightButton = [[UIBarButtonItem alloc] initWithCustomView:btn];
         self.badgeView.badgeValue = @"0";
         self.badgeView.hidden = YES;
    }

    - (void)updateBadgeNumber:(NSMutableArray *)soundArray
    {
        self.badgeView.badgeValue = [NSString stringWithFormat:@"%i",[soundArray count]];
        self.badgeView.hidden = ([soundArray count] == 0);
    }

    - (void)clickedTest:(id)sender
    {
        NSLog(@"%s", __FUNCTION__);
    }

    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }

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

И я установил кнопку так в каждом представлении:

@implementation MyVC

@synthesize tabBarController;

    - (void)viewDidLoad
    {
        //NSLog(@"begin: %s", __FUNCTION__);
        [super viewDidLoad];


         // right bar button from custom tabbarcontroller
        self.tabBarController = [[CustomTabBarController alloc] init];
        self.navigationItem.rightBarButtonItem = self.tabBarController.sharedRightButton;

}

1 ответ

Решение

Меня поражает, что создание нового CustomTabBarController для каждого контроллера представления в корне неправильно, особенно если для решения проблемы не отображается ваша правая кнопка. Проблема в том, что вы создаете новые фантомные контроллеры панели вкладок и, что еще хуже, теряете ссылку на реальный контроллер панели вкладок представления.

Ваше решение доходит до сути проблемы, которая заключается в том, что вы добавляете подпредставления для своей кнопки, а именно создаете UIBarButtonItem с initWithCustomViewи т. д., что вы не можете поделиться кнопкой с несколькими контроллерами навигации. Общая правая кнопка общего доступа работает, если вы создаете простой UIBarButtonItem с initWithTitle (или другие простые варианты, подобные этому), но это не сработает, если вы сделаете это с пользовательским представлением для своей кнопки.

Правильное решение заключается в создании нового UIBarButtonItem экземпляр, который имеет поведение и внешний вид, что вам нужно. Затем любой контроллер представления, которому нужен этот элемент панели кнопок, может создать экземпляр этой кнопки. Таким образом, новый обычай RightBarButtonItem может выглядеть так:

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

Затем CustomTabBarController значительно упрощен:

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

И, наконец, все контроллеры представления, добавленные в контроллер панели вкладок, могут просто выполнить:

- (void)viewDidLoad
{
    [super viewDidLoad];

    CustomTabBarController *tabBarController = (id)self.tabBarController;

    self.navigationItem.rightBarButtonItem = [tabBarController rightBarButton];
}

Все это достигает критически важной части предложенного вами решения, а именно обеспечения того, чтобы у нас был уникальный экземпляр элемента правой панели кнопок, но без проблемы создания избыточных контроллеров панели вкладок.

Другие вопросы по тегам