最新iOS面试题:iOS开发-组件化(②系列更新)
MGJRouter 蘑菇街组件实现原理
方案一 url-block
这是蘑菇街中应用的一种页面间调用的方式,通过在启动时注册组件提供的服务,把调用组件使用的url和组件提供的服务block对应起来,保存到内存中。在使用组件的服务时,通过url找到对应的block,然后获取服务。
注册
[MGJRouter registerURLPattern:@"mgj://detail?id=:id" toHandler:^(NSDictionary *routerParameters) {
NSNumber *id = routerParameters[@"id"];
// create view controller with id
// push view controller
}];
调用:
- url的参数传递受到限制,只能传递常规的字符串参数,无法传递非常规参数,如UIImage、NSData等类型
- 没有区分本地调用和远程调用的情况,尤其是远程调用,会因为url参数受限,导致一些功能受限
- 组件本身依赖了中间件,且分散注册使的耦合较多
方案二、protocol-class
针对方案一的问题,蘑菇街又提出了另一种组件化的方案,就是通过protocol定义服务接口,组件通过实现该接口来提供接口定义的服务,具体实现就是把protocol和class做一个映射,同时在内存中保存一张映射表,使用的时候,就通过protocol找到对应的class来获取需要的服务。
注册:
[ModuleManager registerClass:ClassA forProtocol:ProtocolA]
调用
[ModuleManager classForProtocol:ProtocolA]
蘑菇街的这种方案确实解决了方案一中无法传递非常规参数的问题,使得组件间的调用更为方便,但是它依然没有解决组件依赖中间件的问题、内存中维护映射表的问题、组件的分散调用的问题。设计思想和方案一类似,都是通过给组件加了一层wrapper,然后给使用者调用。
方案三、target-action
casa的方案是通过给组件包装一层wrapper来给外界提供服务,然后调用者通过依赖中间件来使用服务;其中,中间件是通过runtime来调用组件的服务,是真正意义上的解耦,也是该方案最核心的地方。具体实施过程是给组件封装一层target对象来对外提供服务,不会对原来组件造成入侵;然后,通过实现中间件的category来提供服务给调用者,这样使用者只需要依赖中间件,而组件则不需要依赖中间件。
也就是每个组件创建一个target类(由组件开发者维护),其内部定义了组件对外暴露的action(方法)。和组件通信时,其实质是调用一个特定的target-action的方法。target类的类名必须以Target_开头,比如Target_A,action的方法名必须以Action_开头,比如Action_nativeFetchDetailViewController。注意,暴露出来的这个target类并不是这个组件的具体实现,它只是为了方便调用者使用,target类的实现文件中会引入组件的头文件,实现声明文件中的功能,从而达到调用组件的目的。
使用者只需要依赖中间件,而中间件又不依赖组件,这是真正意义上的解耦。但是casa的这个方案有个问题就是hardcode,在中间件的category里有hardcode,casa的解释是在组件间调用时,最好是去model化,所以不可避免的引入了hardcode,并且所有的hardcode只存在于分类中。针对这个问题,有人提议,把所有的model做成组件化下沉,然后让所有的组件都可以自由的访问model,不过在我看来,这种方案虽然解决了组件间传递model的依赖问题,但是为了解决这个小问题,直接把整个model层组件化后暴露给所有组件,容易造成数据泄露,付出的代价有点大。针对这个问题,经过和网友讨论,一致觉得组件间调用时用字典传递数据,组件内调用时用model传递数据,这样即减少组件间数据对model的耦合,又方便了组件内使用model传递数据的便捷性。
精选全网 · iOS面试题答案PDF文集
image
- 最新 初级iOS 面试题
- 最新 中级iOS 面试题
- 最新 高级iOS 面试题
- 《BAT面试资料全集》
- 《BAT大厂常问iOS面试题》
- 《2021年面试真题》
- 《iOS中级到高级面试题完整版》
- 字节跳动,京东,小米,腾讯、头条、阿里、美团等公司21年的面试真题
资料下载地址: