IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    给UITableView减肥瘦身

    键盘上的舞者发表于 2016-10-23 09:55:40
    love 0

    UITableView这个玩意儿是经常要用到的,初始化,设置delegate,设置dataSource,然后实现代理方法,数据源方法,然后VC的代码就多了一大堆,是不是感觉好臃肿,看着就不舒服呢?那么就对他进行一下简单的瘦身吧!

    抽出一个类,叫cellDataAdapter,这个类用处很大,是关联Controller和Model以及View的,相当于一个转换器一样。

    //
    //  RDCellDataAdapter.h
    //  UITableViewAnimation
    //
    //  Created by 键盘上的舞者 on 16/10/23.
    //  Copyright © 2016年 键盘上的舞者. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface RDCellDataAdapter : NSObject
    /**
     *  重用标识符
     */
    @property (nonatomic, copy) NSString *cellReuseIdentifier;
    /**
     *  数据
     */
    @property (nonatomic, strong) id data;
    /**
     *  cell的高度
     */
    @property (nonatomic, assign) CGFloat cellHeight;
    /**
     *  cell的类型
     */
    @property (nonatomic, assign) NSInteger cellType;
    /**
     *  便捷构造方法
     *
     *  @param reuseIdentifier 重用标识符
     *  @param data            数据
     *  @param cellHeight      高度
     *  @param cellType        类型
     *
     *  @return cellDataAdapter
     */
    + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)reuseIdentifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType;
    
    @end

    //
    //  RDCellDataAdapter.m
    //  UITableViewAnimation
    //
    //  Created by 键盘上的舞者 on 16/10/23.
    //  Copyright © 2016年 键盘上的舞者. All rights reserved.
    //
    
    #import "RDCellDataAdapter.h"
    
    @implementation RDCellDataAdapter
    
    + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)reuseIdentifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType {
        
        RDCellDataAdapter *adapter = [[[self class] alloc] init];
        adapter.cellReuseIdentifier = reuseIdentifier;
        adapter.data = data;
        adapter.cellHeight = cellHeight;
        adapter.cellType = cellType;
        
        return adapter;
    }
    
    @end

    再抽出一个类CustomCell,继承自UITableViewCell.

    //
    //  RDCustomCell.h
    //  UITableViewAnimation
    //
    //  Created by 键盘上的舞者 on 16/10/23.
    //  Copyright © 2016年 键盘上的舞者. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import "RDCellDataAdapter.h"
    
    @class RDCustomCell;
    
    @protocol RDCustomCellDelegate <NSObject>
    
    @optional
    - (void)customCell:(RDCustomCell *)customCell event:(id)event;
    
    @end
    
    @interface RDCustomCell : UITableViewCell
    /**
     *  代理
     */
    @property (nonatomic, weak) id<RDCustomCellDelegate> delegate;
    /**
     *  cellDataAdapter
     */
    @property (nonatomic, weak) RDCellDataAdapter *cellDataAdapter;
    /**
     *  data
     */
    @property (nonatomic, weak) id data;
    /**
     *  indexPath
     */
    @property (nonatomic, weak) NSIndexPath *indexPath;
    /**
     *  tableview
     */
    @property (nonatomic, weak) UITableView *tableView;
    /**
     *  是否显示
     */
    @property (nonatomic, assign) BOOL display;
    /**
     *  cell配置
     */
    - (void)setupCell;
    /**
     *  构建UI
     */
    - (void)buildSubView;
    /**
     *  cell读取数据
     */
    - (void)loadContent;
    /**
     *  便捷方法构造cellDataAdapter
     *
     *  @param identifier 重用标识符
     *  @param data       data
     *  @param cellHeight cellHeight
     *  @param cellType   cellType
     *
     *  @return cellDataAdapater
     */
    + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)identifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType;
    /**
     *  将cellDataAdapter若引用到cell
     *
     *  @param cellDataAdapter cellDataAdapter
     *  @param data            data
     *  @param indexPath       indexPath
     *  @param tableView       指向的tableView
     */
    - (void)setWeakReferenceWithCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter data:(id)data indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView;
    /**
     *  更新cell高度
     *
     *  @param newHeight 新高度
     *  @param animated  是否开启动画
     */
    - (void)updateCellHeightWithNewHeight:(CGFloat)newHeight animated:(BOOL)animated;
    /**
     *  点击事件
     */
    - (void)selectedEvent;
    /**
     *  通过数据计算cell的高度
     */
    + (CGFloat)heightWithData:(id)data;
    
    @end

    //
    //  RDCustomCell.m
    //  UITableViewAnimation
    //
    //  Created by 键盘上的舞者 on 16/10/23.
    //  Copyright © 2016年 键盘上的舞者. All rights reserved.
    //
    
    #import "RDCustomCell.h"
    
    @implementation RDCustomCell
    
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
        if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
            [self setupCell];
            [self buildSubView];
        }
        return self;
    }
    
    #pragma mark - 由子类重写
    - (void)setupCell {
        
    }
    
    - (void)buildSubView {
        
    }
    
    - (void)loadContent {
        
    }
    
    - (void)selectedEvent {
        
    }
    
    #pragma mark - method
    
    + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)identifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType {
        
        NSString *tmpIdentifier = identifier.length <= 0 ? NSStringFromClass([self class]) : identifier;
        
        return [RDCellDataAdapter cellDataAdapterWithReuseIdentifier:tmpIdentifier data:data cellHeight:cellHeight cellType:cellType];
    }
    
    + (CGFloat)heightWithData:(id)data {
        return 0.f;
    }
    
    - (void)setWeakReferenceWithCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter data:(id)data indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView {
        
        _cellDataAdapter = cellDataAdapter;
        _data = data;
        _indexPath = indexPath;
        _tableView = tableView;
        
    }
    
    - (void)updateCellHeightWithNewHeight:(CGFloat)newHeight animated:(BOOL)animated {
        if (_tableView && _cellDataAdapter) {
            if (animated) {
                _cellDataAdapter.cellHeight = newHeight;
                [_tableView beginUpdates];
                [_tableView endUpdates];
            } else {
                _cellDataAdapter.cellHeight = newHeight;
                [_tableView reloadData];
            }
        }
    }
    
    @end

    根据自己的项目去增加或者删减。

    给UITableView增加一个category

    //
    //  UITableView+CellClass.h
    //  UITableViewAnimation
    //
    //  Created by 键盘上的舞者 on 16/10/23.
    //  Copyright © 2016年 键盘上的舞者. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    @class RDCustomCell;
    @class RDCellDataAdapter;
    
    @interface CellClassType : NSObject
    
    @property (nonatomic, copy) NSString *classString;
    @property (nonatomic, copy) NSString *reuseIdentifier;
    
    + (instancetype)cellClassTypeWithClassString:(NSString *)classString reuseIdentifier:(NSString *)reuseIdentifier;
    
    @end
    
    NS_INLINE CellClassType *cellClass(NSString *classString, NSString *reuseIdentifier) {
        return [CellClassType cellClassTypeWithClassString:classString reuseIdentifier:reuseIdentifier.length <= 0 ? classString : reuseIdentifier];
    }
    
    @interface UITableView (CellClass)
    
    - (void)registerCellClass:(NSArray <CellClassType *> *)cellClass;
    
    - (RDCustomCell *)dequeueAndLoadContentFromCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter indexPath:(NSIndexPath *)indexPath;
    
    @end

    //
    //  UITableView+CellClass.m
    //  UITableViewAnimation
    //
    //  Created by 键盘上的舞者 on 16/10/23.
    //  Copyright © 2016年 键盘上的舞者. All rights reserved.
    //
    
    #import "UITableView+CellClass.h"
    #import "RDCellDataAdapter.h"
    #import "RDCustomCell.h"
    
    @implementation CellClassType
    
    + (instancetype)cellClassTypeWithClassString:(NSString *)classString reuseIdentifier:(NSString *)reuseIdentifier {
        CellClassType *classType = [[[self class] alloc] init];
        classType.classString = classString;
        classType.reuseIdentifier = reuseIdentifier;
        return classType;
    }
    
    @end
    
    @implementation UITableView (CellClass)
    
    - (void)registerCellClass:(NSArray<CellClassType *> *)cellClass {
        for (int i = 0; i < cellClass.count; i++) {
            CellClassType *type = cellClass[i];
            [self registerClass:NSClassFromString(type.classString) forCellReuseIdentifier:type.reuseIdentifier];
        }
    }
    
    - (RDCustomCell *)dequeueAndLoadContentFromCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter indexPath:(NSIndexPath *)indexPath {
        RDCustomCell *cell = [self dequeueReusableCellWithIdentifier:cellDataAdapter.cellReuseIdentifier forIndexPath:indexPath];
        [cell setWeakReferenceWithCellDataAdapter:cellDataAdapter data:cellDataAdapter.data indexPath:indexPath tableView:self];
        [cell loadContent];
        
        return cell;
    }
    
    @end

    分离出来之后,你可以这样去使用它。

    1.初始化UITableView

    self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
        self.tableView.delegate = self;
        self.tableView.dataSource = self;
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        //注册
        [self.tableView registerCellClass:@[cellClass(@"TableViewCellTapAnimationCell", nil)]];
        [self.view addSubview:self.tableView];

    使用UITableView的category中的便捷方法,注册cell

    2.设置数据源

    NSArray *tmp = @[[TapAnimationModel modelWithName:@"test1" selected:NO],
                         [TapAnimationModel modelWithName:@"test2" selected:NO],
                         [TapAnimationModel modelWithName:@"test3" selected:NO]];
        
        self.dataArray = [NSMutableArray array];
        for (int i = 0; i < tmp.count; i++) {
            [self.dataArray addObject:[TableViewCellTapAnimationCell cellDataAdapterWithReuseIdentifier:nil data:tmp[i] cellHeight:80 cellType:0]];
        }

    TapAnimationModel为你的数据模型。

    然后向dataArray中添加dataAdapter,data就是TapAnimationModel。

    3.设置delegate和dataSource

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return self.dataArray.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        TableViewCellTapAnimationCell *cell = (TableViewCellTapAnimationCell *)[tableView dequeueAndLoadContentFromCellDataAdapter:self.dataArray[indexPath.row] indexPath:indexPath];
        
        return cell;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        RDCellDataAdapter *adapter = self.dataArray[indexPath.row];
        return adapter.cellHeight;
    }

    tableView dequeueAndLoadContentFromCellDataAdapter:<#(RDCellDataAdapter *)#> indexPath:<#(NSIndexPath *)#>

    这句代码就是来进行cell复用的,具体实现如下。

    - (RDCustomCell *)dequeueAndLoadContentFromCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter indexPath:(NSIndexPath *)indexPath {
        RDCustomCell *cell = [self dequeueReusableCellWithIdentifier:cellDataAdapter.cellReuseIdentifier forIndexPath:indexPath];
        [cell setWeakReferenceWithCellDataAdapter:cellDataAdapter data:cellDataAdapter.data indexPath:indexPath tableView:self];
        [cell loadContent];
        
        return cell;
    }

    在自定义的cell中读取数据。

    - (void)loadContent {
        TapAnimationModel *model = self.cellDataAdapter.data;
        _name.text = model.name;
    }

     

    现在,你在你的controller中使用UITableView,就不需要再像以前那样去写那么大一堆代码,你只需要在VC中设置好你的数据源,向UITableView中注册你自定义的cell,然后在你的自定义cell(继承自CustomCell)中去布局UI,去设置相关的数值就搞定了。



沪ICP备19023445号-2号
友情链接