简体   繁体   English

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

[英]Is it possible to change the navigation bar title outside of viewDidLoad/viewWillAppear?

I'm trying to change the navigation bar title with this statement: 我正在尝试使用以下语句更改导航栏标题:

[[self navigationItem] setTitle:myTitle];

It works fine in viewDidLoad and viewWillAppear, but it doesn't work anywhere else. 它在viewDidLoad和viewWillAppear中工作正常,但它在其他任何地方都不起作用。 Is what I am trying to do possible? 我正在尝试做什么? It's a view controller I'm working with. 这是我正在使用的视图控制器。

There is a very simple way to change the title for the current view controller. 有一种非常简单的方法可以更改当前视图控制器的标题。

self.title = @"New Title";

Calling this on a view controller that is in a navigation controller will result in the title shown in the navigation bar being updated with the new title. 在导航控制器中的视图控制器上调用此选项将导致导航栏中显示的标题使用新标题进行更新。

This can be called at any time while the view controller is displayed. 在显示视图控制器时,可以随时调用此方法。

There is no need to dig into the view controller's navigationItem for setting the title. 无需深入了解视图控制器的navigationItem来设置标题。

I know this is old, but I wanted to answer this for future users. 我知道这是旧的,但我想为将来的用户回答这个问题。 I think the main issue that most answers don't cover is that it is important to set the title from the main thread, otherwise there are a handful of cases where it won't get set immediately. 我认为大多数答案没有涵盖的主要问题是从主线程设置标题很重要,否则有一些情况不会立即设置。 For Swift 3.0 you can use code like this: 对于Swift 3.0,您可以使用以下代码:

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

It is important to do all UI updates from the main thread. 从主线程执行所有UI更新非常重要。 I'm not sure if the original user was setting the title via an asynchronous closure, but this should help anyone who is having difficulties. 我不确定原始用户是否通过异步关闭设置标题,但这应该可以帮助任何有困难的人。

It's actually the view controller's title property that the navigationItem will use. 它实际上是navigationItem将使用的视图控制器的title属性。 The answer above is the simplest and correct way to change the title in the navigation bar. 上面的答案是在导航栏中更改标题的最简单和正确的方法。

If you need to customize your navigation bar, the way you do this is to override it in your UIViewController subclass, NOT change it in viewDidAppear: or any other viewWill/Did methods 如果您需要自定义导航栏,那么执行此操作的方法是在UIViewController子类中覆盖它,而不是在viewDidAppear中更改它:或任何其他viewWill / Did方法

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

  // customize it further than the default

  return navigationItem;
}

In addition, you can have changes in your title update a custom titleView using KVO. 此外,您可以使用KVO更改标题更新自定义titleView。 You listen for changes in the UIViewController's title property and update the titleView property of your navigationItem. 您在UIViewController的title属性中侦听更改并更新navigationItem的titleView属性。 Check this out: 看一下这个:

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;
}

Don't forget to remove the observer: 不要忘记删除观察者:

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

And now we revisit the navigationItem again, where you can create a custom UILabel that will update whenever we change the title, and after that we have to provide a handler implementation for when the title does change: 现在我们再次访问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;
}

And finally, what to do when self.title actually changes: 最后,当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];
    }
}

And there you go! 你去吧! Obviously a bit more code than you might have thought, so if you're not currently, I recommend to anyone building iOS Apps that you always create a base class view controller for your application, (MyBaseViewController : UIViewController) then subclass that for any other view controllers in your app. 显然比你想象的要多一些代码,所以如果你现在没有,我建议任何构建iOS应用程序的人总是为你的应用程序创建一个基类视图控制器,(MyBaseViewController:UIViewController)然后为其他任何子类创建子类查看应用中的控制器。

You can set up the the title in viewDidLoad , because the view is not yet visible but instaciated. 您可以在viewDidLoad设置标题,因为视图尚未可见但是已实现。 Same story for viewWillAppear . viewWillAppear After the UIElement is visible, you cant change the title without a redraw . UIElement可见之后,您无法在不redraw情况下更改标题。

@reid55 you can set navigation title in below method also: @ reid55你也可以在下面的方法中设置导航标题:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM