更改 navigationItem 的 barButtonItem

Posted

技术标签:

【中文标题】更改 navigationItem 的 barButtonItem【英文标题】:Change navigationItem's barButtonItem 【发布时间】:2011-05-24 14:31:03 【问题描述】:

我有一个 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...

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

【问题讨论】:

您是否使用后台线程来处理您的数据? 【参考方案1】:

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

由于您应该只从主线程调用UIKit 方法,因此您应该通过以下方式调用spinEnd

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

【讨论】:

你好@Daniel 谢谢你的回复。我使用另一个线程来启动微调器。如果我使用相同的线程,微调器不会出现。这是重新加载方法:-(IBAction)refreshFeeds:(id)sender if (stories) [stories release]; stories = nil; [self parseXMLFileAtURL:_theUrl]; 在 parseXMLFileAtURL 中,我通过执行以下操作启动微调器:[NSThread detachNewThreadSelector: @selector(spinBegin) toTarget:self withObject:nil];,在 NSXMLParser 的 parserDidEndDocument 方法中,我使用 [NSThread detachNewThreadSelector: @selector(spinEnd) toTarget:self withObject:nil]; 停止它。 如果我使用你的建议(启动和停止微调器)它永远不会出现。我错过了什么? 它可能不会显示,因为您正在通过阻塞主线程同步下载和解析 XML,因此 UIKit 永远没有机会进行任何绘图(例如显示微调器)。你应该做的是正常启动微调器,然后在后台线程上进行下载/解析,然后当完成时,回调到主线程以停止微调器。【参考方案2】:

您的属性是retained 吗?你正在做和alloc] init...,但在将它们分配给你的属性后没有释放它们。我建议查看Memory Management Guide

【讨论】:

以上是关于更改 navigationItem 的 barButtonItem的主要内容,如果未能解决你的问题,请参考以下文章

更改 navigationItem 的 barButtonItem

想要更改 NavigationItem 标题

NavigationItem 点击范围更改

更改 NavigationItem 提示时出现奇怪的动画

如何重新加载 NavigationItem 标题

navigationItem backBarButtonItem 标题