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

网友投稿 664 2022-11-02

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

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

SJStaticTableView

一个基于MVVM,用于快速搭建设置页,个人信息页的框架。 封装了cell和section的viewModel,用另外一个类来充当UITableViewDataSource的角色。

使用方法:只需继承SJStaticTableViewController并给数据源传入viewModel数组即可。

支持的cell类型:

typedef NS_ENUM(NSInteger, SSJStaticCellType) { //系统风格的各种cell类型,已封装好,可以直接用 SSJStaticCellTypeSystemLogout, //退出登录cell(已封装好) SSJStaticCellTypeSystemAccessoryNone, //右侧没有任何控件 SSJStaticCellTypeSystemAccessorySwitch, //右侧是开关 SSJStaticCellTypeSystemAccessoryDisclosureIndicator, //右侧是三角箭头(箭头左侧可以有一个image或者一个label,或者二者都有,根据传入的参数决定) //需要用户自己添加的自定义cell类型 SSJStaticCellTypeMeAvatar, //个人页“我”cell };

集成方法:

静态:手动将SJStaticTableViewComponent文件夹拖入到工程中。动态:CocoaPods:pod 'SJStaticTableView', '~> 1.2.0。

1. Demo效果图:

2. 页面与代码展示

2.1 发现页

效果图:

数据源设置代码:

+ (NSArray *)momentsPageData{ // ========== section 0 SJStaticTableviewCellViewModel *vm0 = [[SJStaticTableviewCellViewModel alloc] init]; vm0.leftImage = [UIImage imageNamed:@"ff_IconShowAlbum"]; vm0.leftTitle = @"朋友圈"; vm0.indicatorLeftImage = [UIImage imageNamed:@"avatar"]; vm0.identifier = 0; SJStaticTableviewSectionViewModel *section0 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray: @[vm0]]; // ========== section 1 SJStaticTableviewCellViewModel *vm1 = [[SJStaticTableviewCellViewModel alloc] init]; vm1.leftImage = [UIImage imageNamed:@"ff_IconQRCode"]; vm1.leftTitle = @"扫一扫"; vm1.identifier = 1; SJStaticTableviewCellViewModel *vm2 = [[SJStaticTableviewCellViewModel alloc] init]; vm2.leftImage = [UIImage imageNamed:@"ff_IconShake"]; vm2.leftTitle = @"摇一摇"; vm2.identifier = 2; SJStaticTableviewSectionViewModel *section1 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm1,vm2]]; SJStaticTableviewCellViewModel *vm3 = [[SJStaticTableviewCellViewModel alloc] init]; vm3.leftImage = [UIImage imageNamed:@"ff_IconLocationService"]; vm3.leftTitle = @"附近的人"; vm3.identifier = 3; SJStaticTableviewCellViewModel *vm4 = [[SJStaticTableviewCellViewModel alloc] init]; vm4.leftImage = [UIImage imageNamed:@"ff_IconBottle"]; vm4.leftTitle = @"漂流瓶"; vm4.identifier = 4; SJStaticTableviewSectionViewModel *section2 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm3,vm4]]; // ========== section 2 SJStaticTableviewCellViewModel *vm5 = [[SJStaticTableviewCellViewModel alloc] init]; vm5.leftImage = [UIImage imageNamed:@"CreditCard_ShoppingBag"]; vm5.leftTitle = @"购物"; vm5.identifier = 5; // ========== section 3 SJStaticTableviewCellViewModel *vm6 = [[SJStaticTableviewCellViewModel alloc] init]; vm6.leftImage = [UIImage imageNamed:@"MoreGame"]; vm6.leftTitle = @"游戏"; vm6.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm6.indicatorLeftTitle = @"一起来玩王者荣耀呀!"; vm6.identifier = 7; SJStaticTableviewSectionViewModel *section3 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm5,vm6]]; return @[section0,section1,section2,section3];}

发现页ViewController:

- (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"发现";}- (void)createDataSource{ self.dataSource = [[SJStaticTableViewDataSource alloc] initWithViewModelsArray:[Factory momentsPageData] configureBlock:^(SJStaticTableViewCell *cell, SJStaticTableviewCellViewModel *viewModel) { switch (viewModel.staticCellType) { case SSJStaticCellTypeSystemAccessoryDisclosureIndicator: { [cell configureAccessoryDisclosureIndicatorCellWithViewModel:viewModel]; } break; default: break; } }];}

2.2 设置页

效果图:

数据源设置代码:

+ (NSArray *)settingPageData{ // ========== section 0 SJStaticTableviewCellViewModel *vm0 = [[SJStaticTableviewCellViewModel alloc] init]; vm0.leftTitle = @"账号与安全"; vm0.identifier = 0; vm0.indicatorLeftTitle = @"已保护"; vm0.indicatorLeftImage = [UIImage imageNamed:@"ProfileLockOn"]; vm0.isImageFirst = NO; SJStaticTableviewSectionViewModel *section0 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm0]]; // ========== section 1 SJStaticTableviewCellViewModel *vm1 = [[SJStaticTableviewCellViewModel alloc] init]; vm1.leftTitle = @"新消息通知"; vm1.identifier = 1; //额外添加switch SJStaticTableviewCellViewModel *vm7 = [[SJStaticTableviewCellViewModel alloc] init]; vm7.leftTitle = @"夜间模式"; vm7.switchValueDidChangeBlock = ^(BOOL isON){ NSString *message = isON?@"打开夜间模式":@"关闭夜间模式"; NSLog(@"%@",message); }; vm7.staticCellType = SSJStaticCellTypeSystemAccessorySwitch; vm7.identifier = 7; SJStaticTableviewCellViewModel *vm8 = [[SJStaticTableviewCellViewModel alloc] init]; vm8.leftTitle = @"清理缓存"; vm8.indicatorLeftTitle = @"12.3M"; vm8.identifier = 8; SJStaticTableviewCellViewModel *vm2 = [[SJStaticTableviewCellViewModel alloc] init]; vm2.leftTitle = @"隐私"; vm2.identifier = 2; SJStaticTableviewCellViewModel *vm3 = [[SJStaticTableviewCellViewModel alloc] init]; vm3.leftTitle = @"通用"; vm3.identifier = 3; SJStaticTableviewSectionViewModel *section1 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm1,vm7,vm8,vm2,vm3]]; // ========== section 2 SJStaticTableviewCellViewModel *vm4 = [[SJStaticTableviewCellViewModel alloc] init]; vm4.leftTitle = @"帮助与反馈"; vm4.identifier = 4; SJStaticTableviewCellViewModel *vm5 = [[SJStaticTableviewCellViewModel alloc] init]; vm5.leftTitle = @"关于微信"; vm5.identifier = 5; SJStaticTableviewSectionViewModel *section2 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm4,vm5]]; SJStaticTableviewCellViewModel *vm9 = [[SJStaticTableviewCellViewModel alloc] init]; vm9.leftTitle = @"定制性cell展示页面 - 分组"; vm9.identifier = 9; SJStaticTableviewCellViewModel *vm10 = [[SJStaticTableviewCellViewModel alloc] init]; vm10.leftTitle = @"定制性cell展示页面 - 同组"; vm10.identifier = 10; SJStaticTableviewSectionViewModel *section4 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm9,vm10]]; // ========== section 3 SJStaticTableviewCellViewModel *vm6 = [[SJStaticTableviewCellViewModel alloc] init]; vm6.staticCellType = SSJStaticCellTypeSystemLogout; vm6.cellID = @"logout"; vm6.identifier = 6; SJStaticTableviewSectionViewModel *section3 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm6]]; return @[section0,section1,section2,section4,section3];}

设置页ViewController:

- (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"设置";}- (void)createDataSource{ self.dataSource = [[SJStaticTableViewDataSource alloc] initWithViewModelsArray:[Factory settingPageData] configureBlock:^(SJStaticTableViewCell *cell, SJStaticTableviewCellViewModel *viewModel) { switch (viewModel.staticCellType) { case SSJStaticCellTypeSystemAccessoryDisclosureIndicator: { [cell configureAccessoryDisclosureIndicatorCellWithViewModel:viewModel]; } break; case SSJStaticCellTypeSystemAccessorySwitch: { [cell configureAccessorySwitchCellWithViewModel:viewModel]; } break; case SSJStaticCellTypeSystemLogout: { [cell configureLogoutTableViewCellWithViewModel:viewModel]; } break; case SSJStaticCellTypeSystemAccessoryNone: { [cell configureAccessoryNoneCellWithViewModel:viewModel]; } break; default: break; } }];}- (void)didSelectViewModel:(SJStaticTableviewCellViewModel *)viewModel atIndexPath:(NSIndexPath *)indexPath{ switch (viewModel.identifier) { case 6: { NSLog(@"退出登录"); [self showAlertWithMessage:@"真的要退出登录嘛?"]; } break; case 8: { NSLog(@"清理缓存"); } break; case 9: { NSLog(@"跳转到定制性cell展示页面 - 分组"); SJCustomCellsViewController *vc = [[SJCustomCellsViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } break; case 10: { NSLog(@"跳转到定制性cell展示页面 - 同组"); SJCustomCellsOneSectionViewController *vc = [[SJCustomCellsOneSectionViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } break; default: break; }}

3. 定制性展示

分组页面:

+ (NSArray *)customCellsPageData{ //默认配置 SJStaticTableviewCellViewModel *vm1 = [[SJStaticTableviewCellViewModel alloc] init]; vm1.leftImage = [UIImage imageNamed:@"MoreGame"]; vm1.leftTitle = @"全部默认配置,用于对照"; vm1.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm1.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewSectionViewModel *section1 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm1]]; SJStaticTableviewCellViewModel *vm2 = [[SJStaticTableviewCellViewModel alloc] init]; vm2.leftImage = [UIImage imageNamed:@"MoreGame"]; vm2.leftTitle = @"左侧图片变小"; vm2.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm2.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewSectionViewModel *section2 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm2]]; section2.leftImageSize = CGSizeMake(20, 20); SJStaticTableviewCellViewModel *vm3 = [[SJStaticTableviewCellViewModel alloc] init]; vm3.leftImage = [UIImage imageNamed:@"MoreGame"]; vm3.leftTitle = @"字体变小变红"; vm3.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm3.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewSectionViewModel *section3 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm3]]; section3.leftLabelTextFont = [UIFont systemFontOfSize:8]; section3.leftLabelTextColor = [UIColor redColor]; SJStaticTableviewCellViewModel *vm4 = [[SJStaticTableviewCellViewModel alloc] init]; vm4.leftImage = [UIImage imageNamed:@"MoreGame"]; vm4.leftTitle = @"左侧两个控件距离变大"; vm4.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm4.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewSectionViewModel *section4 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm4]]; section4.leftImageAndLabelGap = 20; SJStaticTableviewCellViewModel *vm5 = [[SJStaticTableviewCellViewModel alloc] init]; vm5.leftImage = [UIImage imageNamed:@"MoreGame"]; vm5.leftTitle = @"右侧图片变小"; vm5.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm5.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewSectionViewModel *section5 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm5]]; section5.indicatorLeftImageSize = CGSizeMake(15, 15); SJStaticTableviewCellViewModel *vm6= [[SJStaticTableviewCellViewModel alloc] init]; vm6.leftImage = [UIImage imageNamed:@"MoreGame"]; vm6.leftTitle = @"右侧字体变大变蓝"; vm6.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm6.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewSectionViewModel *section6 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm6]]; section6.indicatorLeftLabelTextFont = [UIFont systemFontOfSize:18]; section6.indicatorLeftLabelTextColor = [UIColor blueColor]; SJStaticTableviewCellViewModel *vm7= [[SJStaticTableviewCellViewModel alloc] init]; vm7.leftImage = [UIImage imageNamed:@"MoreGame"]; vm7.leftTitle = @"右侧两个控件距离变大"; vm7.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm7.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewSectionViewModel *section7 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm7]]; section7.indicatorLeftImageAndLabelGap = 18; return @[section1,section2,section3,section4,section5,section6,section7]; }

我们可以看到,定制的代码都作用于section的viewModel。

同组页面:

+ (NSArray *)customCellsOneSectionPageData{ //默认配置 SJStaticTableviewCellViewModel *vm1 = [[SJStaticTableviewCellViewModel alloc] init]; vm1.leftImage = [UIImage imageNamed:@"MoreGame"]; vm1.leftTitle = @"全部默认配置,用于对照"; vm1.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm1.indicatorLeftTitle = @"王者荣耀!"; SJStaticTableviewCellViewModel *vm2 = [[SJStaticTableviewCellViewModel alloc] init]; vm2.leftImage = [UIImage imageNamed:@"MoreGame"]; vm2.leftTitle = @"左侧图片变小"; vm2.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm2.indicatorLeftTitle = @"王者荣耀!"; vm2.leftImageSize = CGSizeMake(20, 20); SJStaticTableviewCellViewModel *vm3 = [[SJStaticTableviewCellViewModel alloc] init]; vm3.leftImage = [UIImage imageNamed:@"MoreGame"]; vm3.leftTitle = @"字体变小变红"; vm3.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm3.indicatorLeftTitle = @"王者荣耀!"; vm3.leftLabelTextFont = [UIFont systemFontOfSize:8]; vm3.leftLabelTextColor = [UIColor redColor]; SJStaticTableviewCellViewModel *vm4 = [[SJStaticTableviewCellViewModel alloc] init]; vm4.leftImage = [UIImage imageNamed:@"MoreGame"]; vm4.leftTitle = @"左侧两个控件距离变大"; vm4.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm4.indicatorLeftTitle = @"王者荣耀!"; vm4.leftImageAndLabelGap = 20; SJStaticTableviewCellViewModel *vm5 = [[SJStaticTableviewCellViewModel alloc] init]; vm5.leftImage = [UIImage imageNamed:@"MoreGame"]; vm5.leftTitle = @"右侧图片变小"; vm5.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm5.indicatorLeftTitle = @"王者荣耀!"; vm5.indicatorLeftImageSize = CGSizeMake(15, 15); SJStaticTableviewCellViewModel *vm6= [[SJStaticTableviewCellViewModel alloc] init]; vm6.leftImage = [UIImage imageNamed:@"MoreGame"]; vm6.leftTitle = @"右侧字体变大变蓝"; vm6.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm6.indicatorLeftTitle = @"王者荣耀!"; vm6.indicatorLeftLabelTextFont = [UIFont systemFontOfSize:18]; vm6.indicatorLeftLabelTextColor = [UIColor blueColor]; SJStaticTableviewCellViewModel *vm7= [[SJStaticTableviewCellViewModel alloc] init]; vm7.leftImage = [UIImage imageNamed:@"MoreGame"]; vm7.leftTitle = @"右侧两个控件距离变大"; vm7.indicatorLeftImage = [UIImage imageNamed:@"wzry"]; vm7.indicatorLeftTitle = @"王者荣耀!"; vm7.indicatorLeftImageAndLabelGap = 18; SJStaticTableviewSectionViewModel *section1 = [[SJStaticTableviewSectionViewModel alloc] initWithCellViewModelsArray:@[vm1,vm2,vm3,vm4,vm5,vm6,vm7]]; return @[section1];}

为了方便比较,同组页面的定制和分组是一致的。我们可以看到,定制代码都作用于cell的viewModel上了。

4. 刷新数据源

支持更新数据源后,刷新数据源。比如在发现页模拟网络请求,在请求结束后更新某个cell的viewmodel:

//模拟网络请求 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //请求成功x NSDictionary *responseDict = @{@"title_info":@"新游戏上架啦", @"title_icon":@"game_1", @"game_info":@"一起来玩斗地主呀!", @"game_icon":@"doudizhu" }; //将要刷新cell的indexPath NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:3]; //获取cell对应的viewModel SJStaticTableviewCellViewModel *viewModel = [self.dataSource tableView:self.tableView cellViewModelAtIndexPath:indexPath]; if (viewModel) { //更新viewModel viewModel.leftTitle = responseDict[@"title_info"]; viewModel.leftImage = [UIImage imageNamed:responseDict[@"title_icon"]]; viewModel.indicatorLeftImage = [UIImage imageNamed:responseDict[@"game_icon"]]; viewModel.indicatorLeftTitle = responseDict[@"game_info"]; //刷新tableview [self.tableView reloadData]; } });

效果图:

5. 没有默认数据源的情况

SJStaticViewController在创建的时候分为两种情况:

//SJStaticTableViewController.htypedef enum : NSUInteger { SJDefaultDataTypeExist, //在表格生成之前就有数据(1. 完全不依赖网络请求,有现成的完整数据 2. 先生成默认数据,然后通过网络请求来更新数据并刷新表格) SJDefaultDataTypeNone, //无法生成默认数据,需要完全依赖网络请求,在拿到数据后,生成表格 }SJDefaultDataType;- (instancetype)initWithDefaultDataType:(SJDefaultDataType)defualtDataType;

//SJStaticTableViewController.m- (instancetype)initWithDefaultDataType:(SJDefaultDataType)defualtDataType{ self = [super init]; if (self) { self.defualtDataType = defualtDataType; } return self;}- (instancetype)init{ self = [self initWithDefaultDataType:SJDefaultDataTypeExist];//默认是SJDefaultDataTypeExist return self;}

详细说明一下这两种情况:

SJDefaultDataTypeExist:在表格生成之前就存在数据,可以是表格的全部数据,也可以是表格的默认数据(后来通过网络请求来更新部分数据,参考上一节)。SJDefaultDataTypeNone:意味着当前没有任何的默认数据可以使用,也就是无法生成tableview,需要在网络请求拿到数据后,再手动调用生成数据源,生成表格的方法。

- (void)viewDidLoad { [super viewDidLoad]; [self configureNav]; //在能够提供给tableivew全部,或者部分数据源的情况下,可以先构造出tableview; //否则,需要在网络请求结束后,手动调用configureTableView方法 if (self.defualtDataType == SJDefaultDataTypeExist) { [self configureTableView]; }}//只有在SJDefaultDataTypeExist的时候才会自动调用,否则需要手动调用- (void)configureTableView{ [self createDataSource];//生成数据源 [self createTableView];//生成表格}

看一个例子,我们将表情页设置为SJDefaultDataTypeNone,那么就意味着我们需要手动调用configureTableView方法:

- (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"表情"; [self networkRequest];}- (void)networkRequest{ [MBProgressHUD showHUDAddedTo: self.view animated:YES]; //模拟网络请求 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [MBProgressHUD hideHUDForView: self.view animated:YES]; self.modelsArray = [Factory emoticonPage];//网络请求后,将数据保存在self.modelsArray里面 [self configureTableView];//手动调用 });}- (void)createDataSource{ self.dataSource = [[SJStaticTableViewDataSource alloc] initWithViewModelsArray:self.modelsArray configureBlock:^(SJStaticTableViewCell *cell, SJStaticTableviewCellViewModel *viewModel) { switch (viewModel.staticCellType) { case SJStaticCellTypeSystemAccessoryDisclosureIndicator: { [cell configureAccessoryDisclosureIndicatorCellWithViewModel:viewModel]; } break; default: break; } }];}

License

SJStaticTableView is released under the MIT license.

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:JVM启动参数-Xmx的默认值是多少?
下一篇:@Scheduled注解各参数详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~