(七)BaseViewController做父类的简单运用

来源:互联网 发布:mac使用技巧 编辑:程序博客网 时间:2024/06/02 04:54

BaseViewController的简单运用

概述

为了在开发时,尽可能让团队减少重复的无用功开发,以及保证代码统一性,所以我对作为基类的ViewController以及TableView封装的要稍稍复杂些。在这一章中若一行一行的解释代码,则会特别凌乱,也不易大家理解。这里我更多的是分享下我的开发思路供大家参考,具体的内容可查看项目代码。
此类涉及内容如下

1.  title的自定义2.  数据的统计3.  内存释放的监控4.  导航栏上的返回按钮5.  常用信息mod的快速获取6.  网络请求的处理

1. title自定义

这个比较好理解,覆盖系统的title设置方法,统一设置好导航栏上的字体,在ViewController中设置标题时会自动调用
这里写图片描述

2. 数据的统计

有时运营方需要我们统计用户进入每个页面的路径,次数等,此时我们可以借助第三方比如友盟的统计,将统计用的代码写在baseViewController的viewWillAppear,viewWillDisappear中即可
这里写图片描述

3. 内存释放的监控

虽然我们现在用的都是自动内存释放,但难保写法不当,造成内存没有进行释放,所以我们可以在此类中释放的父类方法dealloc中进行标记,当类完全被释放的时候我们打印出当前类名
这里写图片描述

4. 导航栏上的返回按钮

一般导航栏上的返回按钮整个app都是一致的,所以我们可以直接在viewWillAppear中定义好导航栏图标,如果某个页面需要单独定制,则我们也只需要在那个页面重新再设置下返回按钮即可。同时我们默认给此按钮定义一个返回上一个界面的方法。
这里写图片描述

这里写图片描述

5.常用信息mod的获取

在整个app中有些数据是经常使用到的,比如个人信息中的性别,昵称,头像等。我们将经常使用的数据类作为常用属性,这样我们需要使用其中的数据时只需要调用baseViewController中的一个属性即可。

我这里就先举一个例子类:User,当我们登录时一般会获取到用户的最新信息,一般此时我们可以将用户信息保存到本地,方便随时获取。但是在app使用过程中用户也可能会修改昵称,头像等。我们可以在修改时将修改的信息同步到本地中。这样我们使用user信息时直接使用即可,不用随时去单独请求一些用户信息,还能保持数据的准确性,具体的mod使用会在后面数据管理中单独进行说明。这里只简单说明下在baseViewController中的使用
这里写图片描述

6.网络请求的处理

绝大多数前端app的一个核心功能便是展示数据。我自己罗略了一般情况下一个需要展示数据界面中可能出现的情况。

1.  数据正在加载。(hudBaseView)2.  数据加载成功。(baseView)3.  数据加载失败。(requestFailView)

这里写图片描述

写完自己一看挺像是废话的,哈哈。不过废话归废话,核心上来说总结出来就这三点。看上去挺简单的,其实细细探究下里面的细节还是挺杂乱的。对应这三种常出现的情况,我便默认在ViewController上放置三层view,分别对其处理。

  1. 数据正在加载

进入一个新界面,此时需要刷新数据出来。这种数据加载出来的过程,在产品实现上会有很多差异。

1.  最简单的,界面上什么都不展示,一片空白,数据加载完成后直接显示内容。2.  界面中加一个loading动画,数据加载完成后隐藏掉loading动画。

对于第一种,如果网络好,加载页数据量小,同时数据并不需要随时保持更新,交互较轻则比较实用。比如新闻类app,大多数都属于文字居多,加载十分迅速。一般新闻编辑发布后内容也不会改动,所以我们可以保留缓存数据,进入页面后可以直接显示缓存数据,不用进行数据请求,这样也减少了网络差请求不到数据时进入页面一片空白的尴尬。而且没有loading动画的加载展示内容的速度变得更快。

若里面出现一些交互或动态内容,如留言,点赞状态等,我们也可先用缓存展示,等数据更新了再刷新动态内容。但如果是像卖门票之类的app,这种方式就不行了,动态内容如还剩多少门票,门票被购买状态等十分重要,需要随时保持最新数据。总不能明明看到很多门票,但是点击却无法购买。

像淘宝app中我的模块中,数据便不是保持最新的,经常会出现全部订单评价后外边依然显示还有未评价数。

对于数据是否需要随时保持动态更新,切记不是我们开发员一方决定的。一定要结合自己对产品理解的基础上去和产品需求方协商。千万不要想当然觉得怎么简单怎么做。关于数据处理这一块,即使是些微的与产品方要求不同,那也可能会出现比较大的问题。

Loading动画

Loading动画一个注意的地方是,如果网络加载过快,可能出现loading刚出现然后数据便请求完成了,然后立马隐藏loading,这会出现一种闪屏的效果,我们可以默认延迟下时间再隐藏loading。

Loading动画除了在请求数据时让界面不至于过于单调,更重要的任务是在数据完成前屏蔽用户的操作。如果数据没有加载完成便允许用户操作,便会涉及到数据同步异步不同情况下的处理。

比如我们选择购买一张演唱会门票,此时选择完成进入订单生成界面,在这个界面我们需要确定收货地址,而收货地址将决定是否加收运费。为了用户体验,我们可能需要用户进入之后根据个人信息中的地址直接显示运费。因为需求关系运费需要做成动态的,我们需要随时和服务器端确认运费情况。每次修改地址后都需要网络请求,若没有loading没有来屏蔽用户的操作,则用户可能在请求状态下频繁修改进行请求。可能出现先触发的请求数据比后请求触发的数据获取的慢。异步数据处理最为麻烦,每多一个异步处理则复杂程度指数上涨。

所以一个界面中如果有多个可以请求网络的地方,如果可以则一定要尽可能用loading将操作变为同步,完成一个数据请求后再进行下一步的请求操作。

关于loading的显示,出现的几种情况可能有:
1. 只需要中心处有一个loading框
2. 有loading的同时需要有个灰色的遮盖层之类的
3. loading的时候下方是否需要展示缓存数据
4. loading的遮盖层覆盖的区域是整个屏幕,还是导航栏以下
我这里处理的是三种,

typedef enum{    LoadingNormal,//普通页面进入的数据加载loading,没有背景遮盖    LoadingHaveBackground,//页面内进行操作时触发的loading,导航栏可用    LoadingAllWindow//页面内进行操作时触发的loading,导航栏不可用} LoadingType;//关注的类型

2.请求数据失败

这个理解比较简单,具体处理方式也比较多,这里我提供两种
。数据请求失败时可用方案有如下:

1.  界面数据清空,并提示网络异常。这种方案我们可以在提示的地方加上按钮点击事件,用户点击后便进行重新请求2.  Toast提示网络异常,显示缓存数据。这种方式用户友好度好一些,即使网络失败,也不会让当前界面空白,可以给用户一种只是数据没有刷新的感觉。

说了下可能出现的情况,现在说明下实现的大致思路

  1. 因为代码加载顺序是先加载storyboard中的控制器,然后再加载ViewDidLoad,所以,在storyboard创建的控制器中,只要是继承自BaseViewController的控制器,我都会再最底层覆盖一层view作为展示用的baseView,然后代码依次生成hudBaseView和_requestFailView

  2. 在hudBaseView上添加HUD,并用一个isLoading属性开关进行控制hudbaseView的显示与隐藏

  3. requestFailView上添加一张表示网络抽风的图片,并设置其可点击,点击触发网络请求

这里写图片描述

这里写图片描述

这里写图片描述

对应这三种情况,我们可以定义三个需要实现的协议,分别用来出来网络成功,失败,以及再次请求的处理

#import <Foundation/Foundation.h>@protocol RequestDataDelegate <NSObject>/** *  网络请求失败,关闭loading动画,判断网络是没有还是异常来对于显示没网图片还是抽风图片 显示我们用来展示网络异常时准备好的requestFailView,关闭tableView的下拉刷新动画 */- (void)requestFail;/** *  网络请求成功,关闭loading动画,关闭下拉刷新动画 */- (void)requestSuccess;/** *重新请求,实际没有进行请求,只是隐藏requestFailView,为重新请求做好准备 */- (void)requestDataAgain;@optional/** *  请求网络,做好请求准备,开始loading动画,子类继承此方法进行扩展实现网络请求 */- (void)requestData;/** * 请求结果ret!=1,额外增加一张请求时间过长的处理,本质与请求失败requestFail一致 */-(void)requestTooLong;

在BaseViewController中分别对应进行实现,基本思路与上边代码注释一致,另外我添加了关于上拉加载的统计封装,因为上拉加载时我们一般请求数据需要上传服务器请求的是第几页的数据,所以我在这个控制器中添加了页数统计pageNum,当判断此次请求是下拉刷新时重置为1,是上拉加载时则计数器pageNum++;这个用法添加在此控制器上其实并不太好,需要做很多的情况条件处理,让控制器代码稍稍变麻烦了些,如果上拉加载的地方多,则可以考虑添加上此方法。

详情见项目代码