iOS动态化配置页面(页面可后端或用户自己编辑定制)
如何做到页面动态化配置解决方案
Demo:源码地址:https://mp.csdn.net/mp_download/manage/download/UpDetailed?spm=3001.5299
1.前言:页面动态化配置和所谓的模块化/组件化是不同的概念,最下方正好也提供出关于模块/组件的不错的文章
2.下面我要将的是页面的动态化配置,所谓的动态化配置是指当前页面的呈现的任何形式,布局,那些控件,数据显示,刷新机制,跳转形式,传参形式,包括父控件上的子控件样式/事件,子控件上的子控件的样式/事件,子控件的子控件的子控件…….
3.总之一句话,开发者对于UI的处理只需要绘制一个label,一个imageView,或者已经既定的不需要改变的大的组合控件,比如轮播,日历,瀑布流等
4.适用场景:
1)页面需要运营频繁调整的,比如那些东西需要展示,那些东西需要隐藏,那些模块位置需要调整等等
2)类似淘宝店铺可用户自己编辑页面,设置装修风格的
3)类似淘宝,可以控制任意模块的展示以及功能模块的搜索
针对第一点补充说明两点:运营控制页面那些东西是否展示或位置调整,很多人觉得通过后端返回tableView的data就可以做到,OK这里仅仅是控制了列表那些整体一大块的section或者row需不需要,但是无法控制单行cell上子控件都有那些,并且他们的的布局,显示以及事件。如果是scrollView更是如此了。
通过上述的介绍,我们应该如何设置我们的动态化配置方案呢?
两个思路:
思路1:页面所有的配置,全部通过后端下发,返回我要的数据
这里的弊端:如果是长列表,自动化配置的地方很多,那么后端就需要维护大量的数据,包括复杂的数据结构
1.数据结构包括到了label的间距,颜色,文字大小等等所有属性,以及其他控件的属性,这里的数据量是很大的导致在该页面请求接口耗时较久,且无法做到预渲染机制。一旦接口报错则页面就出现无数据或白屏的显示。
2.通过配置文件来控制。和运营及业务规定好默认样式,和后端约定好json格式,配置好默认文件放在项目中,首次下载读取本地json
如果运营需要控制页面的显示与隐藏,如何更新配置文件
1)app启动请求接口,接口只有一个字段,告知需要不需要更新json文件,需要则更新,不需要则跳过
2)如果app集成了推送功能,json数据可以通过推送下发,1.透传能力强,随时接收 2.推送内部自己维护socket 更加实时 3.不需要开发者主动频次调用接口来获知要不要更新
3)如果app没有推送就在页面每次请求是否需要更新的接口(即便这里页面变化很慢也无所谓,因为用户不知道ta的页面展示正在被后端控制,如果很快变化,比如一个模块突然没了,或者突然多了个模块,人家还以为见鬼了呢….)
4)页面需要集成路由来控制页面的跳转和传参,路由的选择根据上述链接的组件化,自己选择一个就好。
5)用户自定义编辑更新本地文件即可
下面给出一个json文件样式
{\"type\":\"view\",\"x\":15,\"y\":90,\"width\":350,\"height\":300,\"backgroundColor\":\"#f0f0f0\",\"subViews\":[{\"type\":\"view\",\"x\":0,\"y\":0,\"width\":150,\"height\":100,\"backgroundColor\":\"#eaeaea\",\"subViews\":[{\"type\":\"view\",\"x\":0,\"y\":0,\"width\":50,\"height\":50,\"backgroundColor\":\"#aaaaaa\",\"subViews\":[]},{\"type\":\"view\",\"x\":55,\"y\":0,\"width\":50,\"height\":50,\"backgroundColor\":\"#aaaaaa\",\"subViews\":[]},{\"type\":\"label\",\"x\":0,\"y\":50,\"width\":50,\"backgroundColor\":\"#66631e\",\"lineSpacing\":5,\"textList\":[{\"text\":\"基于Json的动态化\",\"textSize\":10,\"textColor\":\"#ff631e\"},{\"text\":\"处理方案\",\"textSize\":12,\"textColor\":\"#22631e\"}]}]},{\"type\":\"view\",\"x\":155,\"y\":0,\"width\":150,\"height\":100,\"backgroundColor\":\"#eaeaea\",\"subViews\":[{\"type\":\"view\",\"x\":0,\"y\":0,\"width\":50,\"height\":50,\"backgroundColor\":\"#aaaaaa\",\"subViews\":[]},{\"type\":\"imageView\",\"isNeedCallBack\":1,\"x\":55,\"y\":0,\"width\":50,\"height\":50,\"backgroundColor\":\"#aaaaaa\",\"url\":\"http://v1.qzone.cc/avatar/201503/08/11/30/54fbc2419012c836.jpg%21200x200.jpg\"}]}]}
这是具体控制页面的控件以及属性
其余字段还有很多需要开发者自己定义,比如当前模块的名称(中文名)虽然用不到但是还是需要的,给运营区分使用,比如模块的ID,tableView的话模块应该放在第几区,是否需要使用,scrollView或者View需要定义Frame,各个控件的间距等等。包括控件属于哪一个具体的类,比如当前控件类名,如UIImageView SGImageView ,模块的数据接口,请求方式等等
借助下面两个Json格式化工具,将会大大简化这一过程。
http://www.bejson.com/jsoneditoronline/
http://www.bejson.com/zhuanyi/
解析了Json,就会生成了对应的Model对象,每个控件都有自己的Model,而App端的JsonView就是用来根据这个key-Value值,来配置View的属性的。
1、JsonModel
iOS的基础控件都是基于UIView的,所以我们也需要针对UIView的公共属性,抽象出一层顶层JsonModel,这些包括UIView的x、y、width、Height、background等,当然还有很多属性等待着未来扩展。为了区别生成不同的UIView控件,在此model中还有个type属性,根据此字端来判断需要渲染哪种控件,以后所有子ViewModel都要继承此基类Model。
2、JsonView与JsonBaseView
JsonViewModel最重要的一个属性是如下这个字端:
@property (nonatomic, strong) NSArray <MDJsonModel *> *subViews;
这里也是生成嵌套View的关键。JsonBaseView是暴露给业务使用的baseView,解析Json的任务主要在这里进行,里面生成了嵌套JsonView以及各种Json子View。嵌套代码实现是在这里:
- (void)creatJsonSubViewsWith:(MDJsonViewModel *)model inView:(UIView *)rootView;
在这里,我们将初始化了要生成的子View,并将model传进去,进行属性的配置。
3、JsonLabel与JsonLabelModel
JsonLabel是一个可以单独拿出来的富文本组件,通过JsonLabelModel,生成NSMutableAttributedString可以完美实现动态富文本效果。
4、JsonImageView与JsonImageViewModel
JsonImageView采取加载url和本地图片的两种方式,你只需要配置不同的参数即可。但是常常我们需要获取图片这种异步数据的回调消息,所以在此我特意为此做了处理,你在拼写Json时,只是传入isNeedCallBack的值即可。设置了此属性,实现如下回调代码,即可获取异步资源的所有回调信息:
[_jsonView obtainResult:^(MDJsonNotificationResultModel *result) {
NSLog(@"%@",result);
}];
为此,特意封装了MDJsonNotificationResultModel,目前只支持图片的回调信息,后续待扩展。
5、后续扩展
如果你下载了此项目代码,而且此项目代码不能满足你的业务需求时,你需要扩展这些控件或者已有控件的属性,你可以大概遵循下面几个步骤即可完成:
(1)MDJsonMappers中注册,如下:
- (NSDictionary *)allViewMappers
{
return @{
@"view":@"MDJsonViewModel",
@"label":@"MDJsonLabelModel",
@"imageView":@"MDJsonImageViewModel"
};
}
未经注册的view组件是不能被解析的。
(2)继承MDJsonModel,定义自己控件的customModel类型;
(3)继承原生控件,创建customView,解析customModel即可;
五、相关开发工具
前面介绍过,由于直接书写Json,转义Json是一个十分繁琐的过程,一不小心就会解析失败。
在这里http://www.bejson.com/jsoneditoronline/,你可以拼写自己的Json,并结构化它,便于你直观的书写View的层级;其次,写完Json之后,还需要用http://www.bejson.com/zhuanyi/进行转义,才能生成最终的客户端传输Json字符串。