iOS开发:路由组件

项目改造的需要,重新捣弄了路由的代码,抽离出来「路由组件」。

设计目标

目前大部分的开源路由组件其实已经可以满足基本需求了,比如参数解析、scheme分离等JLRoutes也都支持。但有些别的特性,比如拦截器,比如更动态的配置,还需要重新实现,这也是本文的「路由组件」的主要目标。路由只是路由,关于模块化与路由,以前有简单表达过自己的看法,这里不再赘述。

本文将用接口的方式简要介绍「路由组件」的功能。

拦截器

场景挺常见的。

拦截器接口定义如下:

1
2
3
4
5
6
7
8
9
10
typedef void(^HTRouteInterceptorResultBlock)(BOOL pass, id<HTRouteRequestProtocol>_Nullable  redirectRequest);

//! 路由拦截器
@protocol HTRouteInterceptorProtocol <NSObject>

- (NSInteger)interceptorLevel;
//! 拦截器的意义要求此方法须同步方式执行
- (void)onRoute:(id<HTRouteDefinitionProtocol>)route request:(id<HTRouteRequestProtocol>)request result:(HTRouteInterceptorResultBlock)result;

@end

对于一个可路由的URL,在发起路由请求后、实际执行路由前,我们提供拦截的机会:

  1. 中断路由
  2. 延迟路由
  3. 转发路由

拦截器由业务方定义的,只要遵循接口并在运行时注入到路由系统即可。

中断路由,是对于一些极端情况处理;延迟路由比较常见,比如对于用户未登录的情况,需要跳转到登录页面执行完登录流程后,再执行路由;转发路由也比较容易理解。

路由定义

想要支持

  • 多路径匹配,也就需要允许匹配一个路由后,可以允许继续进行后续的匹配;
  • 匹配模式,是否严格匹配、或是允许fallback;
  • 数据响应,允许返回Object;

以下是路由的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//! 路由定义
@protocol HTRouteDefinitionProtocol <NSObject>

@property (nonatomic, assign) HTRouteMatchMode matchMode;// 匹配模式
@property (nonatomic, assign) BOOL continueNext;// 匹配成功后是否允许后续匹配
@property (nonatomic, assign) CGFloat priority;// 优先级
@property (nonatomic, assign) BOOL skipInterception;// 拦截器

@property (nonatomic, copy, readonly) NSString *scheme;
@property (nonatomic, copy, readonly) NSString *pattern;
@property (nonatomic, copy, readonly) NSArray <NSString *> *patternPathComponents;
@property (nonatomic, copy, readonly) HTRouteHandlerBlock handlerBlock;
@property (nonatomic, copy, readonly) HTRouteObjectBlock objectBlock;// 待定

- (instancetype)initWithRoutePattern:(NSString *)pattern handlerBlock:(HTRouteHandlerBlock)handlerBlock;
- (instancetype)initWithRoutePattern:(NSString *)pattern objectBlock:(HTRouteObjectBlock)objectBlock;

- (id<HTRouteResponseProtocol>)routeResponseForRequest:(id<HTRouteRequestProtocol>)request;
- (BOOL)executeWithResponse:(id<HTRouteResponseProtocol>)response callback:(HTRouteCompletionBlock)callback;

@end

动态配置

指的是,可以在添加路由时,单独针对单个路由动态配置。

接口定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//! 路由请求配置
@protocol HTRouterConfigurationProtocol <NSObject, NSCopying>

@property (nonatomic, copy, readonly) id<HTRouterConfigurationProtocol> _Nonnull (^match)(HTRouteMatchMode matchMode);
@property (nonatomic, copy, readonly) id<HTRouterConfigurationProtocol> _Nonnull (^prefer)(HTRoutePreferOption preferOption);
@property (nonatomic, copy, readonly) id<HTRouterConfigurationProtocol> _Nonnull (^transition)(HTRouteTransitionType transition);
@property (nonatomic, copy, readonly) id <HTRouterConfigurationProtocol> _Nonnull (^addParameters)(NSDictionary *parameters);
@property (nonatomic, copy, readonly) id <HTRouterConfigurationProtocol> _Nonnull (^addInterceptor)(id<HTRouteInterceptorProtocol> interceptor);// 暂不支持
// from 来源配置

@property (nonatomic, assign, readonly) HTRoutePreferOption preferOption;
@property (nonatomic, assign, readonly) HTRouteTransitionType transitionType;
@property (nonatomic, assign, readonly) HTRouteMatchMode matchMode;
@property (nonatomic, strong, readonly, nullable) NSDictionary<NSString *,id> *parameters;
@property (nonatomic, strong, readonly, nullable) NSArray *interceptors;

@end

还差什么?

首先,实现上可能还有bug,不过明显的bug肯定是容易发现、修复的。设计上的问题,可能要做一定调整。

再者,没有类似Java的注解功能,一些语法糖还不支持(但折腾宏的话,其实可以实现一部分的)。

另一方面,我们也要思考,需不需要,适不适合,值不值得。路由库尽量只做路由库的功能,业务嵌入的部分是要单独适配的。不是很喜欢侵入性太高的方案。

Author: Jason

Permalink: http://blog.knpc21.com/ios/ios-lib-router/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。

Comments