我们带着几个问题来看这篇。
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跳转原生的时候,需要监听参数,跳转别的页面。或者是跳转的时候,进行权限验证。
网友评论