UINavigationBar topItem / items似乎是双弹出的

时间:2010-10-13 07:04:59

标签: objective-c cocoa-touch uikit uinavigationbar

我正在管理自己的UINavigationBar。由于皮肤粗糙,我需要这样做。 UINavigationController的文档警告说,当与UINavigationController一起使用时,对UINavigationBar进行外观设置存在限制。

我已经进行了大量的日志记录,从我能说的一切开始,按下UINavigationController中的“后退”按钮会弹出两个项目,而不是一个。我得到一个委托回调告诉我它正在删除逻辑项,但它实际上删除了那一个。

添加到awakeFromNib中的UINavigationController的项应该永远被删除。它出于某种原因被删除了。

有两个相似的问题,但都没有令人满意的答案。这两个问题是:

UINavigationBar .items accessor doesn't return the current UINavigationItem

UINavigationBar seems to pop 2 items off stack on "back"

- (void)awakeFromNib {
    [headerView setDelegate: self];
    [headerView pushNavigationItem: tableDisplay animated: NO];
}

- (void) selectedStory: (NSNotification *)not {
    [headerView pushNavigationItem: base animated: NO];
    NSLog(@"Selected story: %@", base);
}

- (void) baseNav {
    NSLog(@"Current items: %@", [headerView items]);
    BaseInnerItem *current = (BaseInnerItem *)[headerView topItem];
    [self addSubview: [current view]];
}

- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPushItem: (UINavigationItem *)item {
    return YES;
}

- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPopItem: (UINavigationItem *)item {
    return YES;
}

- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item {
    NSLog(@"didPushItem: %@", item);
    [self baseNav];
}

- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item {
    NSLog(@"didPopItem: %@", item);
    [self baseNav];
}

编辑以从单次运行添加相关调试:

2010-10-13 02:12:45.911 Remix2[17037:207] didPushItem: <TableDisplay: 0x5d41cc0>
2010-10-13 02:12:45.912 Remix2[17037:207] Current items: (
    "<TableDisplay: 0x5d41cc0>"
)
2010-10-13 02:12:49.020 Remix2[17037:207] didPushItem: <WebDisplay: 0x591a590>
2010-10-13 02:12:49.021 Remix2[17037:207] Current items: (
    "<TableDisplay: 0x5d41cc0>",
    "<WebDisplay: 0x591a590>"
)
2010-10-13 02:12:49.023 Remix2[17037:207] Selected story: <WebDisplay: 0x591a590>
2010-10-13 02:12:59.498 Remix2[17037:207] didPopItem: <WebDisplay: 0x591a590>
2010-10-13 02:12:59.499 Remix2[17037:207] Current items: (
)

2 个答案:

答案 0 :(得分:0)

根据[super awakeFromNib]的文档,当子类实现该方法时,您总是必须调用-awakeFromNib

  

您必须调用awakeFromNib的超级实现,以便为父类提供执行所需的任何其他初始化的机会

然而,重要的是......

我不明白为什么你必须实际管理自己的导航栏。如果你继承UINavigationBar并且只覆盖某些绘图或布局方法,例如-drawRect:-layoutSubviews等,那么管理导航控制器中导航栏背后的所有逻辑都会掉下来回到最初的UINaviationBar班。

我必须为几乎所有主要UIKit类做大量的视图自定义,但我总是将复杂的逻辑留给原始类,只覆盖绘图方法来自定义外观。

顺便说一句,如果您正在使用自定义图像资源,那么在没有子类化的情况下整个应用程序实际上要容易得多。通过设置图层的contents属性,您可以根据需要或整个应用自定义基于UIView的类的外观:

#import <QuartzCore/QuartzCore.h>
...
- (void)viewDidLoad
{
    [super viewDidLoad];

    UIImage * navigationBarContents = [UIImage imageNamed:@"navigation-bar"];
    self.navigationController.navigationBar.layer.contents =    
        (id)navigationBarContents.CGImage;
}

您可以为从UIView继承的任何类设置内容:导航栏,工具栏,按钮等。这样管理起来要容易得多,而不需要进行子类化。

答案 1 :(得分:0)

这似乎是-[UINavigationBar items]

实施中的一个错误

-navigationBar:didPopItem:委托方法内部调用时,它将省略最后一个对象。您可以通过调用[navigationBar valueForKey:@"_itemStack"]来检查底层数组,并查看预期的项目是否仍在那里。

dispatch_async方法中添加-navigationBar:didPopItem:成功解决了我的应用中的问题。