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


    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,注意.

  • 相关阅读:
    三层架构
    【Leetcode】Linked List Cycle II
    [Angular] @ContentChild with Directive ref
    [PostgreSQL] Use Foreign Keys to Ensure Data Integrity in Postgres
    [PostgreSQL] Ensure Uniqueness in Postgres
    [RxJS] Hot Observable, by .share()
    [RxJS] Implement pause and resume feature correctly through RxJS
    [RxJS] Replace zip with combineLatest when combining sources of data
    [RxJS] Use takeUntil instead of manually unsubscribing from Observables
    [RxJS] Convert RxJS Subjects to Observables
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4121774.html
Copyright © 2020-2023  润新知