iOS10 navigationBar 背景更改延迟问题
iOS10 SDK 中对 UIKit
中 UINavigationBar
, UITabBar
, 和 UIToolbar
的背景、阴影等实现做出更新和统一,导致了一些不算是bug的bug。
In iOS 10, UIKit has updated and unified background management for UINavigationBar, UITabBar, and UIToolbar. In particular, changes to background properties of these views (such as background or shadow images, or setting the bar style) may kick off a layout pass for the bar to resolve the new background appearance.
In particular, this means that attempts to change the background appearance of these bars inside of layoutSubviews, -[UIView updateConstraints], viewWillLayoutSubviews, viewDidLayoutSubviews, updateViewConstraints, or any other method that is called in response to layout may result in a layout loop.
问题是这样的:项目中有个别的控制器当被push进来的时候会更改 viewController.navigationController.navigationBar
的背景图片和阴影图片,在该控制器被 pop 出来的的时候再去把 navigationBar
的状态更改回来。但是在该控制器的 viewWillDisappear:
或者 前一个控制器的viewWillAppear:
方法里更改都会有问题。
// 具体原因以后排查了再总结
解决思路:
既然生命周期方法不准时了,但是可以看到点击 backItem
会有bug,但是用系统左划手势却没有, 那就在 pop/push 的时候去更改。在自定义的 NavigationController
中重写
- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;
- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (nullable NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
比如:
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
UIViewController *returnController = [super popViewControllerAnimated:animated];
// update navigationBar style
return returnController;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// update navigationBar style
return [super pushViewController:viewController animated:animated];
}
如果在这里不方便修改的话(并不是所有的控制器被 pop/push
)进来都需要修改 navigationBar
,按照该思路可以设一个代理。
在 自定义当行控制器的 .h 文件
#import <UIKit/UIKit.h>
@class PFNavigationController;
@protocol PFNavigationControllerDelegate <NSObject>
@optional
- (void)pfNavigationController:(PFNavigationController *)pfNavigationController willPopViewControllerAnimated:(BOOL)animated;
@end
@interface PFNavigationController : UINavigationController
@property (nonatomic, weak) id<PFNavigationControllerDelegate> PFDelegate;
@end
然后在 .m 实现文件中
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
UIViewController *returnController = [super popViewControllerAnimated:animated];
// update navigationBar style
if ([self.PFDelegate respondsToSelector:@selector(pfNavigationController:willPopViewControllerAnimated:)]) {
[self.PFDelegate pfNavigationController:self willPopViewControllerAnimated:animated];
}
return returnController;
}
备注 :如果您有更好的解决办法,请告诉我~
参考:
- Navigationbar coloring in ViewWillAppear happens too late in iOS 10
- iOS SDK Release Notes for iOS 10.0
本文链接:http://sanyucz.top/2016/09/18/iOS_10-modify-navigationbar-background/