公司之前的项目是外包做的,包括Android也是,所以重构或者重写也就势在必行。在这两者之前权衡再三选择了后者,而且这次还用了一个很高大上的东西MVVM+RAC(自己一个人就是好啊),于是看了几天教程和demo就开始干活了。
现在项目做了也有一个月了,做了大概三个多模块,最大的好处应该就是解耦了,比如说我现在这个APP里有大量的表单,如果用MVC的话肯定就是一万个vc了,但是上了MVVM以后我可以让所有的表单公用一个vc,只需要换viewmodel即可。
ok,在这篇里我想先讲讲如何处理大量表单,可能有些人说不就是tableview么,但是如果让你写会怎么写?一万个swicth case么?nonono,千万不要这么写(被之前外包坑惨了),这样写的下场就是一旦有修改是极其痛苦的。那正常的姿势应该是怎样的呢?
![](https://img.haomeiwen.com/i711440/c45cd3de624ba0f2.jpg)
这是众多表单中的一个相对简单的。这些看似平淡的表单实际上却暗含杀机,为什么这么说呢,一会大家往下看到那一堆pageType的枚举或许就知道了。面对这样大量的表单作为一个机智的程序猿肯定是要想些办法的,不然硬写的话就算加班能写完,最后需求一改照样要吐血-。-
首先,先分析下返回的数据格式。
{
"profile": {
"gdie": [
""
],
"gdad": "",
"anm": "Aaaabb",
"gdic": "",
"aid": "f29f378c26b448ca8d0656962a8b4a64",
"snm": "Asa",
"bth": [
"184032000"
],
"gdit": [
""
],
"sex": [
"男"
],
"gdnm": "",
"loc": [
"山东省",
"济南市"
]
},
"response": "success",
"regi": 1
}
很明显这是一个obj,那我们就先把这个obj转成model对象吧。
@interface YYQBaseInfoSetting : YYQModel
/**
* 真实姓名
*/
@property(nonatomic,copy)NSString *anm;
/**
* 艺名
*/
@property(nonatomic,copy)NSString *snm;
/**
* 性别
*/
@property(nonatomic,strong)NSArray *sex;
/**
* 出生日期
*/
@property(nonatomic,strong)NSArray *bth;
/**
* 所在地区
*/
@property(nonatomic,strong)NSArray *loc;
/**
* 监护人姓名
*/
@property(nonatomic,copy)NSString *gdnm;
/**
* 监护人证件类型
*/
@property(nonatomic,strong)NSArray *gdit;
/**
* 监护人证件号码
*/
@property(nonatomic,copy)NSString *gdic;
/**
* 监护人证件地址
*/
@property(nonatomic,copy)NSString *gdad;
/**
* 监护人证件到期
*/
@property(nonatomic,strong)NSArray *gdie;
然后呢,嗯,这里我们要分两块去做,作为展示我们需要把model类转为tableview可用的线性的结构,而作为上传和缓存我们又需要保持当前数据结构原封不动。那要怎么转才是正确的姿势呢。我们还是看图说话
![](https://img.haomeiwen.com/i711440/3585b43763eb62b9.png)
这是一个线性结构的plist,这就是我们需要在tableview上展示的数据源,每一条都是完整的,接下来只要把model里的value对应赋给每个item,我们就破案了,让我们怀着激动的心情看一下FormItem(或者我们称其为cell的viewmodel,用其来控制cell以及二级页的显示)
typedef NS_ENUM(NSUInteger,YYQFormCellType) {
YYQFormCellTypeNormal,
YYQFormCellTypeCountTag,
YYQFormCellTypeMultiTag,
};
typedef NS_ENUM(NSUInteger,YYQPageType) {
//输入
YYQPageTypeInput,
//日期选择
YYQPageTypePickerDate,
//单列选择
YYQPageTypePickerSingle,
//多列选择
YYQPageTypePickerMulti,
//多选
YYQPageTypeMultiSelect,
//单选
YYQPageTypeRadioSelect,
//可编辑列表
YYQPageTypeEditableList,
//技能列表
YYQPageTypeSkillsList,
};
@interface FormItem : NSObject
/**
* 属性名
*/
@property(nonatomic,copy)NSString *propertyName;
/**
* cell显示名
*/
@property(nonatomic,copy)NSString *title;
/**
* 二级页title
*/
@property(nonatomic,copy)NSString *pageTitle;
/**
* value
*/
@property(nonatomic,strong)id obj;
/**
* cellType
*/
@property(nonatomic,assign)YYQFormCellType cellType;
/**
* 二级页Type
*/
@property(nonatomic,assign)YYQPageType pageType;
/**
* 二级页数据
*/
@property(nonatomic,strong)id pageContent;
/**
* 是否必须
*/
@property(nonatomic,assign)BOOL isNeed;
有没有发现这个FormItem和plist文件里的字段都是对应的呢。接下来我们只需要把model的value根据propertyName赋值给FormItem的obj就好了。这里有一个小技巧,不知道大家有没有注意到pagecontent里的regular,这是一个正则表达式用来验证我们输入数据的合法性,这样一来所有input类型的二级页就都可以复用了是不是很爽呢
最后,每次从二级页保存数据或picker选择完成后,我会把更新后的Formitem回调拿去更新model,更新完model后都需要重新生成datasource,同时reloadData。可能会观众老爷会问为啥要脱裤子放屁呢,直接一块更新model和datasource不就好了,其实是每次遍历还有一些特殊的需求所以就简单粗暴了,,毕竟A9的性能都逼近桌面级了是吧。
![](https://img.haomeiwen.com/i711440/438c75bf3246d5ce.png)
再贴一下如何把model的value转为FormItem数组,这里用了一个李明杰老师的框架MJExtension神器,推荐。
![](https://img.haomeiwen.com/i711440/e3be2e8b415f0d9e.png)
![](https://img.haomeiwen.com/i711440/ad46f71280ae28e3.png)
恬不知耻的放一波github https://github.com/timelessg
网友评论