更改 navigationItem 的 barButtonItem

发布于 2024-11-09 02:43:01 字数 3626 浏览 2 评论 0原文

我有一个 UIViewController。我使用 navigationItem 的 rightBarButtonItem 作为“重新加载按钮”。当按下重新加载按钮时,我使用 leftBarButtonItem 在应用程序处理数据以重新加载时显示活动指示器。到这里一切都很好。
这是一些代码:

- (void)initSpinner {
    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    activityButton = [[UIBarButtonItem alloc] initWithCustomView: activityIndicator];
    self.navigationItem.leftBarButtonItem = activityButton;
}

- (void)spinBegin {
    [activityIndicator startAnimating];
}

- (void)spinEnd {
    [activityIndicator stopAnimating];
}
- (void)viewDidLoad {
     [self initSpinner];
     [super viewDidLoad];
    //more stuff going on here....
}
-(void) loadView{
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshFeeds:)];
}

现在我被要求稍微改变一下逻辑。
rightBarButtonItem 保持原样。 leftBarButtonItem 仍然在那里显示活动指示器,但是当没有处理时,它应该显示另一个按钮,按下时将显示一个新视图(用于某些信息)。
所以我做了这些更改:

- (void)initSpinner {
    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    activityButton = [[UIBarButtonItem alloc] initWithCustomView: activityIndicator];
}

- (void)spinBegin {
    self.navigationItem.leftBarButtonItem = activityButton;
    [activityIndicator startAnimating];
}

- (void)spinEnd {
    [activityIndicator stopAnimating];
     self.navigationItem.leftBarButtonItem =infoBarButton; //= [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshFeeds:)] autorelease];
}
-(void) loadView{
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshFeeds:)];

    if (infoBarButton == nil){
        UIImage *buttonImage = [UIImage imageNamed:@"info.png"];
        UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [aButton setImage:buttonImage forState:UIControlStateNormal];
        aButton.frame = CGRectMake(0.0, 0.0, 25, 25);

        // Initialize the UIBarButtonItem
        infoBarButton = [[UIBarButtonItem alloc] initWithCustomView:aButton];

        // Set the Target and Action for aButton
        [aButton addTarget:self action:@selector(showInfo:) forControlEvents:UIControlEventTouchUpInside];


    }
    self.navigationItem.leftBarButtonItem = infoBarButton;
}

虽然它似乎正在工作(信息按钮在那里,当我按“重新加载”时,activityIndi​​cator 会取代它的位置,直到处理完成),我在调试器控制台中得到以下内容:

__NSAutoreleaseNoPool(): Object 0x15ef30 of class UINavigationItem autoreleased with no pool in place - just leaking
 __NSAutoreleaseNoPool(): Object 0x1abd90 of class UIBarButtonItem autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1acb20 of class UIButton autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x15ef30 of class UINavigationItem autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1ad030 of class UIActivityIndicatorView autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1ad030 of class UIActivityIndicatorView autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1a8c40 of class UINavigationButton autoreleased with no pool in place - just leaking
Object 0x941c of class NSCFString autoreleased with no pool in place - just leaking
//MORE similar messages following...

我做错了什么?我希望有人可以帮助...
提前致谢。

I have a UIViewController. I use the the rightBarButtonItem of the navigationItem as a "reload button". When the reload button is press, i use the leftBarButtonItem to display an Activity Indicator while the app is processing data to reload. Everything is ok up to here.
Here is some code:

- (void)initSpinner {
    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    activityButton = [[UIBarButtonItem alloc] initWithCustomView: activityIndicator];
    self.navigationItem.leftBarButtonItem = activityButton;
}

- (void)spinBegin {
    [activityIndicator startAnimating];
}

- (void)spinEnd {
    [activityIndicator stopAnimating];
}
- (void)viewDidLoad {
     [self initSpinner];
     [super viewDidLoad];
    //more stuff going on here....
}
-(void) loadView{
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshFeeds:)];
}

Now i was asked to change the logic a bit.
The rightBarButtonItem stays as is. The leftBarButtonItem is still there to display the activity Indicator, but when there is no processing it should display another button which will display a new view (for some info) when pressed.
So i did these changes:

- (void)initSpinner {
    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    activityButton = [[UIBarButtonItem alloc] initWithCustomView: activityIndicator];
}

- (void)spinBegin {
    self.navigationItem.leftBarButtonItem = activityButton;
    [activityIndicator startAnimating];
}

- (void)spinEnd {
    [activityIndicator stopAnimating];
     self.navigationItem.leftBarButtonItem =infoBarButton; //= [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshFeeds:)] autorelease];
}
-(void) loadView{
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshFeeds:)];

    if (infoBarButton == nil){
        UIImage *buttonImage = [UIImage imageNamed:@"info.png"];
        UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [aButton setImage:buttonImage forState:UIControlStateNormal];
        aButton.frame = CGRectMake(0.0, 0.0, 25, 25);

        // Initialize the UIBarButtonItem
        infoBarButton = [[UIBarButtonItem alloc] initWithCustomView:aButton];

        // Set the Target and Action for aButton
        [aButton addTarget:self action:@selector(showInfo:) forControlEvents:UIControlEventTouchUpInside];


    }
    self.navigationItem.leftBarButtonItem = infoBarButton;
}

Although it seems to be working (info button is there and when i press "reload" the activityIndicator takes its place till processing is done), i get the following in the debugger console:

__NSAutoreleaseNoPool(): Object 0x15ef30 of class UINavigationItem autoreleased with no pool in place - just leaking
 __NSAutoreleaseNoPool(): Object 0x1abd90 of class UIBarButtonItem autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1acb20 of class UIButton autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x15ef30 of class UINavigationItem autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1ad030 of class UIActivityIndicatorView autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1ad030 of class UIActivityIndicatorView autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x1a8c40 of class UINavigationButton autoreleased with no pool in place - just leaking
Object 0x941c of class NSCFString autoreleased with no pool in place - just leaking
//MORE similar messages following...

What am i doing wrong? I hope someone out there can help...
Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独木成林 2024-11-16 02:43:01

我的猜测是,您正在后台线程中运行“重新加载”任务,当它完成时,您可以从后台线程调用 spinEnd 。如果后台线程没有自动释放池,您将看到这些警告。

由于您应该只从主线程调用 UIKit 方法,因此您应该通过执行以下操作来调用 spinEnd

[self performSelectorOnMainThread:@selector(spinEnd) withObject:nil waitUntilDone:NO];

My guess is that you're running the "reload" task in a background thread, and when it completes you call spinEnd from the background thread. If the background thread doesn't have an autorelease pool in place, you will see those warnings.

Since you should only ever call UIKit methods from the main thread, you should call spinEnd by doing:

[self performSelectorOnMainThread:@selector(spinEnd) withObject:nil waitUntilDone:NO];
╰つ倒转 2024-11-16 02:43:01

您的属性是否被保留?您正在执行alloc] init...,但在将它们分配给您的属性后并没有释放它们。我建议查看内存管理指南

Are your properties being retained? You are doing and alloc] init... but aren't releasing them after assigning them to your properties. I'd suggest checking out the Memory Management Guide

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文