iOS10 navigationBar 背景更改延迟问题

iOS10 SDK 中对 UIKitUINavigationBar, 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: 方法里更改都会有问题。

bug 截图

// 具体原因以后排查了再总结

解决思路:

既然生命周期方法不准时了,但是可以看到点击 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;
}

备注 :如果您有更好的解决办法,请告诉我~

参考:

本文链接:http://sanyucz.top/2016/09/18/iOS_10-modify-navigationbar-background/

posted @ 2016-09-19 18:21  王修斌  阅读(627)  评论(0编辑  收藏  举报