是否可以在viewDidLoad / viewWillAppear之外更改导航栏标题?

时间:2012-11-10 14:05:21

标签: ios uinavigationbar uinavigationitem

我正在尝试使用以下语句更改导航栏标题:

[[self navigationItem] setTitle:myTitle];

它在viewDidLoad和viewWillAppear中工作正常,但它在其他任何地方都不起作用。我正在尝试做什么?这是我正在使用的视图控制器。

5 个答案:

答案 0 :(得分:4)

有一种非常简单的方法可以更改当前视图控制器的标题。

self.title = @"New Title";

在导航控制器中的视图控制器上调用此选项将导致导航栏中显示的标题使用新标题进行更新。

可以在显示视图控制器的任何时候调用它。

无需深入了解视图控制器的navigationItem来设置标题。

答案 1 :(得分:3)

我知道这已经过时了,但我想为将来的用户回答这个问题。我认为大多数答案没有涵盖的主要问题是从主线程设置标题很重要,否则有一些情况不会立即设置。对于Swift 3.0,您可以使用以下代码:

 DispatchQueue.main.async {
        self.title = "Example string"
 }

从主线程执行所有UI更新非常重要。我不确定原始用户是否通过异步关闭设置标题,但这应该可以帮助任何有困难的人。

答案 2 :(得分:2)

它实际上是navigationItem将使用的视图控制器的title属性。上面的答案是在导航栏中更改标题的最简单和正确的方法。

如果您需要自定义导航栏,则执行此操作的方法是在UIViewController子类中覆盖它,而不是在viewDidAppear中更改它:或任何其他viewWill / Did方法

- (UINavigationItem*)navigationItem
{
  UINavigationItem *navigationItem = [super navigationItem];

  // customize it further than the default

  return navigationItem;
}

此外,您可以使用KVO更改标题更新自定义titleView。您在UIViewController的title属性中侦听更改并更新navigationItem的titleView属性。看看这个:

static void *kObjectStateObservingContext = &kObjectStateObservingContext;  // outside your @implementation bit

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // other init stuff here...

        [self addObserver: self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context: kObjectStateObservingContext];
    }
    return self;
}

不要忘记删除观察者:

- (void)dealloc
{
    [self removeObserver: self forKeyPath:@"title"];
}

现在我们再次访问navigationItem,您可以在其中创建自定义UILabel,每当我们更改标题时都会更新,之后我们必须为标题更改时提供处理程序实现:

- (UINavigationItem*)navigationItem
{
    UINavigationItem *navigationItem = [super navigationItem];

    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(roundf((320 - 230)/2), 0, 230, 44)];
    titleLabel.font = [UIFont systemFontOfSize: 18];
    titleLabel.textColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"topnav-background-text-gradient.png"]];  // you can even draw the font with a gradient!
    titleLabel.shadowColor = [UIColor colorWithWhite: 1.0 alpha:0.59];
    titleLabel.shadowOffset = CGSizeMake(0, 1.0);
    titleLabel.text = self.title;
    titleLabel.backgroundColor = [UIColor clearColor];
    titleLabel.textAlignment = UITextAlignmentCenter;

    navigationItem.titleView = titleLabel;

    return navigationItem;
}

最后,当self.title实际发生变化时该怎么办:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ( context == kObjectStateObservingContext ) {
        // here we update the text of the titleView
        if ([self.navigationItem.titleView isKindOfClass:[UILabel class]]) {
            [(UILabel*)self.navigationItem.titleView setText: self.title];
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

你去吧!显然比你想象的要多一些代码,所以如果你现在没有,我建议任何构建iOS应用程序的人总是为你的应用程序创建一个基类视图控制器,(MyBaseViewController:UIViewController)然后为其他任何子类创建子类查看应用中的控制器。

答案 3 :(得分:0)

您可以在viewDidLoad中设置标题,因为该视图尚未显示但已实现。同一个故事viewWillAppearUIElement可见后,您无法在没有redraw的情况下更改标题。

答案 4 :(得分:0)

@ reid55你也可以在下面的方法中设置导航标题:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  if (self) {
   [[self navigationItem] setTitle:myTitle];
}
return self;
}