基于MVVM用于快速搭建设置页个人信息页的框架.docx

上传人:b****8 文档编号:29028570 上传时间:2023-07-20 格式:DOCX 页数:33 大小:327.20KB
下载 相关 举报
基于MVVM用于快速搭建设置页个人信息页的框架.docx_第1页
第1页 / 共33页
基于MVVM用于快速搭建设置页个人信息页的框架.docx_第2页
第2页 / 共33页
基于MVVM用于快速搭建设置页个人信息页的框架.docx_第3页
第3页 / 共33页
基于MVVM用于快速搭建设置页个人信息页的框架.docx_第4页
第4页 / 共33页
基于MVVM用于快速搭建设置页个人信息页的框架.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

基于MVVM用于快速搭建设置页个人信息页的框架.docx

《基于MVVM用于快速搭建设置页个人信息页的框架.docx》由会员分享,可在线阅读,更多相关《基于MVVM用于快速搭建设置页个人信息页的框架.docx(33页珍藏版)》请在冰豆网上搜索。

基于MVVM用于快速搭建设置页个人信息页的框架.docx

基于MVVM用于快速搭建设置页个人信息页的框架

基于MVVM,用于快速搭建设置页,个人信息页的框架

仿照了微信客户端的发现页,个人页和设置页写了一个Demo,来看一下效果图:

先不要纠结分组定制和同组定制的具体意思,在后面讲到定制性的时候我会详细说明。

现在只是让大家看一下效果。

在大概了解了功能之后,开始详细介绍这个框架。

写这篇介绍的原因倒不是希望有多少人来用,而是表达一下我自己的思路而已。

各位觉得不好的地方请多批评。

在正式讲解之前,先介绍一下本篇的基本目录:

1.用到的技术点。

2.功能说明。

3.使用方法。

4.定制性介绍。

1.用到的技术点

框架整体来说还是比较简单的,主要还是基于苹果的UITableView组件,为了解耦和责任分离,主要运用了以下技术点:

-MVVM:

采用MVVM架构,将每一行“纯粹”的数据交给一个单独的ViewModel,让其持有每个cell的数据(行高,cell类型,文本宽度,图片高度等等)。

而且每一个section也对应一个ViewModel,它持有当前section的配置数据(title,header和footer的高度等等)。

-轻UIViewController:

分离UITableViewDataSource与UIViewController,让单独一个类来实现UITableViewDataSource的职能。

-block:

使用block来调用cell的绘制方法。

-分类:

使用分类来定义每一种不同的cell的绘制方法。

知道了主要运用的技术点以后,给大家详细介绍一下该框架的功能。

2.功能介绍

这个框架可以用来快速搭建设置页,个人信息页能静态表格页面,使用者只需要给tableView的DataSource传入元素是viewModel的数组就可以了。

虽说这类页面的布局还是比较单一的,但是还是会有几种不同的情况(cell的布局类型),我对比较常见的cell布局做了封装,使用者可以直接使用。

我在定义这些cell的类型的时候,大致划分了两类:

1.第一类是系统风格的cell,大多数情况下,cell高度为44;在cell左侧会有一张图,一个label,也可以只存在一种(但是只存在图片的情况很少);在cell右侧一般都有一个向右的箭头,而且有时这个箭头的左侧还可能有label,image,也可以两个都有。

2.第二类就是自定义的cell了,它的高度不一定是44,而且布局和系统风格的cell很不一样,需要用户自己添加。

基于这两大类,再细分了几种情况,可以由下面这张图来直观看一下:

既然是cell的类型,那么就类型的枚举就需要定义在cell的viewModel里面:

typedefNS_ENUM(NSInteger,SJStaticCellType){

//系统风格的各种cell类型,已封装好,可以直接用

SJStaticCellTypeSystemLogout,//退出登录cell

SJStaticCellTypeSystemAccessoryNone,//右侧没有任何控件

SJStaticCellTypeSystemAccessorySwitch,//右侧是开关

SJStaticCellTypeSystemAccessoryDisclosureIndicator,//右侧是三角箭头(箭头左侧可以有一个image或者一个label,或者二者都有,根据传入的参数决定)

//需要用户自己添加的自定义cell类型

SJStaticCellTypeMeAvatar,//个人页“我”cell

};

在这里有三点需要说一下:

这里面除了自定义的cell以外,其他类型的cell都不需要开发者自己布局,都已经被我封装好,只需要在cell的ViewModel里面传入相应的类型和数据(文字,图片)即可。

因为左侧的两个控件(图片和文字)是至少存在一个而且左右顺序固定(图片永远在最左侧),所以该框架通过开发者传入的左侧需要显示的图片和文字,可以自己进行cell的布局。

所以类型的判断主要作用于cell的右侧。

值得一提的是,在”最右侧是一个箭头”子分支的五个类型其实都属于一个类型,只需要传入文字和图片,以及文字图片的显示顺序参数(这个参数只在同时存在图片和文字的时候有效)就可以自行判断布局。

在了解了该框架的功能之后,我们先看一下如何使用这个框架:

3.使用方法

最开始先用文字说明一下:

将SJStaticTableViewComponent文件夹复制到工程里。

将要开发的页面的ViewController继承SJStaticTableViewController。

在新ViewController里实现createDataSource方法,将viewModel数组传给控制器的dataSource属性。

根据不同的cell类型,调用不同的cell绘制方法。

如果需要接受cell的点击,需要实现didSelectViewModel方法。

可能感觉比较抽象,我拿设置页来具体说明一下:

先看一下设置页的布局:

然后我们看一下设置的ViewController的代码:

-(void)viewDidLoad{

[superviewDidLoad];

self.navigationItem.title=@"设置";

}

-(void)createDataSource

{

self.dataSource=[[SJStaticTableViewDataSourcealloc]initWithViewModelsArray:

[FactorysettingPageData]configureBlock:

^(SJStaticTableViewCell*cell,SJStaticTableviewCellViewModel*viewModel){

switch(viewModel.staticCellType)

{

caseSJStaticCellTypeSystemAccessoryDisclosureIndicator:

{

[cellconfigureAccessoryDisclosureIndicatorCellWithViewModel:

viewModel];

}

break;

caseSJStaticCellTypeSystemAccessorySwitch:

{

[cellconfigureAccessorySwitchCellWithViewModel:

viewModel];

}

break;

caseSJStaticCellTypeSystemLogout:

{

[cellconfigureLogoutTableViewCellWithViewModel:

viewModel];

}

break;

caseSJStaticCellTypeSystemAccessoryNone:

{

[cellconfigureAccessoryNoneCellWithViewModel:

viewModel];

}

break;

default:

break;

}

}];

}

-(void)didSelectViewModel:

(SJStaticTableviewCellViewModel*)viewModelatIndexPath:

(NSIndexPath*)indexPath

{

switch(viewModel.identifier)

{

case6:

{

NSLog(@"退出登录");

[selfshowAlertWithMessage:

@"真的要退出登录嘛?

"];

}

break;

case8:

{

NSLog(@"清理缓存");

}

break;

case9:

{

NSLog(@"跳转到定制性cell展示页面-分组");

SJCustomCellsViewController*vc=[[SJCustomCellsViewControlleralloc]init];

[self.navigationControllerpushViewController:

vcanimated:

YES];

}

break;

case10:

{

NSLog(@"跳转到定制性cell展示页面-同组");

SJCustomCellsOneSectionViewController*vc=[[SJCustomCellsOneSectionViewControlleralloc]init];

[self.navigationControllerpushViewController:

vcanimated:

YES];

}

break;

default:

break;

}

}

看到这里,你可能会有这些疑问:

1.UITableViewDataSource方法哪儿去了?

2.viewModel数组是如何设置的?

3.cell的绘制方法是如何区分的?

4.UITableViewDelegate的方法哪里去了?

下面我会一一解答,看完了下面的解答,就能几乎完全掌握这个框架的思路了:

问题1:

UITableViewDataSource方法哪儿去了?

我自己封装了一个类SJStaticTableViewDataSource专门作为数据源,需要控制器给它一个viewModel数组。

来看一下它的实现文件:

//SJStaticTableViewDataSource.m

-(NSInteger)numberOfSectionsInTableView:

(UITableView*)tableView

{

returnself.viewModelsArray.count;

}

-(NSInteger)tableView:

(UITableView*)tableViewnumberOfRowsInSection:

(NSInteger)section

{

SJStaticTableviewSectionViewModel*vm=self.viewModelsArray[section];

returnvm.cellViewModelsArray.count;

}

-(UITableViewCell*)tableView:

(UITableView*)tableViewcellForRowAtIndexPath:

(NSIndexPath*)indexPath

{

//获取section的ViewModel

SJStaticTableviewSectionViewModel*sectionViewModel=self.viewModelsArray[indexPath.section];

//获取cell的viewModel

SJStaticTableviewCellViewModel*cellViewModel=sectionViewModel.cellViewModelsArray[indexPath.row];

SJStaticTableViewCell*cell=[tableViewdequeueReusableCellWithIdentifier:

cellViewModel.cellID];

if(!

cell){

cell=[[SJStaticTableViewCellalloc]initWithStyle:

UITableViewCellStyleDefaultreuseIdentifier:

cellViewModel.cellID];

}

self.cellConfigureBlock(cell,cellViewModel);

returncell;

}

-(NSString*)tableView:

(UITableView*)tableViewtitleForHeaderInSection:

(NSInteger)section{

SJStaticTableviewSectionViewModel*vm=self.viewModelsArray[section];

returnvm.sectionHeaderTitle;

}

-(NSString*)tableView:

(UITableView*)tableViewtitleForFooterInSection:

(NSInteger)section

{

SJStaticTableviewSectionViewModel*vm=self.viewModelsArray[section];

returnvm.sectionFooterTitle;

}

表格的cell和section都设置了与其对应的viewModel,用于封装其对应的数据:

cell的viewModel(大致看一下即可,后面有详细说明):

typedefNS_ENUM(NSInteger,SJStaticCellType){

//系统风格的各种cell类型,已封装好,可以直接用

SJStaticCellTypeSystemLogout,//退出登录cell(已封装好)

SJStaticCellTypeSystemAccessoryNone,//右侧没有任何控件

SJStaticCellTypeSystemAccessorySwitch,//右侧是开关

SJStaticCellTypeSystemAccessoryDisclosureIndicator,//右侧是三角箭头(箭头左侧可以有一个image或者一个label,或者二者都有,根据传入的参数决定)

//需要用户自己添加的自定义cell类型

SJStaticCellTypeMeAvatar,//个人页“我”cell

};

typedefvoid(^SwitchValueChagedBlock)(BOOLisOn);//switch开关切换时调用的block

@interfaceSJStaticTableviewCellViewModel:

NSObject

@property(nonatomic,assign)SJStaticCellTypestaticCellType;//类型

@property(nonatomic,copy)NSString*cellID;//cellreuseridentifier

@property(nonatomic,assign)NSIntegeridentifier;//区别每个cell,用于点击

//===============系统默认cell左侧===============//

@property(nonatomic,strong)UIImage*leftImage;//左侧的image,按需传入

@property(nonatomic,assign)CGSizeleftImageSize;//左侧image的大小,存在默认设置

@property(nonatomic,copy)NSString*leftTitle;//cell主标题,按需传入

@property(nonatomic,strong)UIColor*leftLabelTextColor;//当前组cell左侧label里文字的颜色

@property(nonatomic,strong)UIFont*leftLabelTextFont;//当前组cell左侧label里文字的字体

@property(nonatomic,assign)CGFloatleftImageAndLabelGap;//左侧image和label的距离,存在默认值

//===============系统默认cell右侧===============//

@property(nonatomic,copy)NSString*indicatorLeftTitle;//右侧箭头左侧的文本,按需传入

@property(nonatomic,strong)UIColor*indicatorLeftLabelTextColor;//右侧文字的颜色,存在默认设置,也可以自定义

@property(nonatomic,strong)UIFont*indicatorLeftLabelTextFont;//右侧文字的字体,存在默认设置,也可以自定义

@property(nonatomic,strong)UIImage*indicatorLeftImage;//右侧箭头左侧的image,按需传入

@property(nonatomic,assign)CGSizeindicatorLeftImageSize;//右侧尖头左侧image大小,存在默认设置,也可以自定义

@property(nonatomic,assign,readonly)BOOLhasIndicatorImageAndLabel;//右侧尖头左侧的文本和image是否同时存在,只能通过内部计算

@property(nonatomic,assign)CGFloatindicatorLeftImageAndLabelGap;//右侧尖头左侧image和label的距离,存在默认值

@property(nonatomic,assign)BOOLisImageFirst;//右侧尖头左侧的文本和image同时存在时,是否是image挨着箭头,默认为YES

@property(nonatomic,copy)SwitchValueChagedBlockswitchValueDidChangeBlock;//切换switch开关的时候调用的block

//===============长宽数据===============//

@property(nonatomic,assign)CGFloatcellHeight;//cell高度,默认是44,可以设置

@property(nonatomic,assign)CGSizeleftTitleLabelSize;//左侧默认Label的size,传入text以后内部计算

@property(nonatomic,assign)CGSizeindicatorLeftLabelSize;//右侧label的size

//===============自定义cell的数据放在这里===============//

@property(nonatomic,strong)UIImage*avatarImage;

@property(nonatomic,strong)UIImage*codeImage;

@property(nonatomic,copy)NSString*userName;

@property(nonatomic,copy)NSString*userID;

section的viewModel(大致看一下即可,后面有详细说明):

@interfaceSJStaticTableviewSectionViewModel:

NSObject

@property(nonatomic,copy)NSString*sectionHeaderTitle;//该section的标题

@property(nonatomic,copy)NSString*sectionFooterTitle;//该section的标题

@property(nonatomic,strong)NSArray*cellViewModelsArray;//该section的数据源

@property(nonatomic,assign)CGFloatsectionHeaderHeight;//header的高度

@property(nonatomic,assign)CGFloatsectionFooterHeight;//footer的高度

@property(nonatomic,assign)CGSizeleftImageSize;//当前组cell左侧image的大小

@property(nonatomic,strong)UIColor*leftLabelTextColor;//当前组cell左侧label里文字的颜色

@property(nonatomic,strong)UIFont*leftLabelTextFont;//当前组cell左侧label里文字的字体

@property(nonatomic,assign)CGFloatleftImageAndLabelGap;//当前组左侧image和label的距离,存在默认值

@property(nonatomic,strong)UIColor*indicatorLeftLabelTextColor;//当前组cell右侧label里文字的颜色

@property(nonatomic,strong)UIFont*indicatorLeftLabelTextFont;//当前组cell右侧label里文字的字体

@property(nonatomic,assign)CGSizeindicatorLeftImageSize;//当前组cell右侧image的大小

@property(nonatomic,assign)CGFloatindicatorLeftImageAndLabelGap;//当前组cell右侧image和label的距离,存在默认值

-(instancetype)initWithCellViewModelsArray:

(NSArray*)cellViewModelsArray;

你可能会觉得属性太多了,但这些属性的存在意义是为cell的定制性服务的,在后文会有解释。

现在了解了我封装好的数据源,cell的viewModel,section的viewModel以后,我们看一下第二个问题:

问题2:

viewModel数组是如何设置的?

我们来看一下设置页的viewModel数组的设置:

+(NSArray*)settingPageData

{

//==========section0

SJStaticTableviewCellViewModel*vm0=[[SJStaticTableviewCellViewModelalloc]init];

vm0.leftTitle=@"账号与安全";

vm0.identifier=0;

vm0.indicatorLeftTitle=@"已保护";

vm0.indicatorLeftImage=[UIImageimageNamed:

@"ProfileLockOn"];

vm0.isImageFirst=

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1