概述

基本上,每一款APP都有相应的设置模块。怎么设置才能更灵活和通用呢,这也是大家一直思考的。下面说说在网易彩票中,设置模块的设置思想。

基本上有三种方案:

  1. static cell(呆板,完全没有动态)
  2. 使用代码,条件判断逐个编写(麻烦,代码冗长)
  3. 使用plist加载(能够动态配置跳转控制器,不能配置请求代码;由于使用字符串配置跳转控制器名,容易出现运行时错误)
  4. 使用模型封装每个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(, , , );
_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

效果如下:

系统源码下载:点击下载

iOS 网易彩票-4设置模块一的更多相关文章

  1. iOS 网易彩票-6设置模块三(常用小功能)

    该篇文章中,用到很多iOS开发过程中常用的小功能,当前只是将这些功能集成到网易彩票的设置中.iOS-常用小功能介绍,请参考我的另一篇文章: iOS 常用小功能 总结:http://www.cnblog ...

  2. iOS 网易彩票-5设置模块二

    产品推荐 产品推荐使用的是UICollectionView控件,UICollectionView 和 UICollectionViewController 类是iOS6 新引进的API,用于展示集合视 ...

  3. iOS 网易彩票-1框架搭建

    仿网易彩票,最终要做成的效果如下: 一.分层搭建 1.新建一个项目,Lottery.只支持7.1以上坚屏. 2.将素材全部图片全部拉到相应的文件夹里. 3.选中Lottery--右键Show in F ...

  4. iOS 网易彩票-3常见设置

    Navigation导航设置 为了统一管理导航控制器,需要自定义导航控制器MJNavigationController,继承于UINavigationController.分别设置5个Navigati ...

  5. iOS 网易彩票-2框架搭建-代码重构

    在上一篇中,我们基本已经把整个框架都搭建出来了,下面进行代码重构一下. 思路: 导航按钮,按下时,会变灰,那是系统自带了,通过自定义UIButton,实现按下按钮立即切换效果. MJTabBarCon ...

  6. iOS菜鸟成长笔记(2)——网易彩票练习

    距离上一篇<第一个iOS应用>已经有一个多月了,今天来和大家一起学习和分享一下一个小练习<网易彩票> 首先我们向storyboard中拖入一个TabBarController和 ...

  7. iOS开发——实战总结OC篇&网易彩票开发知识点总结

    网易彩票开发知识点总结 关于网易彩票开发中遇到了不少的坑,弄了好久才弄懂,或者有些犹豫很久没用就不记得了,所以这里就总结了一下,希望以后不会忘记,就算忘记也能快速查看! /************** ...

  8. 再造轮子之网易彩票-第一季(IOS 篇 by sixleaves)

    前言 在网上看了别人做的模仿网易彩票的项目, 于是也跟着用自己的想法做了一篇.写这篇博客的目的, 在于UI综合的一次小练习, 同时总结和串联其各个控件之间的应用.封装思想等.考虑到有人上不了githu ...

  9. UI进阶之--网易彩票手写plist文件,动态创建控制器与tableViewcell

    点击右上角设置按钮 点击按钮后发生的事件:1. 控制器的跳转,进入新的控制器.view, 2. 跳转的时候对将要跳转的目标控制的子控件进行了布局.---通过手写plist文件的方式加载 为按钮注册单击 ...

随机推荐

  1. C#设计模式--装饰器模式

    0.C#设计模式-简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C# ...

  2. office excel Query 功能

    Microsoft Query 合并查询 Excel 2016 默认已集成 Power Query 功能

  3. vue2.0笔记《一》列表渲染

    内容中包含 base64string 图片造成字符过多,拒绝显示

  4. sencha touch 监听视图切换动画(animation)

    var animation = this.getLayout().getAnimation(); //添加监听 animation.on({ scope: this, animationend: 'o ...

  5. mysql optimize整理表碎片

    当您的库中删除了大量的数据后,您可能会发现数据文件尺寸并没有减小.这是因为删 除操作后在数据文件中留下碎片所致.optimize table 可以去除删除操作后留下的数据文件碎片,减小文件尺寸,加快未 ...

  6. 2015.8.2js-19(完美运动框架)

    /*完美运动框架*/ //1.先清除定时期,2,获取样式,如果是opacity则单独解决,3,定义速度,4,定义当前值是否到达目的地,5,判断当前值是否到达目的地,6运动基本,如果是opacity f ...

  7. 总结一下最近用到的技术(2)--JsonSchema和JsonSchemaValidator

    我们最早接触xml的时候会使用一个dtd文件去定义xml里可以有哪些元素和属性等,后来发展到xml schama(是一个xsd文件,在dtd的基础上提供了命名空间等更强大的功能) 现在,RESTful ...

  8. 涨知识,涨知识 :ThinkPHP框架下Where条件查询Mysql数据库某字段是否为空

    代码虐我千百遍,我对代码如初恋~ 问题: 查询某字段app_date数据是否为NULL,正常我们实现的办法是: $map['app_data'] = array('eq','null'); $data ...

  9. iOS - Block的简单使用

    Block 的使用有两种: .独立Block .内联Block   <一>独立Block 使用方式   一.定义一个Block Object,并调用.   1.定义   // 定义一个Bl ...

  10. Shell转义字符与变量替换

    转义字符 含义 \\ 反斜杠 \a 警报,响铃 \b 退格(删除键) \f 换页(FF),将当前位置移到下页开头 \n 换行 \r 回车 \t 水平制表符(tab键)  \v 垂直制表符 vim te ...