iOS解决导航隐藏问题

使用setNavigationBarHidden:animated:方法直接处理,跳转的时候有个跳转很丑。这个就不说了。

FDFullscreenPopGesture
我很喜欢用。
给UIViewController添加一个设置隐藏导航栏的属性af_prefersNavigationBarHidden:

// MARK: - 给UIViewController添加af_prefersNavigationBarHidden属性

@implementation UIViewController (HandlerNavigationBar)

- (BOOL)af_prefersNavigationBarHidden
{
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setLsl_prefersNavigationBarHidden:(BOOL)hidden
{
    objc_setAssociatedObject(self, @selector(af_prefersNavigationBarHidden), @(hidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

hook UIViewController的viewWillAppear:方法,并在此方法中执行已经存好的代码块:

typedef void(^_LSLViewControllerWillAppearInjectBlock)(UIViewController *viewController, BOOL animated);

@interface UIViewController (HandlerNavigationBarPrivate)

@property(nonatomic, copy) _LSLViewControllerWillAppearInjectBlock af_willAppearInjectBlock;

@end

// MARK: - 替换UIViewController的viewWillAppear方法,在此方法中,执行设置导航栏隐藏和显示的代码块。

@implementation UIViewController (HandlerNavigationBarPrivate)

+ (void)load
{
    Method orginalMethod = class_getInstanceMethod(self, @selector(viewWillAppear:));
    Method swizzledMethod = class_getInstanceMethod(self, @selector(af_viewWillAppear:));
    method_exchangeImplementations(orginalMethod, swizzledMethod);
}

- (void)af_viewWillAppear:(BOOL)animated
{
    [self af_viewWillAppear:animated];

    if (self.af_willAppearInjectBlock) {
        self.af_willAppearInjectBlock(self, animated);
    }
}

- (_AFViewControllerWillAppearInjectBlock)af_willAppearInjectBlock
{
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setaf_willAppearInjectBlock:(_AFViewControllerWillAppearInjectBlock)block
{
    objc_setAssociatedObject(self, @selector(af_willAppearInjectBlock), block, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

@end



hook住navigationController的pushViewController:animated:及setViewControllers:animated:方法,当控制器被压入栈中的时候,预存设置隐藏和显示导航栏的代码块到即将显示的控制器中,备控制器调用:

// MARK: - 替换UINavigationController的pushViewController:animated:方法,在此方法中去设置导航栏的隐藏和显示
@implementation UINavigationController (NavigationBar)

+ (void)load
{
    Method originMethod = class_getInstanceMethod(self, @selector(pushViewController:animated:));
    Method swizzedMethod = class_getInstanceMethod(self, @selector(af_pushViewController:animated:));
    method_exchangeImplementations(originMethod, swizzedMethod);

    Method originSetViewControllersMethod = class_getInstanceMethod(self, @selector(setViewControllers:animated:));
    Method swizzedSetViewControllersMethod = class_getInstanceMethod(self, @selector(af_setViewControllers:animated:));
    method_exchangeImplementations(originSetViewControllersMethod, swizzedSetViewControllersMethod);
}

- (void)af_pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // Handle perferred navigation bar appearance.
    [self af_setupViewControllerBasedNavigationBarAppearanceIfNeeded:viewController];

    // Forward to primary implementation.
    [self af_pushViewController:viewController animated:animated];
}

- (void)af_setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
{
    // Handle perferred navigation bar appearance.
    for (UIViewController *viewController in viewControllers) {
        [self af_setupViewControllerBasedNavigationBarAppearanceIfNeeded:viewController];
    }

    // Forward to primary implementation.
    [self af_setViewControllers:viewControllers animated:animated];
}

- (void)af_setupViewControllerBasedNavigationBarAppearanceIfNeeded:(UIViewController *)appearingViewController
{
    if (!self.af_viewControllerBasedNavigationBarAppearanceEnabled) {
        return;
    }

    // 即将被调用的代码块
    __weak typeof(self) weakSelf = self;
    _afViewControllerWillAppearInjectBlock block = ^(UIViewController *viewController, BOOL animated){
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (strongSelf) {
            [strongSelf setNavigationBarHidden:viewController.af_prefersNavigationBarHidden animated:animated];
        }
    };

    // 给即将显示的控制器,注入代码块
    appearingViewController.af_willAppearInjectBlock = block;

    // 因为不是所有的都是通过push的方式,把控制器压入stack中,也可能是"-setViewControllers:"的方式,所以需要对栈顶控制器做下判断并赋值。
    UIViewController *disappearingViewController = self.viewControllers.lastObject;
    if (disappearingViewController && !disappearingViewController.af_willAppearInjectBlock) {
        disappearingViewController.af_willAppearInjectBlock = block;
    }
}

- (BOOL)af_viewControllerBasedNavigationBarAppearanceEnabled
{
    NSNumber *number = objc_getAssociatedObject(self, _cmd);
    if (number) {
        return number.boolValue;
    }
    self.af_viewControllerBasedNavigationBarAppearanceEnabled = YES;
    return YES;
}

- (void)setaf_viewControllerBasedNavigationBarAppearanceEnabled:(BOOL)enabled
{
    SEL key = @selector(af_viewControllerBasedNavigationBarAppearanceEnabled);
    objc_setAssociatedObject(self, key, @(enabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

你可能感兴趣的:(iOS解决导航隐藏问题)