UITableVIew与UICollectionView带动画删除cell时崩溃的处理

大憨熊 提交于 2020-03-18 05:08:13

UITableVIew与UICollectionView带动画删除cell时崩溃的处理

-会崩溃的原因是因为没有处理好数据源与cell之间的协调关系-

效果:

tableView的源码:

ModelCell.h + ModelCell.m

//
//  ModelCell.h
//  Set
//
//  Created by YouXianMing on 14/11/24.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>
@class ModelCell;

@protocol ModelCellDelegate <NSObject>
@optional
- (void)modelCellButton:(ModelCell *)cell;
@end

@interface ModelCell : UITableViewCell

@property (nonatomic, weak)   id<ModelCellDelegate>  delegate;

@property (nonatomic, strong) UILabel *title;

@end
//
//  ModelCell.m
//  Set
//
//  Created by YouXianMing on 14/11/24.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "ModelCell.h"

@implementation ModelCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        UIButton *button = [[UIButton alloc] initWithFrame:self.bounds];
        [button addTarget:self
                   action:@selector(buttonsEvent:)
         forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button];
        
        _title               = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 200, 44)];
        _title.textAlignment = NSTextAlignmentLeft;
        _title.font          = [UIFont fontWithName:@"HelveticaNeue-Thin" size:17.f];
        [self addSubview:_title];
    }
    
    return self;
}

- (void)buttonsEvent:(UIButton *)button {
    if (_delegate && [_delegate respondsToSelector:@selector(modelCellButton:)]) {
        [_delegate modelCellButton:self];
    }
}

@end

控制器源码:

//
//  ViewController.m
//  Set
//
//  Created by YouXianMing on 14/11/24.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "ViewController.h"
#import "ModelCell.h"

@interface ViewController ()<UITableViewDelegate, UITableViewDataSource, ModelCellDelegate>
@property (nonatomic, strong) UITableView    *tableView;
@property (nonatomic, strong) NSMutableArray *dataArray;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
 
    // 初始化数据源
    _dataArray = [NSMutableArray array];
    [_dataArray addObject:@"YouXianMing"];
    [_dataArray addObject:@"Job"];
    [_dataArray addObject:@"NoZuoNoDie"];
    [_dataArray addObject:@"XiaoMing"];
    [_dataArray addObject:@"Smith"];
    [_dataArray addObject:@"K.K.K."];

    // 初始化tableView
    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds
                                              style:UITableViewStylePlain];
    _tableView.delegate       = self;
    _tableView.dataSource     = self;
    _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    [self.view addSubview:_tableView];
    [_tableView registerClass:[ModelCell class] forCellReuseIdentifier:@"YouXianMing"];
}

#pragma mark - 代理
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [_dataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ModelCell *cell = [tableView dequeueReusableCellWithIdentifier:@"YouXianMing"];
    cell.delegate   = self;
    cell.title.text = _dataArray[indexPath.row];
    
    return cell;
}

- (void)modelCellButton:(ModelCell *)cell {
    // 获取到cell的indexPath
    NSIndexPath *indexPath = [_tableView indexPathForCell:cell];
    
    // 删除数据源
    [_dataArray removeObjectAtIndex:indexPath.row];
    
    // 执行删除动画效果
    [_tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}

@end

UICollectionView源码:

ModelCell.h + ModelCell.m

//
//  ModelCell.h
//  collection
//
//  Created by YouXianMing on 14/11/25.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>
@class ModelCell;

@protocol ModelCellDelegate <NSObject>
@optional
- (void)modelCellEvent:(ModelCell *)cell;
@end

@interface ModelCell : UICollectionViewCell

@property (nonatomic, weak)   id<ModelCellDelegate>  delegate;
@property (nonatomic, strong) UILabel               *title;

@end
//
//  ModelCell.m
//  collection
//
//  Created by YouXianMing on 14/11/25.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "ModelCell.h"

@implementation ModelCell

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _title               = [[UILabel alloc] initWithFrame:self.bounds];
        _title.textAlignment = NSTextAlignmentCenter;
        [self addSubview:_title];
        self.layer.borderWidth = 1.f;
        
        UIButton *button = [[UIButton alloc] initWithFrame:self.bounds];
        [button addTarget:self
                   action:@selector(buttonEvent:)
         forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button];
    }
    return self;
}

- (void)buttonEvent:(UIButton *)button {
    if (_delegate && [_delegate respondsToSelector:@selector(modelCellEvent:)]) {
        [_delegate modelCellEvent:self];
    }
}

@end

CellLayout.h + CellLayout.m

//
//  CellLayout.h
//  collection
//
//  Created by YouXianMing on 14/11/25.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface CellLayout : UICollectionViewFlowLayout

@end
//
//  CellLayout.m
//  collection
//
//  Created by YouXianMing on 14/11/25.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "CellLayout.h"

@implementation CellLayout

- (instancetype)init {
    self = [super init];
    if (self) {
        self.itemSize                = CGSizeMake([UIScreen mainScreen].bounds.size.width / 3.f, 140); // 单元格尺寸
        self.sectionInset            = UIEdgeInsetsMake(0, 0, 0, 0);                                   // 单元格边缘
        self.minimumInteritemSpacing = 0;                                                              // 横排单元格最小间隔
        self.minimumLineSpacing      = 0;                                                              // 单元格最小行间距
    }
    return self;
}

@end

控制器源码:

//
//  ViewController.m
//  collection
//
//  Created by YouXianMing on 14/11/25.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "ViewController.h"
#import "CellLayout.h"
#import "ModelCell.h"

@interface ViewController ()<UICollectionViewDataSource, UICollectionViewDelegate, ModelCellDelegate>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) NSMutableArray   *dataArray;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化数据源
    _dataArray = [NSMutableArray array];
    [_dataArray addObject:@"YouXianMing"];
    [_dataArray addObject:@"Job"];
    [_dataArray addObject:@"NoZuoNoDie"];
    [_dataArray addObject:@"XiaoMing"];
    [_dataArray addObject:@"Smith"];
    [_dataArray addObject:@"K.K.K."];
    
    // 创建出UICollectionView
    _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds
                                         collectionViewLayout:[CellLayout new]];
    _collectionView.backgroundColor = [UIColor whiteColor];
    _collectionView.delegate        = self;
    _collectionView.dataSource      = self;
    [_collectionView registerClass:[ModelCell class] forCellWithReuseIdentifier:@"YouXianMing"];
    [self.view addSubview:_collectionView];
}

#pragma mark - 代理
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return [_dataArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    ModelCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"YouXianMing"
                                                                forIndexPath:indexPath];
    cell.title.text = _dataArray[indexPath.row];
    cell.delegate   = self;
    
    return cell;
}
- (void)modelCellEvent:(ModelCell *)cell {
    // 获取到cell的indexPath
    NSIndexPath *indexPath = [_collectionView indexPathForCell:cell];
    
    // 删除数据源
    [_dataArray removeObjectAtIndex:indexPath.row];
    
    // 执行删除动画效果
    [_collectionView deleteItemsAtIndexPaths:@[indexPath]];
}

@end

分析:

注意:

1. 先取得cell的indexPath

2. 删除数据源

3. 执行删除cell的操作,带动画

执行delete操作的时候,并不会刷新数据源,不会执行reloadData,注意.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!