{
mgj = {
"~" = {
category = {
travel = {
"_" = "<__NSMallocBlock__: 0x600000640e70>";
};
};
};
};
}
mgj://foo/bar mgj://search/:query mgj://category/travel
蘑菇街存储回调handler的routes数据结构:其中scheme-自定义协议头(如mgj)、host-主机地址(如demo中的foo/category/search)、path-路径(如bar/:query/travel)
1、强制约定了两个占位符:"~"和"_",构成了硬编码,对不了解实现的人或则学习维护实现的人,阅读起来晦涩难懂、一脸懵逼。
2、存储回调handler的routes数据结构采用四层嵌套结构(scheme/~/host/path四层),嵌套太深,导致存储和获取handler_block的代码都难以阅读和维护。作者的设计本意是好的,把每一个host下的多个path放在一个一起,便于数据的集中管理和层次隔离;
作者的理念是没错的,但是作者忽略了router的使用场景,本身这router组件就是服务业务组件的,也就是说使用该router组件时,是业务组件依赖该router组件,而在同一个工程中,例如expressfreight://freight.com/xxx/xxx/xxx?xxx=xxx&xxx=xxx,自定义的协议头是固定的,host一般也是固定的,变化的是path部分,因此只需要把path部分打平成一个以path为key、handle_block为value的key-value的字典存储结构就可以了,简洁便于维护和开发。
注意:自定义的协议头,必须在xcode的工程配置中info-->URL Types中配置,这样,在使用方在使用openURL:来打开组件时,才能在application:openURL:options:接收到该事件。也正因为如此,同一个项目工程,自定义的协议头和host一般是固定的。
{
scheme= {
"~"= {
host_1= {
path_1= {
"_" = "<__NSMallocBlock__: 0xXXXXXXXX";
},
path_2= {
"_" = "<__NSMallocBlock__: 0xXXXXXXXX";
}
},
host_2= {
path= {
"_" = "<__NSMallocBlock__: 0xXXXXXXXX";
}
}
}
}
}
protocol/scheme/target_action方式比较和筛选:
1、纯iOS端组件间调用,使用protocol,可以传图片等非基础数据类型参数;但不能跨端使用
2、跨端,比如短信链接、端外push、h5、浏览器、其他APP等跨端跳转到APP的某一个页面,就必须使用scheme,采用openUrl方式打开
3、target_action方式,解耦比较彻底,完全利用系统的performSelector,不需要维护一个注册表,但也导致了一些特殊场景,比如需要拿到先前创建过的实例进行跳转,虽然CTMediator组件中提供了cachedTarget来缓存实例,但是这个实例是第一次调用CTMediator后才存储的,实际场景这个实例是外界创建的,这样使用CTMediator就拿不到这个外界创建的实例了。如果 CTMediator也维护一个外界注册的实例表,和protocol和scheme的方式差异也不大了