团队目标
- 单元测试编写
- 路由表方案讨论
单元测试方案与代码编写
首先研究了苹果自带的XCTest,但是不是很符合。后来在网上找了些资料,由于项目是纯swift,因此选择了Quick+Nimble组合框架,其中,这两个框架,在Alamofire、Moya等swift流行框架均采用了它做为单元测试框架。
基于Quick框架,开始写测试用例,选择信e家作为测试项目,但后写登录ViewModel的测试代码,过程中也会遇到些许问题,但是都一一解决了。最后把方案与同事分享,然后一起完成了信e家的单元测试开发。因为只测试了viewModel模块,没有做UI测试,因此覆盖率不是很高:大概50%.
单元测试总结文章
路由表方案
目前,市面上主流的Router方案有三种,分别为:
- URL Router 参考框架:mogujie/MGJRouter
- Target-Action 参考框架:casatwy/CTMediator
- Protocol
其中,URL Router代表作为蘑菇街App。它是通过注册URl,然后解析URL中的host path等参数,然后拆解实现跳转。但是,注册了URL之后,会造成不必要的内存常驻,所以,不太建议此方案。
Target-Actionc方案,不需要注册,通过解析字段串,解析出目标与函数的串联,然后彩runtime机制完成调用。经对比,我们采用此方案来实现路由跳转功能。
Target-Action方案
采用CTMediator框架,主要化分为六部分,Controller、View、Model、ViewModel、Category、Target。其中Category与Target分别为路由机制相关的文件。实现如下:
category文件代码:
import CTMediator
// 1. 字符串 是类名 Target_xxx.h 中的 xxx 部分
let kCTMediatorTarget_Face = "Face"
// 2. 字符串是 Target_xxx.h 中 定义的 Action_xxxx 函数名的 xxx 部分
let kCTMediatorActionNavigaTo_pushFaceVc = "pushFaceVc"
extension CTMediator {
func ylx_mediator_pushFaceVcWithParams(params: [String:Any]?) -> UIViewController {
if let registerVc = performTarget(kCTMediatorTarget_Face, action: kCTMediatorActionNavigaTo_pushFaceVc, params: nil, shouldCacheTarget: false) as? UIViewController {
return registerVc as! XYJBaseVC
} else {
// 这里处理异常场景,具体如何处理取决于产品
return XYJBaseVC.init()
}
}
}
Target文件
.h文件
#import <Foundation/Foundation.h>
@interface Target_Face : NSObject
- (XYJFaceVC *)Action_pushFaceVc:(NSDictionary *)params;
@end
.m文件
#import "Target_Face.h"
@implementation Target_Face
- (XYJFaceVC *)Action_pushFaceVc:(NSDictionary *)params
{
return [[XYJFaceVC alloc] init];
}
@end
然后,在壳工程中调用时,只要通过CTMdiator的分类方法中,拿到控制器,实现调用就行。至于拿到的是什么控制器,可以通过服务器下发,在category中,取到不能的target与action即可实现不同控制器的跳转。参数传递,采用的是NSDictionary方式。如果要传递的是模型,可通过ObjectMapper转字典再传递。
调度方式:
let vc = CTMediator.sharedInstance().ylx_mediator_pushFaceVcWithParams(params: nil)
self.navigationController?.pushViewController(vc, animated: true)
为什么Target要采用oc方法实现?
因为项目是swift项目,如果target用swift方式编写,那么,框架中通过字符串生成Selector会报错。因为swift的方法与oc是有区别。传参后方法名会不一样。
数据顺传逆传
顺传,可直接通过param参数直接传递过去。
逆传:
- 通过CTMediator分类拿到控制器后,直接对控制闭包或block赋值实现数据逆传。
- 通过Target中,return控制器前,对闭包或block赋值实现数据逆传。
路由更新方案
-
路由表下发情况
- key:value数组的形式,key为类名,value为上述的Target/Action拼接字符串
-
路由表下发更新缓存方案
- app每次进入前台,都会获取一下路由配置信息。 如果本地没有版本信息,则把路由配置信息保存到本地,并赋值给单例对象(存放运行内存中,提高效率)。如果有,比较版本号,如果请求的版本号大于本地的,则替换缓存并赋值给单例。如果等于,则直取本地的。
-
路由表读取跳转方案
- 因为路由表是key value形式,如果读取key,取出来的值为空,则按默认正常业务逻辑跳转。如果有值,但是取出来的值,按路由方案读取得到的类不存在,还是按默认业务逻辑跳转,否则按路由表取出来的值跳转。