美文网首页iOS开发杂货铺iOS猛码计划ios开发 小控件
如何处理一个tableView中同种model多种cell相同逻

如何处理一个tableView中同种model多种cell相同逻

作者: 无夜之星辰 | 来源:发表于2017-11-13 16:02 被阅读721次
iu的图片用完了,用我允的代替一下

这是购物车页面:


有4种cell:
1.一般商品cell
2.带赠品的商品cell
3.满赠商品cell
4.补货中商品cell

一般来说,有多少种cell就要自定义多少种cell,但是这4种cell又有相同的逻辑处理,如点击商品图片进入商品详情页。如何处理既不会让代码显得啰嗦又不会因为继承导致耦合度变高?

我的做法是先封装一个基类cell,这个cell只封装逻辑处理相关代码

#import <UIKit/UIKit.h>
#import "CQShopCartCellModel.h"

@class CQShopCartGoodsCell;
@protocol CQShopCartGoodsCellDelegate <NSObject>

@optional

/** 选中按钮点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell chooseButtonDidClick:(UIButton *)chooseButton;
/** 加按钮点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell addButtonDidClick:(UIButton *)addButton;
/** 减按钮点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell minusButtonDidClick:(UIButton *)minusButton;
/** 商品图片点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell goodsImageViewDidTap:(UIImageView *)goodsImageView;

@end

@interface CQShopCartGoodsCell : UITableViewCell

@property (nonatomic, weak) id <CQShopCartGoodsCellDelegate> delegate;
@property (nonatomic, strong) CQShopCartCellModel *model;

@end

然后4种cell再继承这个基类cell。

在controller中:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    CQShopCartGoodsCell *goodsCell = [tableView dequeueReusableCellWithIdentifier:@""];
    CQShopCartCellModel *model = nil;
    switch (indexPath.section) {
        case 0: // 普通商品
        {
            model = self.commonGoodsArray[indexPath.row];
            if (goodsCell == nil) {
                if (model.giftsArray.count > 0) {
                    // 有赠品的商品
                    goodsCell = [[CQShopCartHaveGiftGoodsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CQShopcartHaveGiftGoodsCellID];
                } else {
                    // 无赠品的商品
                    goodsCell = [[CQShopCartNoGiftGoodsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CQShopcartNoGiftGoodsCellID];
                }
            }
        }
            break;
            
        case 1: // 满赠商品
        {
            model = self.giftGoodsArray[indexPath.row];
            goodsCell = (goodsCell ?: [[CQShopCartGiftGoodsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CQShopcartGiftGoodsCellID]);
        }
            break;
            
        case 2: // 补货中商品
        {
            model = self.emptyGoodsArray[indexPath.row];
            goodsCell = (goodsCell ?: [[CQShopCartEmptyGoodsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CQShopcartEmptyGoodsCellID]);
        }
            break;
            
        default:
            break;
    }
    goodsCell.model = model;
    goodsCell.delegate = self;
    return goodsCell;
}

一目了然。

欢迎大家说出自己的想法。


补充

详细解释一下。

这是cell对应的文件夹:

商品cell基类的.h文件:

#import <UIKit/UIKit.h>
#import "CQShopCartCellModel.h"

@class CQShopCartGoodsCell;
@protocol CQShopCartGoodsCellDelegate <NSObject>

@optional

/** 选中按钮点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell chooseButtonDidClick:(UIButton *)chooseButton;
/** 加按钮点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell addButtonDidClick:(UIButton *)addButton;
/** 减按钮点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell minusButtonDidClick:(UIButton *)minusButton;
/** 商品图片点击 */
- (void)goodsCell:(CQShopCartGoodsCell *)goodsCell goodsImageViewDidTap:(UIImageView *)goodsImageView;

@end

@interface CQShopCartGoodsCell : UITableViewCell

@property (nonatomic, weak) id <CQShopCartGoodsCellDelegate> delegate;
@property (nonatomic, strong) CQShopCartCellModel *model;

@end

商品cell基类的.m文件没做任何处理。

不带赠品的商品cell(继承自商品cell基类):

#pragma mark - 构造方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        [self setUpUI];
    }
    return self;
}

#pragma mark - UI搭建
/** UI搭建 */
- (void)setUpUI {
    // 根据UI图搭建UI
}

#pragma mark - model 赋值
- (void)setModel:(CQShopCartCellModel *)model {
    super.model = model;
    // 相关赋值
}

#pragma mark - 选中按钮点击
/** 选中按钮点击 */
- (void)chooseButtonClicked:(UIButton *)sender {
    if ([self.delegate respondsToSelector:@selector(goodsCell:chooseButtonDidClick:)]) {
        [self.delegate goodsCell:self chooseButtonDidClick:sender];
    }
}

#pragma mark - 商品图片点击
/** 商品图片点击 */
- (void)goodsImageViewTaped:(UIImageView *)goodsImageView {
    if ([self.delegate respondsToSelector:@selector(goodsCell:goodsImageViewDidTap:)]) {
        [self.delegate goodsCell:self goodsImageViewDidTap:goodsImageView];
    }
}

#pragma mark - 商品“加”按钮点击
/** 商品“加”按钮点击 */
- (void)addButtonClicked:(UIButton *)addButton {
    if ([self.delegate respondsToSelector:@selector(goodsCell:addButtonDidClick:)]) {
        [self.delegate goodsCell:self addButtonDidClick:addButton];
    }
}

#pragma mark - 商品“减”按钮点击
/** 商品“减”按钮点击 */
- (void)minusButtonClicked:(UIButton *)minusButton {
    if ([self.delegate respondsToSelector:@selector(goodsCell:minusButtonDidClick:)]) {
        [self.delegate goodsCell:self minusButtonDidClick:minusButton];
    }
}

注意那几个事件处理

补货中商品cell(还是继承商品cell基类):

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        // UI搭建
        [self setUpUI];
    }
    return self;
}

#pragma mark - UI搭建
/** UI搭建 */
- (void)setUpUI {
    // 根据UI图搭建UI
}

#pragma mark - 赋值model
/** 赋值model */
- (void)setModel:(CQShopCartCellModel *)model {
    super.model = model;
    
    // 相关赋值
}

#pragma mark - 点击图片进入详情页
/** 点击图片进入详情页 */
- (void)goodsImageViewTaped {
    if ([self.delegate respondsToSelector:@selector(goodsCell:goodsImageViewDidTap:)]) {
        [self.delegate goodsCell:self goodsImageViewDidTap:self.goodsImageView];
    }
}

还是注意事件处理

其余两种cell的处理类似

总结

将协议写到基类cell里,在controller中只需对应基类cell的协议就可以了:


这样就避免了写重复的事件处理,并且代码看起很整洁清晰。

2017年11月16日更新

今天才知道,我这种写法就是传说中的抽象基类。

相关文章

网友评论

  • 奔跑的鸿:快师傅,CQShopCartGoodsCell *goodsCell = [tableView dequeueReusableCellWithIdentifier:@""];的Identifier和alloc init的cell的Identifier不一样,这样cell没有复用吧
    无夜之星辰:的确没有复用:sweat_smile: 这里的代码需要改一下
  • 叶熙雯:我也码了!!!
    无夜之星辰:@叶熙雯 不错
  • 标准答案:很清晰,
  • 小暖风:其实就相当于开放了一个接口文件,然后基类去各自实现是吧。
    无夜之星辰:@小暖风 是的,在其他语言里面这种写法叫做抽象基类
  • PGOne爱吃饺子:健身我还理解,男孩子嘛,我有时候也会举哑铃,但是,为啥还练琴啊
    无夜之星辰:@4140d18ee6fc 兴趣而已:smile:
  • licaLicaGao_:码了先,看见允儿跑进来的😂
    无夜之星辰:@licaLicaGao_ 论镇楼图的重要性:smile:
  • ZackDt:我用工厂模型来简单按思路写了下,你可以看看。http://www.jianshu.com/p/6979c7ab098c
    无夜之星辰:你这招可以减少C层的代码,挺6的。
  • 简书坤:这种属于规范接口,可以使用协议的方式来处理
    ```
    @protocol OrderDetailCellShowProtocol<NSObject>

    - (void)setupShowCellStyle;

    @EnD

    ```

    ```
    @interface ApprovedPassCell : UITableViewCell<OrderDetailCellShowProtocol>

    - (void)registQRCodeClickedAction:(void(^)(void))qrCodeAction;

    @EnD
    ```

    如果有点击事件需要规范(同`ApprovedPassCell `注册的点击事件),同样可以放入协议中但是当需要在block中返回的参数不同时,你可能需要缔造一个block返回类来解决(如果某个注册的block是在很异类那就不需要规范了🐷)
    无夜之星辰:你这个是把Protocol专门剔出来的对吧?可以的,我的那个是把Protocol写在基类里的,感觉异曲同工。
  • 小楼东风:同求源码参考,谢谢。
    无夜之星辰:补充了一波,你可以看看。
  • 自在轻梦:大神有源码么,给个参考下咯~ 不胜感激~
    无夜之星辰:我补充了一波,现在应该容易理解了。
  • CepheusSun:快师傅能否教教我
    CepheusSun:@无夜之星辰 多种cell相同逻辑,swift我用protocol
    无夜之星辰:师傅快来指点一波
  • 37e4dd6ddc60:先mark再说
    无夜之星辰:@梦战 不错,mark得很及时:joy:

本文标题:如何处理一个tableView中同种model多种cell相同逻

本文链接:https://www.haomeiwen.com/subject/pvfbmxtx.html