UITableViewControl的编辑(删除,添加,移动)
一 创建UITableVIew对象。遵循dataSource delegate协议
1.模型转换
// 模拟假数据
- (void)setModel
{
self.modelArray = [NSMutableArray array];
for (int i = 0; i < 10; i ++)
{
Model *model = [[Model alloc]init];
model.name = [NSString stringWithFormat:@"哈哈%d",i];
model.gender = @"男";
[self.modelArray addObject:model];
// model的初始坐标 用于实现取消置顶 从哪来 回哪去
model.index = i;
[model release];
}
self.modelArray2 = [NSMutableArray array];
for (int i = 0; i < 10; i ++)
{
Model *model = [[Model alloc]init];
model.name = [NSString stringWithFormat:@"嘻嘻%d",i];
model.gender = @"女";
[self.modelArray2 addObject:model];
// model的初始坐标 用于实现取消置顶 从哪来 回哪去
model.index = i;
[model release];
}
}
// 数组懒加载的形式创建出来
// 本质上 是第一次调用get方法的时候 将数组初始化出来 第二次以及以后在调用get方法的时候 返回的都是 第一次初始化出来的空间
// self.会走set 和 get 方法 而_下划线不会走set get 方法
/*
- (NSMutableArray *)modelArray
{
// 切记:复制的时候 全部用self. 防止出现野指针 崩溃的现象
// 懒加载判断的时候 不要使用 self. 因为会调用get方法 会形成死循环
if (_modelArray == nil)
{
self.modelArray = [NSMutableArray array];
}
return _modelArray;
}
*/
self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 375, 667 - 64) style:UITableViewStylePlain];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.view addSubview:_tableView];
二 在viewDidLoad中设定系统自带的tableView编辑按钮
self。navigationItem。rightBarButton = self。editButtonItem;
三 执行协议的方法
#pragma mark --- 返回多少个分区 ---
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
#pragma mark ---- 每个分区下返回多少行 ----
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)
{
return self.modelArray.count;
}
return self.modelArray2.count;
}
#pragma mark --- 返回cell的方法 ---
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIndentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIndentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIndentifier]autorelease];
}
if (indexPath.section == 0)
{
Model *model = self.modelArray[indexPath.row];
cell.textLabel.text = model.name;
cell.detailTextLabel.text = model.gender;
return cell;
}
else
{
Model *model = self.modelArray2[indexPath.row];
cell.textLabel.text = model.name;
cell.detailTextLabel.text = model.gender;
return cell;
}
}
四 实现编辑的必要方法
#pragma mark --- tableView 允许进行编辑 ---
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
}
#pragma mark ---- 允许哪些cell可以进行编辑 ---
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
# pragma mark --- 编辑样式 ---
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1)
{
// 添加样式左滑是不会出现任何效果的 只要点击barButton 进入状态编辑 才会看到绿色的添加符号
return UITableViewCellEditingStyleInsert;// 添加 默认是删除
}
if (indexPath.section == 0)
{
// 默认是删除 删除样式左滑可以出现删除
return UITableViewCellEditingStyleDelete;// 删除样式
}return nil;
}
#pragma mark --- 实现编辑的方法 (删除 添加) ---
// 老方法 iOS8之前的方法
// 此方法空实现的时候 就可以左滑 出现删除按钮
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// 当编辑样式为删除的时候
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// 我们之后 所有的对数据源以及界面的操作 都是先操作数据源 再操作界面 界面是根据数据源的变动而变动得
// 第一步:删除数据源 数组中对应的元素进行删除掉
[self.modelArray removeObjectAtIndex:indexPath.row];
// 第二步:刷新界面
//[self.tableView reloadData];
// 这种刷新方法比上一种效率更高
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
}
else// 添加样式
{
Model *model = [[Model alloc]init];
model.name = @"添加";
model.gender = @"不详";
[self.modelArray insertObject:model atIndex:indexPath.row];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}
}
#pragma mark --- 允许移动 ---
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
#pragma mark --- 移动的触发方法 ---
// 实现了这个方法以后 界面上的移动效果 系统已经帮我们实现好了 但是我们需要在这个方法中操作我们的数据源
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSLog(@"起始坐标 %ld分区 %ld行",sourceIndexPath.section,sourceIndexPath.row);
NSLog(@"最终坐标 %ld分区 %ld行",destinationIndexPath.section,destinationIndexPath.row);
// 同区移动
if (sourceIndexPath.section == destinationIndexPath.section)
{
if (sourceIndexPath.section == 0)
{
// 取到当前model
Model *model = [self.modelArray[sourceIndexPath.row]retain];
[self.modelArray removeObjectAtIndex:sourceIndexPath.row];
[self.modelArray insertObject:model atIndex:destinationIndexPath.row];
[model release];
}
else
{
Model *model = [self.modelArray2[sourceIndexPath.row]retain];
[self.modelArray2 removeObjectAtIndex:sourceIndexPath.row];
[self.modelArray2 insertObject:model atIndex:destinationIndexPath.row];
[model release];
}
}
// 跨区移动
else
{
// 如果是第0个分区作为起始坐标
if (sourceIndexPath.section == 0)
{
// 取出第0个分区移动的model
Model *model = [self.modelArray[sourceIndexPath.row]retain];
// 从第一个分区删除该model
[self.modelArray removeObjectAtIndex:sourceIndexPath.row];
// 插入到地热个分区中移动到的位置
[self.modelArray2 insertObject:model atIndex:destinationIndexPath.row];
}
// 如果是第1个分区作为起始坐标
if (sourceIndexPath.section == 1)
{
Model *model = [self.modelArray2[sourceIndexPath.row]retain];
[self.modelArray2 removeObjectAtIndex:sourceIndexPath.row];
[self.modelArray insertObject:model atIndex:destinationIndexPath.row];
}
}
}
#pragma mark --- 限制跨区移动 ---
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
NSLog(@"起始坐标 %ld分区 %ld行",sourceIndexPath.section,sourceIndexPath.row);
NSLog(@"最终坐标 %ld分区 %ld行",proposedDestinationIndexPath.section,proposedDestinationIndexPath.row);
// 如果起始和跨区在同一个分区 返回最终坐标
if (sourceIndexPath.section == proposedDestinationIndexPath.section)
{
return proposedDestinationIndexPath;
}
// 如果起始和跨区不在同一个分区 返回起始坐标
else
return sourceIndexPath;
}
#pragma mark ---改变系统的删除按钮文字 ---
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 返回删除文字
return @"删除";
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// ios8之后的新方法
#pragma mark --- 自定义tableView编辑按钮的样式以及个数 ---
// 如果实现了这个方法 老的方法就不再执行了
// 如果没有这个方法 还是会继续走老的方法
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
Model *model = self.modelArray[indexPath.row];
if (model.isTop == NO)———isTop在模型类中声明成为属性了,还有下面的index
{
UITableViewRowAction *deletAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"删除");
// 取到当前的model
// 如果
Model *tempModel = self.modelArray[indexPath.row];
for (Model *model in self.modelArray)
{
if (model.index > tempModel.index)
{
model.index--;
}
}
// block块内 写的代码就是该按钮要实现的业务逻辑
// 删除数据源
[self.modelArray removeObjectAtIndex:indexPath.row];
// 刷新tableView列表
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}];
UITableViewRowAction *topAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"置顶" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"置顶");
// 置顶的操作 把置顶的model先取出来 插入到数组当中的第0个位置 然后把之前的model删除掉
Model *tempModel = self.modelArray[indexPath.row];
[self.modelArray insertObject:tempModel atIndex:0];
// 修改置顶状态
tempModel.isTop = YES;
[self.modelArray removeObjectAtIndex:indexPath.row + 1];
[self.tableView reloadData];
}];
return @[deletAction,topAction];
}
else
{
UITableViewRowAction *deletAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"删除");
// 取到当前的model
// 如果
Model *tempModel = self.modelArray[indexPath.row];
for (Model *model in self.modelArray)
{
if (model.index > tempModel.index)
{
model.index--;
}
}
// block块内 写的代码就是该按钮要实现的业务逻辑
// 删除数据源
[self.modelArray removeObjectAtIndex:indexPath.row];
// 刷新tableView列表
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}];
UITableViewRowAction *cancelTopAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"取消置顶" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"取消置顶");
// 取消置顶的操作
Model *tempModel = self.modelArray[indexPath.row];
// 先把当前model置顶状态赋值为NO
tempModel.isTop = NO;
int count = 0;
for (Model *model in self.modelArray)
{
if (model.isTop == YES)
{
if (model.index > tempModel.index)
{
count++;
}
}
}
//
[self.modelArray insertObject:tempModel atIndex:tempModel.index + count + 1];
[self.modelArray removeObjectAtIndex:indexPath.row];
[self.tableView reloadData];
}];
return @[deletAction,cancelTopAction];
}
}