A.需要掌握的
设计、实现设置界面cell的封装UICollectionView的使用自定义UICollectionView抽取控制器父类“帮助”功能code source: https://github.com/hellovoidworld/HelloLottery
B.实现
1.探讨“设置”界面的实现方案
(1)“设置”界面可以采用的做法
static cell(呆板,完全没有动态)使用代码,条件判断逐个编写(麻烦,代码冗长)使用模型、plist加载(能够动态配置跳转控制器,不能配置请求代码;由于使用字符串配置跳转控制器名,容易出现运行时错误)
(2)“设置”界面最终的做法
a.使用模型封装每个cell的数据(item),使用Class作为跳转控制器属性(这样就能经过编译检测)
b.在“设置”控制器延迟加载数据,设置每个cell的数据
2.“设置”界面控制器基类
(1)创建cell的数据模型group
组:包含了头部和尾部数据,还有最重要的内容数据items
group:
头部标题尾部标题items
(2)创建cell的数据模型item
包含了每个cell的内容,有图标、标题,根据有部分控件的不同,创建不同的item类
item:
图标标题跳转目标控制器类
各种不同类型的item数据模型类:
(3)创建自定义cell,包含图标、标题、右部分控件(暂时有跳转箭头、开关、文本)
设置数据成员(item模型数据属性)加载数据提供静态初始化方法cellWithTableView,使用缓冲池重用细分子类自定义“开关”item(不能点击跳转,拥有一个开关)细分子类自定义“箭头”item(点击跳转,没有开关)默认的请求item(不能点击跳转,没有开关,内置block成员)
根据item的类型,描绘cell的外观:
1/** 设置右部分控件*/2- (void) setuPRightView {3if([self.item isKindOfClass:[HVWArrowSettingItemclass]]) {//跳转箭头类型4self.accessoryView =self.arrowView;5}elseif([self.item isKindOfClass:[HVWSwitchSettingItemclass]]) {//开关类型6self.accessoryView =self.switchView;7}elseif([self.item isKindOfClass:[HVWLabelSettingItemclass]]) {//标签类型8self.accessoryView =self.labelView;9}else{10self.accessoryView =nil;11}12}
(4)执行代码属性block
使用copy修饰使用MBProgressHUD外部包进行提示信息显示,模拟交互效果
a.定义block成员
1//2//HVWSettingItem.h3//HelloLottery4//5//Created by hellovoidworld on 15/1/6.6//Copyright (c) 2015年 hellovoidworld. All rights reserved.7//89#import<Foundation/Foundation.h>1011typedefvoid(^RunningBlock)();1213/** item基类*/14@interfaceHVWSettingItem : NSObject1516/** 图标*/17@property(nonatomic, copy) NSString *icon;1819/** 标题*/20@property(nonatomic, copy) NSString *title;2122/** block代码*/23@property(nonatomic, copy) RunningBlock runningBlock;2425+ (instancetype) itemWithIcon:(NSString *) icon title:(NSString *) title;26+ (instancetype) itemWithTitle:(NSString *) title;2728@end
b.配置block
使用外部包辅助进行弹窗信息的显示
1//第1组2HVWSettingItem *updateCheckItem = [HVWArrowSettingItem itemWithIcon:@"MoreUpdate"title:@"检查新版本"];34//检查新版本配置一个block,模拟更新过程5updateCheckItem.runningBlock = ^{6//弹窗提示7[MBProgressHUD showMessage:@"正在使出吃奶的劲儿检查中..."];89//模拟发送网络请求延迟10dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{11//隐藏消息框12[MBProgressHUD hideHUD];1314//提醒版本信息15[MBProgressHUD showError:@"没有发现新版本!"];16});17};
(5)自定义继承UITableViewController的HVWBaseSettingViewController作为“设置”界面的控制器父类,为“设置”的若干个子界面提供公共逻辑代码。
包括功能
加载解析group和item数据根据group数据创建table的样式根据不同的item模型创建不同的cell外观如果item类是跳转类型的,需要配置跳转目标控制器如果item类是代码执行型的,需要配置block代码
a.使用同一个BaseSettingViewController作为父类,配置了不同数据的界面
b.所有类“设置”界面控制器:
c.MVC
3.部分代码
a.“设置”跳转控制器父类:
1//2//HVWBaseSettingViewController.m3//HelloLottery4//5//Created by hellovoidworld on 15/1/6.6//Copyright (c) 2015年 hellovoidworld. All rights reserved.7//89#import"HVWBaseSettingViewController.h"10#import"HVWSettingGroup.h"11#import"HVWSettingItem.h"12#import"HVWSettingCell.h"13#import"HVWArrowSettingItem.h"1415@interfaceHVWBaseSettingViewController ()1617@end1819@implementationHVWBaseSettingViewController2021- (void)viewDidLoad {22[super viewDidLoad];232425}2627- (void)didReceiveMemoryWarning {28[super didReceiveMemoryWarning];29//Dispose of any resources that can be recreated.30}3132/** 重写初始化方法33* 一定要使用group样式34*/35-(instancetype)init {36return[super initWithStyle:UITableViewStyleGrouped];37}3839-(instancetype)initWithStyle:(UITableViewStyle)style {40return[super initWithStyle:UITableViewStyleGrouped];41}4243/** 加载空数据*/44- (NSMutableArray *)data {45if(nil ==_data) {46_data =[NSMutableArray array];47}4849return_data;50}5152#pragmamark - Table view data source5354- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {55returnself.data.count;56}5758- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {59HVWSettingGroup *group =self.data[section];60returngroup.items.count;61}6263- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {64HVWSettingCell *cell =[HVWSettingCell cellWithTableView:tableView];65HVWSettingGroup *group =self.data[indexPath.section];66cell.item =group.items[indexPath.row];67returncell;68}6970#pragmamark - 代理方法71- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {72//1.取消选中,不要保持选中状态73[self.tableView deselectRowAtIndexPath:indexPath animated:YES];7475//2.1加载点击事件76HVWSettingGroup *group =self.data[indexPath.section];77HVWSettingItem *item =group.items[indexPath.row];7879//2.2如果配置有block, 运行block80if(item.runningBlock) {81item.runningBlock();82}8384//2.3配置跳转控制器85if([item isKindOfClass:[HVWArrowSettingItemclass]]) {//如果是跳转类型的item86HVWArrowSettingItem *arrowItem = (HVWArrowSettingItem *) item;878889if(nil !=arrowItem.destinationViewControllerClass) {90UIViewController *viewController =[[arrowItem.destinationViewControllerClass alloc] init];91viewController.title =arrowItem.title;92[self.navigationController pushViewController:viewController animated:YES];93}94}95}9697/** 组头部*/98- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {99HVWSettingGroup *group =self.data[section];100returngroup.headerTitle;101}102103/** 组尾部*/104- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {105HVWSettingGroup *group =self.data[section];106returngroup.tailTitle;107}108109@end
b.“设置”界面控制器
1//2//HVWSettingViewController.m3//HelloLottery4//5//Created by hellovoidworld on 15/1/6.6//Copyright (c) 2015年 hellovoidworld. All rights reserved.7//89#import"HVWSettingViewController.h"10#import"HVWSettingGroup.h"11#import"HVWArrowSettingItem.h"12#import"HVWSwitchSettingItem.h"13#import"HVWPushNoticeViewController.h"14#import"MBProgressHUD+MJ.h"1516@interfaceHVWSettingViewController ()1718@end1920@implementationHVWSettingViewController2122- (void)viewDidLoad {23[super viewDidLoad];24//Do any additional setup after loading the view.2526//设置标题27self.title =@"设置";2829//配置数据30[self setupGroup0];31[self setupGroup1];32}3334- (void) setupGroup0 {35//第0组36HVWSettingItem *pushItem = [HVWArrowSettingItem itemWithIcon:@"MorePush"title:@"推送和提醒"destinationViewControllerClass:[HVWPushNoticeViewControllerclass]];37HVWSettingItem *shakeItem = [HVWSwitchSettingItem itemWithIcon:@"handShake"title:@"摇一摇机选"];38HVWSettingItem *soundItem = [HVWSwitchSettingItem itemWithIcon:@"sound_Effect"title:@"声音效果"];39HVWSettingItem *assistantItem = [HVWSwitchSettingItem itemWithIcon:@"IDInfo"title:@"购彩小助手"];4041HVWSettingGroup *group =[[HVWSettingGroup alloc] init];42group.items =@[pushItem, shakeItem, soundItem, assistantItem];4344[self.data addObject:group];45}4647- (void) setupGroup1 {48//第1组49HVWSettingItem *updateCheckItem = [HVWArrowSettingItem itemWithIcon:@"MoreUpdate"title:@"检查新版本"];5051//检查新版本配置一个block,模拟更新过程52updateCheckItem.runningBlock = ^{53//弹窗提示54[MBProgressHUD showMessage:@"正在使出吃奶的劲儿检查中..."];5556//模拟发送网络请求延迟57dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{58//隐藏消息框59[MBProgressHUD hideHUD];6061//提醒版本信息62[MBProgressHUD showError:@"没有发现新版本!"];63});64};6566HVWSettingItem *checkMailItem = [HVWArrowSettingItem itemWithIcon:@"MoreMessage"title:@"查看邮箱"];67HVWSettingItem *shareItem = [HVWArrowSettingItem itemWithIcon:@"MoreShare"title:@"分享"];68HVWSettingItem *productRecommandItem = [HVWArrowSettingItem itemWithIcon:@"MoreNetease"title:@"产品推荐"];69HVWSettingItem *aboutItem = [HVWArrowSettingItem itemWithIcon:@"MoreAbout"title:@"关于"];7071HVWSettingGroup *group =[[HVWSettingGroup alloc] init];72group.items =@[updateCheckItem, checkMailItem, shareItem, productRecommandItem, aboutItem];73[self.data addObject:group];74}7576- (void)didReceiveMemoryWarning {77[super didReceiveMemoryWarning];78//Dispose of any resources that can be recreated.79}8081@end
4.“产品推荐”界面
基本框架:
(1)UICollectionView的基本使用
a.注册cell(告诉collectionView将来创建怎样的cell)
1[self.collectionView registerClass:[UICollectionViewCellclass] forCellWithReuseIdentifier:@"product"];
b.从缓存池中取出cell
1- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath2{3UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"product"forIndexPath:indexPath];45returncell;6}
b.重写init方法,创建布局参数
1- (id)init2{3//1.流水布局4UICollectionViewFlowLayout *layout =[[UICollectionViewFlowLayout alloc] init];5//2.每个cell的尺寸6layout.itemSize = CGSizeMake(100,100);7return[super initWithCollectionViewLayout:layout];8}
(2)UICollectionViewFlowLayout
UICollectionViewFlowLayout称为”流水布局”, 用来约束cell的显示
常见属性
Cell的尺寸
@property (nonatomic) CGSize itemSize;
cell之间的水平间距
@property (nonatomic) CGFloat minimumInteritemSpacing;
cell之间的垂直间距
@property (nonatomic) CGFloat minimumLineSpacing;
四周的内边距
@property (nonatomic) UIEdgeInsets sectionInset;
(3)自定义UICollectionViewCell(每个“产品”图标)
a.通过一个json文件读取数据,使用“产品”模型封装
使用NSJSONSerialization解析JSON数据,得到装有字典数据的数组字典转模型
b.使用xib设计自定义UICollectionCell
自定义类xib设计自定义类的初始化、方法设计
c.UICollectionViewController对于xib自定义UICollectionCell的适配
修改重用方法在init方法中,设置cell的尺寸、水平间距、垂直间距设置四周间距
HVWUICollectionViewController:
1//2//HVWProductViewController.m3//HelloLottery4//5//Created by hellovoidworld on 15/1/7.6//Copyright (c) 2015年 hellovoidworld. All rights reserved.7//89#import"HVWProductViewController.h"10#import"HVWProduct.h"11#import"HVWProductCell.h"1213@interfaceHVWProductViewController ()1415/** 数据*/16@property(nonatomic, strong) NSArray *products;1718@end1920@implementationHVWProductViewController2122staticNSString *constreuseIdentifier =@"HVWProductCell";2324- (void)viewDidLoad {25[super viewDidLoad];2627//1.Register cell classes 注册cell,要使用哪个CollectionViewCell28UINib *nib = [UINib nibWithNibName:@"HVWProductCell"bundle:[NSBundle mainBundle]];29[self.collectionView registerNib:nib forCellWithReuseIdentifier:reuseIdentifier];3031//2.设置背景色32self.collectionView.backgroundColor =[UIColor whiteColor];33}3435- (void)didReceiveMemoryWarning {36[super didReceiveMemoryWarning];37//Dispose of any resources that can be recreated.38}3940/** 加载JSON数据*/41- (NSArray *)products {42if(nil ==_products) {43//1.读取json44NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"more_project.json"ofType:nil];4546//2.加载数据47NSData *data =[NSData dataWithContentsOfFile:jsonPath];4849//3.将json数据转成数组、字典,使用一个json工具类50NSArray *dictArray =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];5152//4.字典转模型53NSMutableArray *productArray =[NSMutableArray array];54for(NSDictionary *dictindictArray) {55HVWProduct *product =[HVWProduct productWithDictionary:dict];56[productArray addObject:product];57}5859_products =productArray;60}61return_products;62}6364/** 初始化,配置布局*/65-(instancetype)init {66//1.使用流水布局67UICollectionViewFlowLayout *layout =[[UICollectionViewFlowLayout alloc] init];6869//2.设置cell尺寸70layout.itemSize = CGSizeMake(80,80);7172//3.设置cell水平间距73layout.minimumInteritemSpacing =0;7475//4.设置cell垂直间距76layout.minimumLineSpacing =10;7778//5.设置四周边距79layout.sectionInset = UIEdgeInsetsMake(layout.minimumLineSpacing,0,0,0);8081//6.配置布局方式82return[super initWithCollectionViewLayout:layout];83}84858687#pragmamark <UICollectionViewDataSource>8889- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {90return1;91}929394- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {95returnself.products.count;96}9798- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {99100//1.获得cell101HVWProductCell *cell =[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];102103//2.配置模型数据104cell.product =self.products[indexPath.item];105106returncell;107}108109#pragmamark <UICollectionViewDelegate>110/** 选择事件*/111- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {112HVWProduct *product =self.products[indexPath.item];113NSLog(@"选择了app: %@", product.title);114}115116@end
8.“帮助”模块
(1)UIWebView
加载网页
// 创建URL
NSURL *url = [[NSBundle mainBundle] URLForResource:@”abc.html” withExtension:nil];
// 创建请求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 发送请求加载网页
[webView loadRequest:request];
执行javaScript(要等网页加载完毕才能执行)
[webView stringByEvaluatingJavascriptFromString:js];
监听webView的加载
设置代理监听:webView.delegate = self;
(2)“帮助”界面
创建类“设置”界面控制器:HVWHelpViewController
a.加载json数据,使用HVWHtml模型封装
b.根据HVWHtml模型数据,封装出tableView的group和item用于显示
(3)“帮助”条目点击查看
a.HVWHelpViewController根据html数据动态配置了所有cell的显示内容,所以要再动态配置每个cell的跳转页面,跳转用控制器HVWHtmlViewController(这个是继承UIViewController的普通控制器)
b.创建一个UIViewController,使用UIWebView加载html网页
c.HVWHtmlViewController加载完html后,执行js代码跳转到html网页的指定位置
1//2//HVWHelpViewController.m3//HelloLottery4//5//Created by hellovoidworld on 15/1/7.6//Copyright (c) 2015年 hellovoidworld. All rights reserved.7//89#import"HVWHelpViewController.h"10#import"HVWHtml.h"11#import"HVWArrowSettingItem.h"12#import"HVWSettingGroup.h"13#import"HVWHtmlViewController.h"14#import"HVWNavigationController.h"1516@interfaceHVWHelpViewController ()1718/** html数据*/19@property(nonatomic, strong) NSArray *htmls;2021@end2223@implementationHVWHelpViewController2425- (void)viewDidLoad {26[super viewDidLoad];27//Do any additional setup after loading the view.2829//配置html数据30//1.创建item31NSMutableArray *items =[NSMutableArray array];32for(HVWHtml *htmlinself.htmls) {33HVWSettingItem *item =[HVWArrowSettingItem itemWithTitle:html.title destinationViewControllerClass:nil];34[items addObject:item];35}3637//2.创建group38HVWSettingGroup *group =[[HVWSettingGroup alloc] init];39group.items =items;4041//3.配置到tableView42[self.data addObject:group];43}4445/** 加载数据*/46- (NSArray *)htmls {47if(nil ==_htmls) {48//1.读取json49NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"help.json"ofType:nil];5051//2.解析json52NSData *jsonData =[NSData dataWithContentsOfFile:jsonPath];53NSArray *jsonArray =[NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];5455//3.字典转模型56NSMutableArray *htmlArray =[NSMutableArray array];57for(NSDictionary *dictinjsonArray) {58HVWHtml *html =[HVWHtml htmlWithDictionary:dict];59[htmlArray addObject:html];60}61_htmls =htmlArray;6263}64return_htmls;65}6667- (void)didReceiveMemoryWarning {68[super didReceiveMemoryWarning];69//Dispose of any resources that can be recreated.70}717273#pragmamark - 代理方法74/** cell点击跳转*/75- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {7677HVWHtmlViewController *htmlViewController =[[HVWHtmlViewController alloc] init];78htmlViewController.html =self.htmls[indexPath.row];7980/** 为了实现向上弹出效果,不使用push,而是用modal (present**);81* 使用NaviationController是为了配置一个头部导航栏82*/83HVWNavigationController *nv =[[HVWNavigationController alloc] initWithRootViewController:htmlViewController];84[self.navigationController presentViewController:nv animated:YES completion:nil];85}8687@end
1//2//HVWHtmlViewController.m3//HelloLottery4//5//Created by hellovoidworld on 15/1/7.6//Copyright (c) 2015年 hellovoidworld. All rights reserved.7//89#import"HVWHtmlViewController.h"10#import"HVWHtml.h"1112@interfaceHVWHtmlViewController ()<UIWebViewDelegate>1314@end1516@implementationHVWHtmlViewController171819- (void)loadView {20//改变内置view为UIWebView21self.view =[[UIWebView alloc] init];22}2324- (void)viewDidLoad {25[super viewDidLoad];26//Do any additional setup after loading the view.2728}293031/** 加载数据*/32- (void)setHtml:(HVWHtml *)html {33_html =html;3435//1.设置标题36self.title =self.html.title;3738//2.获取UIWebView39UIWebView *webView = (UIWebView *) self.view;40//设置webView代理41webView.delegate=self;4243//3.创建URL44NSURL *url =[[NSBundle mainBundle] URLForResource:self.html.html withExtension:nil];4546//4.创建请求47NSURLRequest *request =[NSURLRequest requestWithURL:url];4849//5.发送请求50[webView loadRequest:request];5152//6.添加关闭按钮53self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"关闭"style:UIBarButtonItemStylePlain target:self action:@selector(close)];54}5556- (void)didReceiveMemoryWarning {57[super didReceiveMemoryWarning];58//Dispose of any resources that can be recreated.59}6061- (void) close {62[self dismissViewControllerAnimated:YES completion:nil];63}6465/** 加载html完毕,跳转到指定部分*/66- (void)webViewDidFinishLoad:(UIWebView *)webView {67//1.合成js代码68NSString *js = [NSString stringWithFormat:@"window.location.href = '#%@';", self.html.ID];6970//2.执行js代码71[webView stringByEvaluatingJavaScriptFromString:js];72}7374@end