美文网首页
『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