iOS 网易彩票-4设置模块一
2015-09-06 16:29 jiangys 阅读(1219) 评论(0) 编辑 收藏 举报概述
基本上,每一款APP都有相应的设置模块。怎么设置才能更灵活和通用呢,这也是大家一直思考的。下面说说在网易彩票中,设置模块的设置思想。
基本上有三种方案:
- static cell(呆板,完全没有动态)
- 使用代码,条件判断逐个编写(麻烦,代码冗长)
- 使用plist加载(能够动态配置跳转控制器,不能配置请求代码;由于使用字符串配置跳转控制器名,容易出现运行时错误)
- 使用模型封装每个cell的数据(item),使用Class作为跳转控制器属性(这样就能经过编译检测)
最终我们使用的是第4种方式来实现,效果:
实现
思路:
1.创建cell的数据模型group(头部标题、尾部标题及items)
2.创建cell的数据模型item(图标、标题、block、跳转到控制器)
3.自定义cell,根据不同的item模型创建不同的cell外观(箭头、开头、文本等)
4.自定一个基类控制器,实现
- 加载解析group和item数据
- 根据group数据创建table的样式(组底部、组尾部)
- 加载自定义的cell
- 如果item类是跳转类型的,需要配置跳转目标控制器
- 如果item类是代码执行型的,需要配置要执行的block代码
5.设置界面实现基类控制器,只需要简单配置要显示的item
创建cell的数据模型group
MJSettingGroup.h
#import <Foundation/Foundation.h> @interface MJSettingGroup : NSObject /** 头部标题*/ @property (nonatomic, copy) NSString *header; /** 尾部标题*/ @property (nonatomic, copy) NSString *footer; /** 存放这组行的所有的模型*/ @property (nonatomic, copy) NSArray *items; @end
创建cell的数据模型item
单元Cell中有好几种类型:
- 开头
- 箭头
- 文本
因此,为了在界面上更容易区别,我们分别为这几个类型定义一个模型。当前,这几种类型的中,左边显示图标和不显示图标都是一样的,因此,定义一个单元Cell模型基类,其它都继续于这个基类。
(基类)MJSettingItem.h
#import <Foundation/Foundation.h> typedef void (^MJSettingItemOption)(); @interface MJSettingItem : NSObject /** 图标 */ @property (nonatomic, copy) NSString *icon; /** 标题 */ @property (nonatomic, copy) NSString *title; /** 点击cell要做的事情 */ @property (nonatomic, copy) MJSettingItemOption option; +(instancetype)itemWithIcon:(NSString *)icon title:(NSString *)title; +(instancetype)itemWithTitle:(NSString *)title; @end
(基类)MJSettingItem.m
#import "MJSettingItem.h" @implementation MJSettingItem +(instancetype)itemWithTitle:(NSString *)title { return [self itemWithIcon:nil title:title]; } +(instancetype)itemWithIcon:(NSString *)icon title:(NSString *)title { MJSettingItem *item = [[self alloc] init]; item.icon = icon; item.title = title; return item; } @end
MJSettingLabelItem(文本)、MJSettingSwitchItem(开关)、MJSettingArrowItem(箭头)都分别继承MJMJSettingItem
MJSettingArrowItem.h
#import "MJSettingItem.h" @interface MJSettingArrowItem : MJSettingItem /** * 点击这行cell需要跳转的控制器 */ @property (nonatomic, assign) Class destVcClass; + (instancetype)itemWithIcon:(NSString *)icon title:(NSString *)title destVcClass:(Class)destVcClass; + (instancetype)itemWithTitle:(NSString *)title destVcClass:(Class)destVcClass; @end
MJSettingArrowItem.m
#import "MJSettingArrowItem.h" @implementation MJSettingArrowItem + (instancetype)itemWithIcon:(NSString *)icon title:(NSString *)title destVcClass:(Class)destVcClass { MJSettingArrowItem *item = [self itemWithIcon:icon title:title]; item.destVcClass = destVcClass; return item; } + (instancetype)itemWithTitle:(NSString *)title destVcClass:(Class)destVcClass { return [self itemWithIcon:nil title:title destVcClass:destVcClass]; } @end
自定义cell
需要根据模型来给每个cell设置数据和类型,因而,通过自定义cell来实现。分别指定显示的数据和右边显示的内容类型。
MJSettingCell.h
#import <UIKit/UIKit.h> @class MJSettingItem; @interface MJSettingCell : UITableViewCell /** * 每个cell需要显示的数据 */ @property (nonatomic, strong) MJSettingItem *item; + (instancetype)cellWithTableView:(UITableView *)tableView; @end
MJSettingCell.m
// // MJSettingCell.m // Lottery // // Created by apple on 15/9/6. // Copyright (c) 2015年 weconex. All rights reserved. // #import "MJSettingCell.h" #import "MJSettingItem.h" #import "MJSettingSwitchItem.h" #import "MJSettingArrowItem.h" #import "MJSettingLabelItem.h" @interface MJSettingCell() /** 箭头*/ @property (nonatomic, strong) UIImageView *arrowView; /** 开关*/ @property (nonatomic, strong) UISwitch *switchView; /** 标签*/ @property (nonatomic, strong) UILabel *labelView; @end @implementation MJSettingCell //懒加载,所有的箭头都只加载一次 - (UIImageView *)arrowView { if (_arrowView == nil) { _arrowView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellArrow"]]; } return _arrowView; } //懒加载,所有的开关都只加载一次 - (UISwitch *)switchView { if (_switchView == nil) { _switchView = [[UISwitch alloc] init]; } return _switchView; } //懒加载,所有的文本都只加载一次 - (UILabel *)labelView { if (_labelView == nil) { _labelView = [[UILabel alloc] init]; _labelView.bounds = CGRectMake(0, 0, 100, 30); _labelView.backgroundColor = [UIColor redColor]; } return _labelView; } + (instancetype)cellWithTableView:(UITableView *)tableView { static NSString *ID = @"setting"; MJSettingCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[MJSettingCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } return cell; } /** * 重写定义的属性item的Set方法,只有赋值就设定数据 */ - (void)setItem:(MJSettingItem *)item { _item = item; // 1.设置数据 [self setupData]; // 2.设置右边的内容 [self setupRightContent]; } /** * 设置右边的内容 */ - (void)setupRightContent { if ([self.item isKindOfClass:[MJSettingArrowItem class]]) { // 箭头 self.accessoryView = self.arrowView; } else if ([self.item isKindOfClass:[MJSettingSwitchItem class]]) { // 开关 self.accessoryView = self.switchView; self.selectionStyle = UITableViewCellSelectionStyleNone; } else if ([self.item isKindOfClass:[MJSettingLabelItem class]]) { // 标签 self.accessoryView = self.labelView; } else { self.accessoryView = nil; } } /** * 设置数据 */ - (void)setupData { if (self.item.icon) { self.imageView.image = [UIImage imageNamed:self.item.icon]; } self.textLabel.text = self.item.title; } @end
自定一个基类控制器,实现
- 加载解析group和item数据
- 根据group数据创建table的样式(组底部、组尾部)
- 根据不同的item模型创建不同的cell外观(箭头、开头、文本等)
- 如果item类是跳转类型的,需要配置跳转目标控制器
- 如果item类是代码执行型的,需要配置要执行的block代码
MJBaseSettingViewController.h
#import <UIKit/UIKit.h> @interface MJBaseSettingViewController : UITableViewController @property (nonatomic, strong) NSMutableArray *data; @end
MJBaseSettingViewController.m
// // MJBaseSettingViewController.m // Lottery // // Created by apple on 15/9/6. // Copyright (c) 2015年 weconex. All rights reserved. // #import "MJBaseSettingViewController.h" #import "MJSettingArrowItem.h" #import "MJSettingSwitchItem.h" #import "MJSettingGroup.h" #import "MJSettingCell.h" @interface MJBaseSettingViewController () @end @implementation MJBaseSettingViewController - (id)init { return [super initWithStyle:UITableViewStyleGrouped]; } - (id)initWithStyle:(UITableViewStyle)style { return [super initWithStyle:UITableViewStyleGrouped]; } - (NSArray *)data { if (_data == nil) { _data = [NSMutableArray array]; } return _data; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.data.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { MJSettingGroup *group = self.data[section]; return group.items.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1.创建cell MJSettingCell *cell = [MJSettingCell cellWithTableView:tableView]; // 2.给cell传递模型数据 MJSettingGroup *group = self.data[indexPath.section]; cell.item = group.items[indexPath.row]; // 3.返回cell return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // 1.取消选中这行 [tableView deselectRowAtIndexPath:indexPath animated:YES]; // 2.模型数据 MJSettingGroup *group = self.data[indexPath.section]; MJSettingItem *item = group.items[indexPath.row]; if (item.option) { // block有值(点击这个cell,.有特定的操作需要执行) item.option(); } else if ([item isKindOfClass:[MJSettingArrowItem class]]) { // 箭头 MJSettingArrowItem *arrowItem = (MJSettingArrowItem *)item; // 如果没有需要跳转的控制器 if (arrowItem.destVcClass == nil) return; UIViewController *vc = [[arrowItem.destVcClass alloc] init]; vc.title = arrowItem.title; [self.navigationController pushViewController:vc animated:YES]; } } /** * 头部标题 */ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { MJSettingGroup *group = self.data[section]; return group.header; } /** * 底部标题 */ - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { MJSettingGroup *group = self.data[section]; return group.footer; } @end
设置界面实现
实现基类控制器,只需要简单配置要显示的cell的文字,图片,push的控制器或者要执行的block代码。
MJSettingViewController.m
// // MJSettingViewController.m // Lottery // // Created by apple on 15/9/6. // Copyright (c) 2015年 weconex. All rights reserved. // #import "MJSettingViewController.h" #import "MJSettingArrowItem.h" #import "MJSettingSwitchItem.h" #import "MJSettingGroup.h" #import "MJTest1ViewController.h" @interface MJSettingViewController () @end @implementation MJSettingViewController /** * 第1组数据 */ - (void)setupGroup1 { MJSettingItem *update = [MJSettingArrowItem itemWithIcon:@"MoreUpdate" title:@"检查新版本"]; update.option = ^{ // 弹框提示 NSLog(@"正在检查更新"); }; MJSettingItem *help = [MJSettingArrowItem itemWithIcon:@"MoreHelp" title:@"帮助" destVcClass:[MJTest1ViewController class]]; MJSettingItem *share = [MJSettingArrowItem itemWithIcon:@"MoreShare" title:@"分享" destVcClass:[MJTest1ViewController class]]; MJSettingItem *viewMsg = [MJSettingArrowItem itemWithIcon:@"MoreMessage" title:@"查看消息" destVcClass:[MJTest1ViewController class]]; MJSettingItem *product = [MJSettingArrowItem itemWithIcon:@"MoreNetease" title:@"产品推荐" destVcClass:[MJTest1ViewController class]]; MJSettingItem *about = [MJSettingArrowItem itemWithIcon:@"MoreAbout" title:@"关于" destVcClass:[MJTest1ViewController class]]; MJSettingGroup *group = [[MJSettingGroup alloc] init]; group.items = @[update, help, share, viewMsg, product, about]; [self.data addObject:group]; } /** * 第0组数据 */ - (void)setupGroup0 { MJSettingItem *pushNotice = [MJSettingArrowItem itemWithIcon:@"MorePush" title:@"推送和提醒" destVcClass:[MJTest1ViewController class]]; MJSettingItem *handShake = [MJSettingSwitchItem itemWithIcon:@"handShake" title:@"摇一摇机选"]; MJSettingItem *soundEffect = [MJSettingSwitchItem itemWithIcon:@"sound_Effect" title:@"声音效果"]; MJSettingGroup *group = [[MJSettingGroup alloc] init]; group.items = @[pushNotice, handShake, soundEffect]; [self.data addObject:group]; } - (void)viewDidLoad { [super viewDidLoad]; // 1.标题 self.title = @"设置"; // 2.添加数据 [self setupGroup0]; [self setupGroup1]; } @end
效果如下:
系统源码下载:点击下载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端