美文网首页
『ios』路由拦截器实现和一些思路

『ios』路由拦截器实现和一些思路

作者: butterflyer | 来源:发表于2021-05-31 20:46 被阅读0次

    我们带着几个问题来看这篇。
    1.什么是路由拦截器,路由拦截器的用处。
    2.路由拦截器是如何实现的。
    3.路由拦截器在项目中的用途。

    1.在组件化开发中,我们不管是原生和原生之间的跳转,还是weex跳转原生,或者是weex跳转h5,或者原生跳转flutter,都需要用到路由拦截器,目的是为了在push操作执行的时候进行拦截,来做我们想要处理的操作,比如添加参数,再比如监听参数,显示不同的界面。一切的操作只是为了我们代码更好的可读性和可复用性。

    2.路由拦截器如何实现的呢?


    image.png

    可以先看一下路由plist文件,有个大致的心里概念。

    我们通过RouterPostcard来进行组件之间的传参和解析

    - (instancetype)initWithURLString:(NSString *)url withParameter:(NSDictionary *)parame {
        
        if (self = [super init]) {
            
            // 默认隐藏底部导航栏
            _hidesBottomBar = YES;
            _parameter = parame;
    
            if (url.length != 0) {
                
                NSURLComponents *components = [self getURLComponents:url];
                _originalURL = components.URL;
                _host = components.host;
                _scheme = components.scheme;
                _path = components.path;
                _query = components.query;
                
                NSMutableDictionary *parameDict = [NSMutableDictionary dictionary];
                if (_query) {
                    for (NSURLQueryItem *item in components.queryItems) {
                        parameDict[item.name] = item.value;
                    }
                }
                [parameDict addEntriesFromDictionary:_parameter];
                _parameter = [parameDict copy];
            }
        }
        return self;
    }
    
    - (NSURLComponents *)getURLComponents:(NSString *)urlString {
        
        if (@available(iOS 9.0, *)) {
            urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        } else {
            urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        }
        
        NSURLComponents *components = [NSURLComponents componentsWithURL:[NSURL URLWithString:urlString] resolvingAgainstBaseURL:NO];
        
        if (components.scheme.length == 0) {
            components.scheme = [ZPMRouterConfiguration getUrlScheme];
        }
        
        if (components.host.length == 0) {
            components.host = [ZPMRouterConfiguration getUrlHost];
        }
        return components;
    }
    
    

    下面我们需要拿到我们的路由plist文件解析出来的字典对象。

     pageInfo = [ZPMRouterConfiguration getRouterUrlDict];
      postcard.interception = pageInfo[kZPMRouterInterception];
    

    然后我们就可以通过操作全局拦截器或者是自定义拦截器了。

    // 全局拦截器与自定义拦截器
        [self interceptorHandle:postcard complete:^(BOOL isContinue) {
            if (isContinue) {
                onJumpHandle();
            } else {
                if (callback.onInterrupt) {
                    callback.onInterrupt();
                }
            }
        }];
    
    
    - (void)interceptorHandle:(ZPMRouterPostcard *)postcard complete:(void(^)(BOOL isContinue))block {
        
        id<ZPMRouterGlobalInterceptorProtocol> globalInterceptor = [ZPMRouterConfiguration getGlobalInterceptor];
       // 先执行全局拦截器
        [self excute:globalInterceptor postcard:postcard complete:^(BOOL isContinue) {
           
            NSString *interceptorClass = postcard.interception[kZPMRouterInterceptorClass];
            //如果找到自定义拦截器就去执行自定义拦截器
            if (isContinue && interceptorClass) {
                id<ZPMRouterInterceptorProtocol> customInterceptor = [[[self findClass:interceptorClass] alloc] init];
                [self excute:customInterceptor postcard:postcard complete:block];
            } else {
                block(isContinue);
            }
        }];
    }
    
    - (void)excute:(id<ZPMRouterInterceptorProtocol>)obj postcard:(ZPMRouterPostcard *)postcard  complete:(void(^)(BOOL isContinue))block {
       // 再执行自定义拦截器
        if ([obj respondsToSelector:@selector(interceptorProcess:complete:)]) {
            [obj interceptorProcess:postcard complete:block];
        } else {
            block(YES);
        }
    }
    
    

    这里就要说下这个全局拦截器和自定义拦截器了。

    /// 自定义拦截器
    @protocol ZPMRouterInterceptorProtocol <NSObject>
    
    /// 拦截器处理 isContinue(YES) 继续执行router操作, isContinue(NO) 中断router操作
    - (void)interceptorProcess:(nonnull ZPMRouterPostcard *)postcard complete:(void(^)(BOOL isContinue))isContinue;
    
    @end
    
    /// 全局拦截器 【自动注册】【唯一】
    @protocol ZPMRouterGlobalInterceptorProtocol <ZPMRouterInterceptorProtocol>
    
    @end
    

    全局拦截器要保证唯一性
    在不阻断push操作的前提下,进行拦截操作。
    isContinue这个block函数,来决定是继续进行push操作,还是拦截住不让跳转。

     isContinue(YES);
    Class ModelClass = NSClassFromString(@"ZLRTCGlobalRouterInterceptor");
        if (ModelClass) {
            SEL selector = NSSelectorFromString(@"interceptorProcess:");
            IMP imp = [ModelClass methodForSelector:selector];
            id (*func)(id, SEL,id) = (void *)imp;
            if ([ModelClass respondsToSelector:selector]) {
                func(ModelClass, selector,postcard);
            }
        }
    

    自定义拦截器呢?
    正如最开始的截图所展示的,需要配置在plist文件中,然后遵守自定义ZPMRouterInterceptorProtocol的协议,并执行- (void)interceptorProcess:(nonnull ZPMRouterPostcard *)postcard complete:(void(^)(BOOL isContinue))isContinue;

    关于拦截器在项目中的用途。
    就比如在weex跳转原生的时候,需要监听参数,跳转别的页面。或者是跳转的时候,进行权限验证。

    相关文章

      网友评论

          本文标题:『ios』路由拦截器实现和一些思路

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