自定义rightBarButtonItem消失

2024-04-25

我在导航栏中有一个自定义 rightBarButtomItem 的奇怪错误。我有一个 TabBar 应用程序。如果应用程序已加载,按钮将显示正确。如果我单击选项卡,按钮将继续显示。如果我返回到已显示的选项卡之一,该按钮就会消失。最后,该按钮仅随机显示在其中一个选项卡中。

如果我以编程方式设置标准 rightBarButtomItem,我的代码可以完美运行。但不适用于自定义图形。如果 ChildViewController 被按下并弹出,该按钮会再次出现。看起来它仍然存在,但不可见!

我认为我在自定义 TabBarViewController 中对 shareRightButton 的引用是错误的!

有人可以帮忙吗?

自定义TabBarController.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

自定义TabBarController.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;

}

让我印象深刻的是,创造了一个新的CustomTabBarController对于每个视图控制器来说都是根本错误的,特别是如果它是为了解决右键没有出现的问题。问题是您正在创建新的虚拟选项卡栏控制器,更糟糕的是,丢失了对视图控制器的真实选项卡栏控制器的引用。

您的解决方案触及了问题的核心,那就是,因为您正在为按钮添加子视图,即创建UIBarButtonItem with initWithCustomView等,您不能与多个导航控制器共享按钮。如果您创建一个简单的,则共享的公共右栏按钮将起作用UIBarButtonItem with 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大大简化了:

自定义TabBarController.h:

@interface CustomTabBarController : UITabBarController

- (UIBarButtonItem *)rightBarButton;

@end

自定义TabBarController.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];
}

所有这些都实现了您提出的解决方案的关键部分,即确保我们拥有右侧栏按钮项目的唯一实例,但不存在创建冗余选项卡栏控制器的问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义rightBarButtonItem消失 的相关文章

随机推荐

  • 如何使用 Objective-C 用空格分隔字符串?

    假设我有一个像这样的字符串 hello world this may have lots of sp ace or little space 我想将此字符串与此分开 hello world this may have lots of sp
  • MySQL 更新时会覆盖相同值的列吗?

    在MySQL中更新表时 例如 Table user user id user name 1 John 2 Joseph 3 Juan 如果我运行查询 UPDATE user SET user name John WHERE user id
  • 单击之前搜索查看查询提示

    我有一个搜索视图和一个查询提示属性 但是 只有在单击搜索视图后才会出现提示 有没有办法让它在点击之前出现
  • SonarQube 6.7 登录时冻结

    我刚刚在带有 MySQL 5 7 的 Ubuntu 16 04 服务器上安装了 SonarQube 6 7 我的同事使用 SonarQube 他们从托管在 GitHub 存储库上的源代码添加了他们的项目 添加了 3 4 个项目后 我们在 M
  • 使用mongoose在mongodb模式中使用ensureIndex

    我想打电话ensureIndex on the authorName 命令是什么以及我应该将其放在这段代码中的什么位置 var mongoose require mongoose defines the database schema fo
  • seo - 图像和 h1

    我遇到一种情况 我想坚持使用我的徽标而不是 h1 标签的实际文本 如果我将关键字放在 alt 标签中 而不是实际编写 我会在 SEO 上受到影响吗 文本和图像同时存在更好吗 想法 div h1 a href img src logo jpg
  • Spark 编码器:何时使用 beans()

    我在使用Spark的缓存机制时遇到了内存管理问题 我目前正在使用Encoder我正在使用 Kryo 想知道切换到 beans 是否可以帮助我减少缓存数据集的大小 基本上 在使用时使用 beans 相对于 Kryo 序列化有哪些优点和缺点En
  • 已将数据预先填充到资产中的领域?

    通常我使用 Realm 作为 RealmConfiguration config new RealmConfiguration Builder applicationContext deleteRealmIfMigrationNeeded
  • 匹配嵌套的html注释块正则表达式[重复]

    这个问题在这里已经有答案了 我有这个 html 代码块 some html content here top base some html content here 1 top some html content here 2 top so
  • Magento Connect 登录后尝试更改为什么路径?

    我每次都会收到错误消息 部署 FTP 错误 登录后无法 chdir 我通过 chmod ing 我的 complete path to magento installation dir 成功完成了第一次连接和设置下载器 至 0777 在 d
  • Apache Tomcat 服务器不在添加新服务器的列表中

    我需要添加 Apache Tomcat 服务器 但 Apache 文件夹中只有 Geronimo 服务器 如何解决这个问题 STS 4 0 0 0 M12 STS4 发行版不包含这些开箱即用的适配器 因为我们出于各种原因 减少启动时间 减小
  • Angular 2 - 使用共享服务

    看起来共享服务是解决许多情况的最佳实践 例如组件之间的通信或替换旧的 Angular 1 的 rootscope 概念 我正在尝试创建我的服务 但它不起作用 有什么帮助吗 泰 应用程序组件 ts import Component from
  • 哪里可以下载 Microsoft.Phone.WinJS.2.1?

    我正在尝试使用 WinJS 制作通用 Windows 应用程序 我已经下载了VS2013的最新更新 RC 版本 我已经安装了我能找到的所有 SDK 我还安装了 WinLibJS VSE exe 扩展 有趣的是 VS 更新一直说我没有 当我打
  • 打印时字体颜色发生变化

    我这里有一个非常令人困惑的问题 我有一个动态构建的表 这里可能是一个不重要的事实 但只是让你知道 在网页上 我根据逻辑标准将文本设置为特定颜色 在页面上 看起来很棒 当进行打印预览 和实际打印 时 颜色有很大不同 在我的代码中 颜色是 红色
  • Laravel 通过表名获取模型

    有没有办法通过表名获取模型 例如 我有一个 用户 模型 其表定义为protected table users 现在 我想做的是通过等于 users 的表名获取模型 这个函数更像是相反的Model getTable 我到处搜索但找不到解决方案
  • 使用 BizTalk Web 服务重新发布内部 Web 服务

    我正在尝试使用 BizTalk 在两个 Web 服务之间进行通信 它必须是这样的 Service1获取输入并通过 BizTalk 发送消息Service2 Service2响应该消息 将其转发至 BizTalk 并将其传递至Service1
  • 导出到 Excel 电子表格 (XLSX) 失败

    使用 ASP NET 网页 我将一些数据导出到 Excel 电子表格 XLSX 当我使用 Visual Studio 运行代码时 代码运行良好 它正在导出具有正确数据的 XLSX 文件 但在部署到测试服务器时 相同的代码会失败 它不会抛出任
  • 在 VC9 中编译时不会出现警告级别 4 的警告。为什么人们不认为这是一种编译器缺陷呢?

    我看到一些发布的代码有超出范围的错误 这让我感到好奇 我希望编译器为此代码生成警告 至少在最高级别 pragma warning push 4 int main int x 2 x 2 0 return 0 pragma warning p
  • 如何打印HttpResponse返回的消息?

    我的 Android 手机上有此代码 URI uri new URI url HttpPost post new HttpPost uri HttpClient client new DefaultHttpClient HttpRespon
  • 自定义rightBarButtonItem消失

    我在导航栏中有一个自定义 rightBarButtomItem 的奇怪错误 我有一个 TabBar 应用程序 如果应用程序已加载 按钮将显示正确 如果我单击选项卡 按钮将继续显示 如果我返回到已显示的选项卡之一 该按钮就会消失 最后 该按钮