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;
}
Il s'agit d'une question sur le cycle de vie de
UINavigationController
(en supposant que votreLMSNavigationController
soit sa sous-classe) etUIViewController
(ci-après dénommé VC). . .Version simple de la réponse
Changer de VC A
viewDidLoad
enviewWillAppear
.(Il existe une meilleure méthode ci-dessous.)
Version compliquée (pas si compliquée...)
Regardons d'abord comment le document décrit viewDidLoad :
Cette méthode sera appelée lorsque la vue VC sera chargée en mémoire. Le VC B
pop
ne remplit pas les conditions pour appeler les VC AviewDidLoad
en sortant. L'explication est la suivante :
LorsqueUINavigationController
maintient une pile VC, et vouspush
etpop
exploitez cette pile lorsque vous utilisez ces VC.
Alorspush
il créera un nouveau VC et le poussera sur la pile, qui est votre VC B Au cours de ce processus, ce nouveau VC B est lié subit le processus d'ajout à la mémoire, etview
est appelé.viewDidLoad
VC B est au sommet de la pile et devient .topViewController
VC A n'est plus en haut de la pile, mais est toujours sur la pile, et sonview
associé est toujours en mémoire . Lorsque lepop
VC B s'éteint, le de la vue associée au VC A n'est plus appelé.viewDidLoad
push
Comment s'appelle-t-on exactement ?pop
Source de l'image : Surveillance des modifications apportées à la section Pile de navigation de la documentation du contrôleur de navigation
Prenonspush
VC B sortant comme exemple :VC B En tant que contrôleur de vue le plus haut actuel, son est appelé en premier
LeviewWillDispear
VC A s'appelle
viewWillAppear
de
UINavigationControllerDelegate
s'appellenavigationController:willShowViewController:animated:
VC B s'appelle
LeviewDidDispear
VC A s'appelle
viewDidAppear
de
UINavigationControllerDelegate
s'appellenavigationController:didShowViewController:animated:
En résumé, les de VC A
viewDidLoad
peuvent être remplacés parviewWillAppear
.Cependant, je pense personnellement qu'une meilleure façon est de diviser les deux
viewDidLoad
et de réécrire la logique dans lesUINavigationControllerDelegate
denavigationController:willShowViewController:animated:
. Vous pouvez résoudre le besoin de modifier l’image d’arrière-plan en un seul endroit.Fin.
Mettre à jour, utilisez
UINavigationControllerDelegate
comme mentionné ci-dessus :viewWillAppear
Je l'ai aussi essayé, c'est exactement le même que celui-ci, aucun cadre noir n'apparaît. En ce qui concerne cette question, ces deux lieux répondent à vos exigences. Choisissez simplement ce que vous aimez.Le contrôleur de navigation fourni avec le système a déjà fait ce qu'il devait faire avant le début de l'animation, il n'y aura donc pas de chargement d'image avant la moitié de l'animation. Le pire, c'est que l'animation sera bloquée quelques secondes avant de démarrer, et elle ne démarrera qu'après son chargement.
Votre contrôleur de navigation est personnalisé. Vérifiez la partie personnalisée pour voir s'il y a des boîtes noires causées par des problèmes.
(Aussi... je ne vois toujours pas où l'image de fond a été modifiée. Ce n'est pas l'image du bouton qui a été modifiée sur la première manette)
Tous les VC sous nav partagent la même navBar
Vous avez modifié la navBar en entrant dans B
mais ne l'avez pas modifiée en quittant B
Vous disposez de deux contrôleurs de barre de navigation (pop). La barre de navigation renvoyée est la même que la barre de navigation actuelle. Vous devez créer un proxy et réaffecter la valeur. (Mais c'est plus gênant)
Vous devez avoir modifié la couleur ou l'image de la barre de navigation en B
Essayez à nouveau de définir l'image d'arrière-plan de vc dans la méthode viewWillAppear de A