iOS高级开发——CollectionView的动态增删cell及模型重构

     CollectionView是iOS开发中的高级控件,比其他控件使用起来要复杂。我在前面几篇博客中讲解了CollectionView的一些高级用法:《iOS高级开发——CollectionView的cell长按事件实现》、《iOS高级开发——CollectionView的cell中按钮的点击实现》、《iOS项目开发实战——实现UICollectionView的动态增加Cell与Section》。今天我们会来实现对cell的动态删除,以及使用模型对代码进行重构。代码已经上传到https://github.com/chenyufeng1991/CollectionView  中的“动态增加cell和section实现”。

(1)目前我的需求是这样的:要在一个cell中显示一张图片和描述文字,以及CollectionView中有多个section。为了便于后续开发,所以我要先定义两个模型:Section模型和Cell模型。Section模型用来定义CollectionView中所有Section包含的属性,Cell模型用来定义一个Section中每一个Cell的属性。Model实现代码如下:

SectionModel.h:

#import <Foundation/Foundation.h>

@interface SectionModel : NSObject

//定义Section头的名字;
@property(nonatomic,copy) NSString *sectionName;
//定义Section中的cell数组;
@property(nonatomic,strong) NSMutableArray *cellArray;//这里存放的是section中的每一个cell;
@end

CellModel.h:

#import <Foundation/Foundation.h>

@interface CellModel : NSObject

//定义cell中的图片;
@property(nonatomic,strong) NSString *cellImage;
//定义cell中的描述文字;
@property(nonatomic,strong) NSString *cellDesc;

@end


(2)View的设计如下:由于要做cell的删除操作,所以我要在每一个cell上面放一个删除按钮。我这里cell是纯代码实现的,代码如下:

CollectionViewCell.h:(m文件请参看源代码)

#import <UIKit/UIKit.h>

@interface CollectionViewCell : UICollectionViewCell

//cell中的图片;
@property(strong,nonatomic) UIImageView *imageView;
//cell中的描述文本;
@property(strong,nonatomic) UILabel *descLabel;
//cell右上角的删除按钮;
@property(nonatomic,strong)UIButton *deleteButton;
@end


(3)核心代码实现:

页面的右上角会有一个编辑按钮,点击编辑按钮,cell就处于可删除状态。所以cell共有两种状态,正常状态和可删除状态,我用枚举来实现:

@property(nonatomic,assign) enum CellState;

NS_ENUM(NSInteger,CellState){
  
  //右上角编辑按钮的两种状态;
  //正常的状态,按钮显示“编辑”;
  NormalState,
  //正在删除时候的状态,按钮显示“完成”;
  DeleteState
  
};

(4) - ( UICollectionViewCell *)collectionView:  cellForItemAtIndexPath:的实现如下:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
  
  CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CollectionCell" forIndexPath:indexPath];
  
  //找到某一个具体的Section;
  SectionModel *sec = [self.dataSectionArray objectAtIndex:indexPath.section];
  //找到Section中的cell数组中某个具体的cell;
  CellModel *cel = [sec.cellArray objectAtIndex:indexPath.row];

  //取出数据;
  cell.imageView.image = [UIImage imageNamed:cel.cellImage];
  cell.descLabel.text = cel.cellDesc;

  //设置删除按钮
  // 点击编辑按钮触发事件
  if(CellState == NormalState){
    //正常情况下,所有删除按钮都隐藏;
    cell.deleteButton.hidden = true;
  }else{
    //可删除情况下;
    //找到某个具体的section;
    SectionModel *section = self.dataSectionArray[indexPath.section];
    //cell数组中的最后一个是添加按钮,不能删除;
    if (indexPath.row == section.cellArray.count - 1){
      cell.deleteButton.hidden = true;
    }else{
      cell.deleteButton.hidden = false;
    }
  }
  [cell.deleteButton addTarget:self action:@selector(deleteCellButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
  
  return cell;
  
}

(5) - ( void )collectionView:  didSelectItemAtIndexPath:的实现如下:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
  
  //取出是某一个section;
  SectionModel *sec = [self.dataSectionArray objectAtIndex:indexPath.section];
  
  if ((indexPath.row == sec.cellArray.count - 1)) {
    NSLog(@"点击最后一个cell,执行添加操作");
    
    //初始化一个新的cell模型;
    CellModel *cel = [[CellModel alloc] init];
    cel.cellImage = @"1";
    cel.cellDesc = @"再来一个";

    //获取当前的cell数组;
    self.dataCellArray = sec.cellArray;
    
    //把新创建的cell插入到最后一个之前;
    [self.dataCellArray insertObject:cel atIndex:self.dataCellArray.count - 1];
    
    //更新UI;
    [self.collectionView reloadData];
    
  }else{
    NSLog(@"第%ld个section,点击图片%ld",indexPath.section,indexPath.row);
  }
  
}

(6)懒加载:在UI的动态更新中,懒加载是经常会用到的手段。具体实现如下:

懒加载section数组:

- (NSMutableArray *)dataSectionArray{
  if (!_dataSectionArray){
    
    //CollectionView有一个Section数组;
    _dataSectionArray = [[NSMutableArray alloc] initWithCapacity:2];//1个;
    
    for (int i = 0; i < 2; i++) {
      //默认初始有两个Section;
      _dataCellArray = [[NSMutableArray alloc] initWithCapacity:6];//2个;
      
      for (int j = 0; j < 6; j++) {
        //默认一个section中有6个cell;
        //初始化每一个cell;
        CellModel *cellModel = [[CellModel alloc] init];
        cellModel.cellImage = self.cellImageArr[j];
        cellModel.cellDesc = self.cellDescArr[j];
        
        //添加到cell数组中;
        [_dataCellArray addObject:cellModel];
      }//for;
      
      //初始化section;
      SectionModel *sectionModel = [[SectionModel alloc] init];
      sectionModel.sectionName = self.headerArray[i];
      //把上面生成的cell数组加入到section数组中;
      sectionModel.cellArray = _dataCellArray;
      
      //增加一个section;
      [_dataSectionArray addObject:sectionModel];
    }//for;
    
  }
  
  return _dataSectionArray;
}

懒加载cell数组中的图片:

- (NSMutableArray *)cellImageArr{

  if (!_cellImageArr) {
    self.cellImageArr = [[NSMutableArray alloc] initWithObjects:@"0",@"1",@"2",@"3",@"4",@"5",nil];
  }
  
  return _cellImageArr;
}


懒加载cell数组中的描述文字:

- (NSMutableArray *)cellDescArr{

  if (!_cellDescArr) {
    self.cellDescArr = [[NSMutableArray alloc] initWithObjects:@"第0个",@"第1个",@"第2个",@"第3个",@"第4个",@"添加",nil];
  }
  
  return _cellDescArr;
}


(7)删除cell的代码实现,首先需要点击右上角的编辑按钮,使所有的cell处于可删除状态:

- (IBAction)editButtonPressed:(id)sender {
  
  //从正常状态变为可删除状态;
  if (CellState == NormalState) {
    
    CellState = DeleteState;
    self.editButton.titleLabel.text = @"完成";
    
    //循环遍历整个CollectionView;
    for(CollectionViewCell *cell in self.collectionView.visibleCells){
      
      NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
      //找到某一个具体的section;
      SectionModel *section = self.dataSectionArray[indexPath.section];
      
      //除最后一个cell外都显示删除按钮;
      if (indexPath.row != section.cellArray.count - 1){
        [cell.deleteButton setHidden:false];
      }
    }
    
    
  }
  else if (CellState == DeleteState){
    
    CellState = NormalState;
    self.editButton.titleLabel.text = @"编辑";
  }
  [self.collectionView reloadData];
  
}


(8)点击每一个删除按钮:

- (void)deleteCellButtonPressed: (id)sender{
  CollectionViewCell *cell = (CollectionViewCell *)[sender superview];//获取cell
  
  NSIndexPath *indexpath = [self.collectionView indexPathForCell:cell];//获取cell对应的indexpath;
  
  //删除cell;
  SectionModel *sec = [self.dataSectionArray objectAtIndex:indexpath.section];
  [sec.cellArray removeObjectAtIndex:indexpath.row];
  
  [self.collectionView reloadData];
  
  NSLog(@"删除按钮,section:%ld ,   row: %ld",(long)indexpath.section,(long)indexpath.row);
}


(9)以上为核心代码实现,其他部分的源代码可以从Github上下载。实现效果如下:






     总结,我会持续对CollectionView的使用进行更新,并实现其他复杂实用的效果。请大家不断关注。



最近开源的iOS应用,高仿印象笔记  https://github.com/chenyufeng1991/iOS-Oncenote 。欢迎大家点赞并关注项目进度。也可以安装到手机上试玩哦。

github主页:https://github.com/chenyufeng1991  。欢迎大家访问!


©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页