IOS导航栏的问题

ios 两个状态栏 背景图片不一样 push过去正常显示
返回(pop)回来,当前的背景图变成了push过去的那个导航栏的背景图片.
用图片演示:
1.这是控制器A:
图片描述
2.设置push过去的控制器B:
图片描述
3.点击返回后的控制器A:
图片描述

为什么控制器A的导航栏的背景图片变成了控制器B的?如何修改?

代码奉上:
自定义控制器的所有代码:

#import "LMSNavigationController.h"

@interface LMSNavigationController ()

@end

@implementation LMSNavigationController

- (void)viewDidLoad {

[super viewDidLoad];

[self.navigationBar setTitleTextAttributes:

@{NSFontAttributeName:[UIFont systemFontOfSize:16]}];

}

/**

* 在这个方法中拦截所有push进来的控制器

*/

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated

{

if (self.childViewControllers.count > 0) {

// 如果push进来的不是第一个控制器

UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];

[leftBtn setImage:[UIImage imageNamed:@"nav-back.png"] forState:UIControlStateNormal];

[leftBtn setImage:[UIImage imageNamed:@"nav-back-hi.png"] forState:UIControlStateHighlighted];

leftBtn.frame = CGRectMake(0, 0, 30, 30);

[leftBtn addTarget:self action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];

viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:leftBtn];

// 隐藏tabbar

viewController.hidesBottomBarWhenPushed = YES;

}

//把导航栏底部的横线去掉

[self.navigationBar setShadowImage:[UIImage new]];

// 这句super的push要放在后面, 让viewController可以覆盖上面设置的leftBarButtonItem

// 意思是,我们任然可以重新在push控制器的viewDidLoad方法中设置导航栏的leftBarButtonItem,如果设置了就会覆盖在push方法中设置的“返回”按钮,因为 [super push....]会加载push的控制器执行viewDidLoad方法。

[super pushViewController:viewController animated:animated];

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

@end

控制器A关键代码:

- (void)viewDidLoad {

[super viewDidLoad];

//导航栏透明背景(nav-clearcolor-image是一张透明的图片)

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav-clearcolor-image"] forBarMetrics:UIBarMetricsDefault];

//把导航栏底部的横线去掉

[self.navigationController.navigationBar setShadowImage:[UIImage new]];

//不显示文字

self.navigationItem.title = nil;

}

控制器B关键代码:

- (void)viewDidLoad {

[super viewDidLoad];

UILabel *titleLabel = [[UILabel alloc]init];

titleLabel.text = @"push过来的控制器";

titleLabel.textColor = TitleTextColor;

[titleLabel sizeToFit];

self.navigationItem.titleView = titleLabel;

}

回答:

这是个关于 UINavigationController(假设你们的 LMSNavigationController 是它的子类)以及 UIViewController (后文简称 VC )生命周期的问题。。。


简单版本的答案

把 VC A 的 viewDidLoad 改成 viewWillAppear
(下面还有个感觉上更优的办法。)

复杂版本(也杂不到哪去。。。)

先看看文档对 viewDidLoad 是怎么描述的:

Called after the controller'€™s view is loaded into memory.

在 VC 的视图加载进内存的时候,这个方法会被调用。VC B pop 出去的时候不符合调用 VC A 的 viewDidLoad 的条件,解释如下:

UINavigationController 维护着一个 VC 栈,你 pushpop 那些 VC 时都是在操作这个栈。

push 的时候它会创建一个新的 VC 压入栈中,就是你的 VC B,这个过程中这个新的 VC B 绑定的 view 经历了被加入内存的过程, viewDidLoad 被调用。 VC B 处于栈顶,成为 topViewController 。 VC A 不再处于栈顶,但仍处于栈中,与它关联的 view 仍在内存中。再 pop VC B 出去的时候,VC A 关联的 view 的 viewDidLoad 不再被调用。

所以 pushpop 具体调用了什么?

上图

Figure 1-5 Messages sent during stack changes
Figure 1-5  Messages sent during stack changes
图片来源:Navigation Controller 文档的 Monitoring Changes to the Navigation Stack 部分

Monitoring Changes to the Navigation Stack
监控导航栈的变化

push VC B 出去为例:

  1. VC B 作为当前的 Topmost view controller ,其 viewWillDispear 最先被调用

  2. VC A 的 viewWillAppear 被调用

  3. UINavigationControllerDelegatenavigationController:willShowViewController:animated: 被调用

  4. 转场动画(完成?不清楚)

  5. VC B 的 viewDidDispear 被调用

  6. VC A 的 viewDidAppear 被调用

  7. UINavigationControllerDelegatenavigationController:didShowViewController:animated: 被调用

综上, VC A 的 viewDidLoad 改成 viewWillAppear 即可。

然而个人感觉更好的办法是把两个 viewDidLoad 都拆了,逻辑重写在 UINavigationControllerDelegatenavigationController:willShowViewController:animated: 中。即可在一个位置解决改背景图这个需求。

完。


更新,上面说的用 UINavigationControllerDelegate 的办法:

    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {

if self.childViewControllers.count > 1 {

navigationController.navigationBar.setBackgroundImage(UIImage(named: "a"), forBarMetrics: .Default)

} else {

navigationController.navigationBar.setBackgroundImage(UIImage(named: "b"), forBarMetrics: .Default)

}

}

图片描述

viewWillAppear 也试了,跟这个一模一样,没出现黑框。就这个问题而言,这两个地方就是符合你要求的。怎么选看自己喜欢就好。

系统自带的导航控制器在动画开始前已经做完了该做的事,不会出现动画到一半图片才载入完。最差也就是动画开始前卡住几秒,载入完才开始。

你们的导航控制器是自己定制的,检查定制的部分哪里有问题导致的黑框。

(另。。还是没看到背景图在哪改了。不是第一个控制器那里改的是按钮图片啊)

回答:

nav 下的所有 VC 是通用同一个 navBar 的
你在进入 B 的时候修改了 navBar
但是在退出 B 的时候没有改回来

回答:

你有2个导航栏控制器 (pop)回去的导航栏是跟当前的导航栏一样的,应该搞个代理就重新赋值就可以了。(不过比较麻烦)

回答:

你肯定在B中修改了导航条的色或者图了吧

回答:

在A的viewWillAppear方法里面再设置一遍vc的背景图片试试

以上是 IOS导航栏的问题 的全部内容, 来源链接: utcz.com/p/184343.html

回到顶部