【问题标题】:Is it possible to change the navigation bar title outside of viewDidLoad/viewWillAppear?是否可以在 viewDidLoad/viewWillAppear 之外更改导航栏标题?
【发布时间】:2012-11-10 14:05:20
【问题描述】:

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

[[self navigationItem] setTitle:myTitle];

它在 viewDidLoad 和 viewWillAppear 中运行良好,但在其他任何地方都无法运行。我正在尝试做的事情可能吗?这是我正在使用的视图控制器。

【问题讨论】:

    标签: ios uinavigationbar uinavigationitem


    【解决方案1】:

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

    self.title = @"New Title";
    

    在导航控制器中的视图控制器上调用它会导致导航栏中显示的标题更新为新标题。

    可以在显示视图控制器时随时调用。

    设置标题无需深入视图控制器的navigationItem

    【讨论】:

    • 我试过了,但即使显示视图控制器,它也没有改变标题。当您说“位于导航控制器中的视图控制器”时,我想我不知道您的意思。请解释一下。
    • 您是将视图控制器添加到 UINavigationController 还是只是将 UINavigationBar 添加到视图控制器?
    • 我假设我将视图控制器添加到导航控制器,因为这是我从另一个视图控制器调用它的方式:[[self navigationController] pushViewController:sentenceViewController animated:YES];
    • 是的,没错。在我自己的应用程序和我创建的一个简单测试应用程序中,调用self.title = @"Some title" 可以很好地更改当前视图控制器的标题。如果它不适合您,那么一定有其他事情发生。
    • 您能猜出是什么原因导致无法在 viewDidLoad/viewWillAppear 之外更新标题吗?
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      如果您需要自定义导航栏,您可以在 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)然后为任何其他的子类在您的应用中查看控制器。

      【讨论】:

      • 从 iOS 5.0 开始,您可以简单地使用 UINavigationBar 的外观 API。不需要您发布的任何代码(从 iOS 5.0 开始)。
      • 由于您唯一更改的是textColor,因此请使用UINavigationBar titleTextAttributes 方法。如果您想对应用程序中的每个导航栏进行更改,请致电[UINavigationBar appearance].titleTextAttributes = ...
      【解决方案4】:

      您可以在viewDidLoad 中设置标题,因为该视图尚不可见但已激活。 viewWillAppear 的情况相同。在UIElement 可见后,没有redraw 就无法更改标题。

      【讨论】:

      • 我试过了:[self.view setNeedsDisplay];更改导航栏标题后,但没有更改标题。
      • 我也试过了:[self.navigationItem.titleView setNeedsDisplay];那也没用。
      • 嗯。您可以尝试在更改导航项后读出它的标题,并确保实际设置了新标题。
      • 尝试 NSLog(@"title: %@", self.navigationItem.title);
      【解决方案5】:

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

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

      【讨论】:

        猜你喜欢
        • 2015-12-24
        • 2019-09-23
        • 1970-01-01
        • 1970-01-01
        • 2014-09-30
        • 1970-01-01
        • 1970-01-01
        • 2020-03-08
        • 2020-10-25
        相关资源
        最近更新 更多