UITableView可以说是非常广泛的出现在各大app中的类了。今天算是专心的做了一天的列表视图,实现了一些基本的功能。
在开始之前,先要弄明白UITableViewDataSource这个协议都要实现哪写方法。苹果官方的API就贴在文末了
首先关注两个Required的方法:cellForRowAtIndexPath和numberOfRowsInSection
其中numberOfRowsInSection就是返回数据的组数就不多说了,只要注意row是从0开始的就好
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//#warning Incomplete implementation, return the number of rows
return [[[User sharedUser] allItems] count] + 1;
}
顺便提一下相似的另一个可选方法numberOfSectionsInTableView,默认生成这个方法时会返回0,这个必须改掉,因为这个方法返回的值是Sections,再少的data source都有一个Sections。Sections可以理解为通讯录或者字典中的首字母的节创建:
对于cellForRowAtIndexPath,这个方法主要做了这些事:
1、创建一个UITableViewCell的对象
2、获取所需的数据模型的对象的数据
3、得到信息,将信息给到cell以后返回这个cell
然而,iOS设备内存有限,不可能同时为所有数据条目准备一份cell对象,所以就需要cell对象的重用,每个cell在不被用户看到后会被丢到一个cell的对象池中等待被重用,当tableview对象要求data source返回某个cell时,只要从池中取到cell对象,再宠幸配置数据就可以返回了,在cellForRowAtIndexPath我们就做了这件事。
重用有两种方法
方法一:
使用 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
这种方法,用到的参数是一个NSString类型的cell的标签。标签的用途是因为可能存在同一张表中需要不同样式的cell,只有同种类的cell才能互相重用。所以对于同种对cell,我们都要给它一个标签来标明它的种类。标签名一般为类名。
因为初始状态下cell对象池为空,所以一开始这个函数可能返回nil,所以一般我们会这么写
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];
//数据配置操作...
}
使用
UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"UITableViewCell"forIndexPath:indexPath];
与上一种方法对比,多出的类型为(NSIndexPath *)参数IndexPath用来确定cell的位置。对于这种方法,在所需cell对象为空(对象池中没有与自己标签相同的对象)的情况下会自动生成新对象,也就是说不会有nil的出现,比上一种方法省略了判断后的函数体
然而这种方法必须在使用前对标签进行注册,否则程序会crash
//注册cell
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"];
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"noMore"];
然后是一些可选的方法,涉及到了表格的删除,移动等操作
删除:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
这个方法中可以完成的操作有删除和插入,此处以插入为例
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//如果tableview 请求确认删除操作
if (editingStyle == UITableViewCellEditingStyleDelete) {
if(indexPath.row < [[[User sharedUser] allItems] count]){
// 从data source删除数据
NSArray *items = [[User sharedUser] allItems];
UserItem *item = items[indexPath.row];
[[User sharedUser] removeItem:item];
//删除表格中的对应行 用fade的动画效果(暂时没看出有啥区别...)
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
对于删除操作要注意的是,要保证视图和模型对象数据的一致性!
下面这这个方法(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
可以自定义删除的文字
//自定义删除文字
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.row < [[[User sharedUser] allItems] count]){
NSArray *items = [[User sharedUser] allItems];
UserItem *item = items[indexPath.row];
NSString *del;
if([item.name isEqualToString:@"xxx"]){
del = [[NSString alloc]initWithFormat :@"%@,%@", @"再见", item.name];
}
else{
del = [[NSString alloc]initWithFormat :@"%@,%@", @"滚吧", item.name];
}
return del;
}
else
return @"Unable";
}
移动:
对于移动,使用
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
注意点依旧是数据模型和试图的一致性
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
[[User sharedUser] moveItemAtIndex:fromIndexPath.row toIndex:toIndexPath.row];
}
下面这个方法可以对每个cell设置条件的移动,说白了就是让谁移谁不能移
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the item to be re-orderable.
//设置可以滑动
NSArray *items = [[User sharedUser] allItems];
//最后一行不可滑动
if (indexPath.row + 1 == [items count] + 1) {
return NO;
}
//只有一行数据时也不可滑动
else if([items count] == 1){
return NO;
}
return YES;
}
还有一个
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;
有点复杂,先不说了...
Configuring a Table View
- tableView:cellForRowAtIndexPath:
Asks the data source for a cell to insert in a particular location of the table view.
- numberOfSectionsInTableView:
Asks the data source to return the number of sections in the table view.
- tableView:numberOfRowsInSection:
Tells the data source to return the number of rows in a given section of a table view.
- sectionIndexTitlesForTableView:
Asks the data source to return the titles for the sections for a table view.
- tableView:sectionForSectionIndexTitle:atIndex:
Asks the data source to return the index of the section having the given title and section title index.
- tableView:titleForHeaderInSection:
Asks the data source for the title of the header of the specified section of the table view.
- tableView:titleForFooterInSection:
Asks the data source for the title of the footer of the specified section of the table view.
Inserting or Deleting Table Rows
- tableView:commitEditingStyle:forRowAtIndexPath:
Asks the data source to commit the insertion or deletion of a specified row in the receiver.
- tableView:canEditRowAtIndexPath:
Asks the data source to verify that the given row is editable.
Reordering Table Rows
- tableView:canMoveRowAtIndexPath:
Asks the data source whether a given row can be moved to another location in the table view.
- tableView:moveRowAtIndexPath:toIndexPath:
Tells the data source to move a row at a specific location in the table view to another location.
github仓库还没搭好,以后弄好了上传地址吧