GeekBand iOS应用开发实战学习笔记(第三周)

UITableView

UITableView用来管理通用表格组件,通用表格组件需要考虑数据集的输入、每行数据的显示、行操作(包括点击、编辑、删除、插入、调整行顺序)。根据MVC编程的思想,UITableView只需要管理表格视图,和行操作,对数据的内部不需要干涉,由专门的数据来源提供。

UITableVIew的结构

TableVIew的数据来源是由UITableViewDataSource管理的,这是一个协议(protocal),只要遵守该协议的数据源都可以向UITableView提供数据。
每个table view是由多个区块(section)组成的。
上图中NSIndexPath指向的区域是一个section,每个section里都有section header和section footer。在中间是由行(row)组成的。
当用户用手点击其中的某一行,将向UITableViewDelegate发送一个事件响应消息,UITableViewDelegate再做出对应的响应。

代码实现

在ViewController.h头文件中加入对UITableDataSource和UITableViewDelegate的协议支持。
@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
UITableDataSource协议中有两个required方法:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section \\\设置整个表格有几个区块 -(NSInteger)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath \\\设置表格中区块有几行
可在ViewController.m文件中添加所需的UITableDataSource协议中方法。

UITableView的style有plain、grouped两种属性
.dataSource经常使用的的方法有:

numberOfSectionsInTableView:
tableView:numberOfRowsInSection:
tableView:cellForRowAtIndexPath:
tableView:viewForHeader/FooterInSection: 

.delegate经常使用的方法有:

tableView:didSelectRowAtIndexPath:

UITableViewCell的使用
重复使用与Cell Identifier

UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
if (cell == nil){
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCell"];
}
return cell;

系统为UITableViewCell提供了不同的风格,包括:Default, Value1,Value2 Subtitle
如果想定制自己风格的表格有多种方法
1、用StoryBoard prototype 提供cell:可以用view tag访问界面,也可以用子类里的outlet访问界面。
2、用xib提供cell:可以用registerNib方法注册xib,也可以用registerClass的方法注册xib。

上课演示代码的详解:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if ( section == 0) { //设置第一个区块有3行,其他区块有10行
return 3;
}
else {
return 10;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView * header = [[UIView alloc] init];  //创建了一个header
header.backgroundColor = [UIColor redColor];  //设置header的背景色
return header;


- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIView * footer = [[UIView alloc] init];  //创建了一个footer
footer.backgroundColor = [UIColor blueColor];  //设置footer的背景色
return footer;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
tableView.rowHeight = 128; // change it and watch number of cells alive.
NSString * cellID = [NSString stringWithFormat:@"cell_sec_%ld", (long)indexPath.section ];
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if ( cell == nil ) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID]; // there are more built-in styles
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text = [NSString stringWithFormat:@"%ld", (long)indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat:@"section %ld - row %ld", (long)indexPath.section, (long)indexPath.row];
if ( indexPath.section == 0 ) {
    cell.imageView.image = [UIImage imageNamed:@"gear"];
} else {
    cell.imageView.image = [UIImage imageNamed:@"guitar"];
}
return cell;


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:@"showDetail" sender:indexPath];

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.


- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ( [segue.identifier isEqualToString:@"showDetail"] ) {
    DetailedViewController * dvc = segue.destinationViewController;
    dvc.indexPath = sender;
}

UITableViewController
可以用来管理UITableView,当UITableView嵌在UITableViewController里时可以使用static cell,支持下拉刷新界面。
下拉刷新界面代码:

self.refreshControl = [[UIRefreshControl alloc] init];
self.refreshControl.attributedTitle = [[NSAttributeString alloc] initWithString:@"Scan"]; //这段代码需要放到viewDidappear里
[self.refreshControl addTarget:self action:@selector(refreshing:)forControlEvents:UIControlEventValueChanged];

响应代码

- (IBAction)startRefresh:(id)sender{
  [self.refreshControl endRefreshing];
  [self.tableView reloadData];
}

当刷新表格时UITableView并不知道dataSource有变化,有一系列reload方法来让UITableView来更新变化。
reloadData 用来刷新整个表格
reloadRowsAtIndexPaths:withRowAnimation: 用来刷新行
reloadSections:withRowAnimation: 用来刷新整个区块
reloadSectionIndexTitles 用来刷新索引

刷新页面的关键代码

- (IBAction)startRefresh:(id)sender{
  self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"scanning"];
  [self performSelector:@selector(stopRefreshing) withObject:nil afterDelay:1.0]; //一秒钟以后停止刷新方法
}

- (void) stopRefreshing{
  [self.refreshControl endRefreshing];
  [self.tableView reloadData];
}

TableView的交互
在TableView中选择某一行是最基本的操作。
选中的响应

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath  //选中某一行
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath  //将某一行的状态改为未选中

-(void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;  //用代码选中,scrollPosition有几种选项可选,UITableScrollPositionTop, UITableScrollPositionMiddle,UITableScrollPositionBottom,UITableScrollPositionNone
-(void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;

NSIndexPath *indexPathForSelectedRow
NSArray<NSIndexPath *> *indexPathsForSelectedRows

控制表格滚动

- scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
-scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated

上面代码中的UITableViewScrollPosition参数有四种
UITableScrollPositionTop 行出现在表顶
UITableScrollPositionMiddle 行出现在表中间
UITableScrollPositionBottom 行出现在表底
UITableScrollPositionNone 就近

编辑模式

UITableView的编辑模式

编辑模式的响应过程

UITableView编辑模式的响应过程

带索引的表格

带索引的表格

高亮与菜单

高亮与菜单

表格的搜索:在iOS8以后,表格的搜索可以用UISearchController。

CollectionView

有的界面用TableView实现起来不怎么方便(比如横向滚动、一行放多个项目),我们可以使用CollectionView。
CollectionView是对UITableView的扩展,增加了网格式界面,对表格内部职责进一步细分,分离出了Layout类。

CollectionView总体结构与TableView相近,但有一些变化,在TableViewcell中的cell在CollectionView中叫item。header/footer在CollectionView中统一叫supplementary view。item view必须register。布局交给独立的layout类edit方法不再指定动画类型。

cell 供应

关键代码
创建 Collection View

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 13;
}

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    ImageCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ImageCell" forIndexPath:indexPath];
    cell.imageView.image = [self imageOfCityWithId:indexPath.item];
    return cell;
}

提供 DataSource

-(UIImage*)imageOfCityWithId:(NSInteger)cityId {
    return [UIImage imageNamed:[NSString stringWithFormat:@"city%d",(int)cityId]];
}

提供supplementary view的方式

-(UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
    return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"citiesHeader" forIndexPath:indexPath];
}

刷新数据
reloadData
reloadSections:(NSIndexSet *)
reloadItemsAtIndexPaths:(NSArray<NSIndexPath >)

将一组编辑或刷新动作合作到一个动画过程里
-performBatchUpdates:completion:

手工移动格子
beginInteractiveMovementForItemAtIndexPath: //开始拖动制定的格子
updateInteractiveMovementTargetPosition: //更新选定格子被拖到的位置
endInteractiveMovement 或 cancelInteractiveMovement //结束

CollectionView Delegate 里交互的相关方法

Collection View Delegate
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容