美文网首页iOS Developer
UINavigationController 默认返回按钮 处理

UINavigationController 默认返回按钮 处理

作者: youlianchun | 来源:发表于2018-01-13 21:37 被阅读0次

    之前写过一个处理这个玩意儿的文章,主要是设置返回按钮的文字和图片,今天介绍一个新做法,几个api自行谷歌,我就直接上代码了

    为了方便,定义两个类型

    typedef void(^PushBlock)(UINavigationController* self, UIViewController* viewController, BOOL animated);
    typedef void(*PushIMP)(id, SEL, UIViewController*, BOOL);
    

    定义一个拦截函数(私有)

    /**
     拦截 -[UINavigationController pushViewController:animated:]
    
     @param push block代码块
     */
    static void intercept_push(PushBlock push)
    {
        static PushBlock will_push;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class nvc_class = [UINavigationController class];
            SEL push_sel = @selector(pushViewController:animated:);
            Method push_method = class_getInstanceMethod(nvc_class, push_sel);
            PushIMP push_imp = (PushIMP)method_getImplementation(push_method);
            IMP push_block = imp_implementationWithBlock(^(UINavigationController* self, UIViewController* viewController, BOOL animated) {
                if (will_push) {
                    will_push(self, viewController, animated);
                }
                push_imp(self, push_sel, viewController, animated);
            });
            class_replaceMethod(nvc_class, push_sel, push_block, method_getTypeEncoding(push_method));
        });
        will_push = push;
    }
    

    定义一个设置函数(公开)

    /**
     设置UINavigationController默认返回按钮内容
    
     @param image nil时为默认
     @param title nil时为默认
     */
    void set_nvc_default_back(UIImage* image, NSString* title)
    {
        static NSString* back_title;
        static PushBlock will_push = ^(UINavigationController* self, UIViewController* viewController, BOOL animated) {
            self.viewControllers.lastObject.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:back_title style:UIBarButtonItemStylePlain target:nil action:nil];
        };
        back_title = title;
        intercept_push(back_title?will_push:nil);
        [[UINavigationBar appearance] setBackIndicatorImage:image];
        [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:image];
    }
    

    下边是使用方式

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        set_nvc_default_back(nil, @"返回");
        
        return YES;
    }
    

    然后,既然做了全局处理,就想着是不是让这玩意能够让指定界面进行定制,用了个简单的办法,如下
    定制一个协议

    /**
     执行 set_nvc_default_back 后有效
     */
    @protocol NavigationBackContentProtocol
    -(NSString*)navigationBackItemTitle;
    @end
    

    然后修改 set_nvc_default_back 为

    void set_nvc_default_back(UIImage* image, NSString* title)
    {
        static NSString* back_title;
        static PushBlock will_push = ^(UINavigationController* self, UIViewController* viewController, BOOL animated) {
            NSString* title = back_title;
            if ([viewController conformsToProtocol:@protocol(NavigationBackContentProtocol)])
            {
                BCPViewController* vc = (BCPViewController*)viewController;
                title = [vc navigationBackItemTitle];
            }
            self.viewControllers.lastObject.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStylePlain target:nil action:nil];
        };
        back_title = title;
        intercept_push(will_push);
        [[UINavigationBar appearance] setBackIndicatorImage:image];
        [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:image];
    }
    

    补充:BCPViewController 是个类型

    typedef UIViewController<NavigationBackContentProtocol> BCPViewController;
    

    相关文章

      网友评论

        本文标题:UINavigationController 默认返回按钮 处理

        本文链接:https://www.haomeiwen.com/subject/orwcoxtx.html