OC项目优化之路(四)之Router篇

2019-06-05  本文已影响0人  boy丿log

最近对路由与组件化产生了兴趣,写了一个DPRouter。路由与组件化是目前大型app都会去做的事情,他有很多的好处,最大好的好处便是业务解耦,每个项目都可以单独调试。DPRouter,是基于URL-Scheme思想写的,拥有以下功能:

无入侵

无入侵指的是在添加route模块时,只需要创建一个继承于BaseRoute的类,并在其中注册方法,并进行标识。

+ (NSString *)url_identify{
    return @"A";
}

- (void)setup{
    [self registerUrl:@"aa" handle:^BOOL(NSString * _Nonnull url, NSMutableDictionary * _Nonnull para, DPBaseRoute * _Nonnull route) {
        NSLog(@"调用方法");
        [route remove];
        return YES;
    }];
    [self registerUrl:@"jumpToVCA" handle:^BOOL(NSString * _Nonnull url, NSMutableDictionary * _Nonnull para, DPBaseRoute * _Nonnull route) {
        
        return YES;
    }];
}

这个时候就可以在其他模块通过router进行调用了

[[DPRouter router] openRouteUrl:@"A/aa"];

预处理数据

预处理数据指的是可以在调用路由模块业务之前先向路由存储数据。

比如,我们在处理上个业务的数据时需要给接下来的业务传递一些一次性的数据,而下个业务可能不是立刻出发的,这个时候保存这些数据就只能保存到本地或者保存到全局数据中,我是非常不建议这样做的,所以在路由中加入了这个功能。使用方法如下:

[[DPRouter router] routeWithUrl:@"111"][@"data"] = @"数据";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [[DPRouter router] openRouteUrl:@"111/save"];
    });
+ (NSString *)url_identify{
    return @"111";
}
- (void)setup{
    [self registerUrl:@"save" handle:^BOOL(NSString * _Nonnull url, NSMutableDictionary * _Nonnull para, DPBaseRoute * _Nonnull route) {
        NSLog(@"%@",route[@"data"]);
        [route remove];
        return YES;
    }];
}

在1秒后会打印“数据”。

业务映射

业务映射一般用来与后端配合使用,能够动态决定app的业务走向,比如在某个界面有bug时跳转入H5,或者在线上更改运营跳转的业务。

注:DPRouter支持"A/B/"模式作为router标识,“/A/B/”和"A/B"相同,路由匹配时是自动去除两边的"/",并且在“A”路由和“A/B”路由存在时优先匹配“A/B”路由

使用方法很简单:

[[DPRouter router] routeMapOriginalUrl:@"B/C" map:@"E"]; [[DPRouter router] openRouteUrl:@"B/C/bb"];
[[DPRouter router] openRouteUrl:@"E/bb"];

这三个方法都会调用,B/C模块的bb方法,更高级的,你可以一个业务添加多条映射,

[[DPRouter router] routeMapOriginalUrl:@"B/C" map:@"E"];
[[DPRouter router] routeMapOriginalUrl:@"B/C" map:@"F"];
[[DPRouter router] openRouteUrl:@"B/C/bb"];
[[DPRouter router] openRouteUrl:@"E/bb"];
[[DPRouter router] openRouteUrl:@"F/bb"];

会调用三次B/C模块的bb方法。

DPRouter还支持多层级映射,在映射时不关心映射层级设置顺序:

[[DPRouter router] routeMapOriginalUrl:@"E" map:@"F"];
[[DPRouter router] routeMapOriginalUrl:@"B/C" map:@"E"];

[[DPRouter router] routeMapOriginalUrl:@"B/C" map:@"E"];
[[DPRouter router] routeMapOriginalUrl:@"E" map:@"F"]; 

相同。

业务消息和监听

DPRouter提供两个方法,允许你可以进行业务模块的消息监听和发送。

/**
 监听,某个状态
 */
- (void)addObserver:(id)target routeWithType:(NSString *)type tuple:(void (^) (DPRouteTuple *tuple, DPBaseRoute *route))tuple;

/**
 发送消息
 */
- (void)postRouteType:(NSString *)type tuple:(DPRouteTuple *)tuple routeBack:(void (^) (id data, DPBaseRoute *route))routeBack;

与消息预存储一样,你可以在这个route没有创建时添加一个监听对象,你不需要关心销毁,因为在监听对象销毁时,route自身会移除这个监听对象。使用方法是这样的:

 [[[DPRouter router] routeWithUrl:@"111"] addObserver:self routeWithType:@"text" tuple:^(DPRouteTuple * _Nonnull tuple, DPBaseRoute * _Nonnull route) {
        NSLog(@"%@", tuple.first);
        tuple.routeBack(^(id  _Nullable __autoreleasing * _Nonnull data) {
            *data = @"aaaa";
        });
    }];
 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [route postRouteType:@"text" tuple:[DPRouteTuple tupleWithObjects:@"传递一个字符串", nil] routeBack:^(id  _Nonnull data, DPBaseRoute * _Nonnull route) {
                NSLog(@"从监听者回调的数据 %@",data);
            }];
  });

支持循环派发

开启路由

self.isAllowedLoadOtherBusiness = YES;

则可支持路由的循环派发功能,在总路由处理派发完路由模块的方法后如果还有剩余未处理的模块,则会继续进入派发流程:

 [[DPRouter router] openRouteUrl:@"111/circyle/B/C/bb"];

会在调用"111"路由的circyle方法后继续解析"B/C/bb",从而调用B/C模块的bb方法。

总结

这只是我对路由的一部分实践,当然好的路由考虑的更多,我会努力把它完善的更好.

上一篇下一篇

猜你喜欢

热点阅读