iOS封裝、繼承、多態(tài)項目應用-tableview(OC篇)

概念

封裝:提供可以調用的接口,隱藏具體實現方案
繼承:子類擁有父類的成員變量和方法,可以較大程度減少代碼的重復率
多態(tài):父類指針指向子類對象(實例對象調用的方法會尋找到真實的類進行調用)

應用

封裝一個常用的UITableView為例子

  • 普通的tableView復用代碼
    WCBaseTableViewCell
@implementation WCBaseTableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self prepareUI];
    }
    return self;
}

- (void)prepareUI {
    self.backgroundColor = [UIColor colorWithRed:random() % 255 / 255.0  green:random() % 255 / 255.0 blue:random() % 255 / 255.0 alpha:1.0];
}

@end

ViewController

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *ID = @"WCBaseTableViewCell";
    WCBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[WCBaseTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

效果

*效果*


  • UITableViewCell的初步封裝
    從上面的tableViewCell創(chuàng)建的過程來看(如下)
static NSString *ID = @"WCBaseTableViewCell";
    WCBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[WCBaseTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;

既然每次實例化一個cell對象都需要寫這么一大段代碼,那么是否可以把這些代碼復用起來(如果WCBaseTableViewCell在多個控制器中使用到,那么就會使得控制器會有很多重復的代碼),于是,我們想到了類方法來進行對象的實例化,方法如下:
WCBaseTableViewCell.h

@interface WCBaseTableViewCell : UITableViewCell

+ (instancetype)wc_baseTableViewCellWithTableView:(UITableView *)tableView;

@end

WCBaseTableViewCell.m

@implementation WCBaseTableViewCell

+ (instancetype)wc_baseTableViewCellWithTableView:(UITableView *)tableView {
    static NSString *ID = @"WCBaseTableViewCell";
    WCBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[WCBaseTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self prepareUI];
    }
    return self;
}

- (void)prepareUI {
    self.backgroundColor = [UIColor colorWithRed:random() % 255 / 255.0  green:random() % 255 / 255.0 blue:random() % 255 / 255.0 alpha:1.0];
}

@end
  • ViewController中的使用*
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    WCBaseTableViewCell *cell = [WCBaseTableViewCell wc_baseTableViewCellWithTableView:tableView];
    return cell;
}

總結
以上的普通的tableView復用代碼UITableViewCell的初步封裝結果是一致的,使用了工廠方法,將一部分在控制器中常使用的代碼放到了cell里面,使得控制器的代碼更加易讀和簡潔,而WCBaseTableViewCell類中的這一部分代碼,提供了接口供外部使用聲明變量,這,就是封裝。


  • UITableViewCell的二次封裝(進階-多態(tài)和繼承)
    從以上的方法來看,是將原本應該在VC中的cell的實例化的代碼封裝到了cell里作為類方法來使用,這解決了以下問題:在不同地方用到相同的cell的時候需要寫一大段的代碼進行變量的聲明。但是!這同樣會有重復代碼的問題,比如,不同的cell,一樣會需要寫一大段類似的類方法進行聲明,如下
    WCBaseTableViewCell
@implementation WCFirstTableViewCell

+ (instancetype)wc_firstTableViewCellWithTableView:(UITableView *)tableView {
    static NSString *ID = @"WCFirstTableViewCell";
    WCFirstTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[WCFirstTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self prepareUI];
    }
    return self;
}

- (void)prepareUI {
    
}

@end
@implementation WCSecondTableViewCell

+ (instancetype)wc_secondTableViewCellWithTableView:(UITableView *)tableView {
    static NSString *ID = @"WCSecondTableViewCell";
    WCSecondTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[WCSecondTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self prepareUI];
    }
    return self;
}

- (void)prepareUI {
    
}

@end

這是不是又碰到了和上面一樣的問題-類似的代碼需要重復的寫,那么,有沒有方法可以避免問題的產生呢?!當然有,這個時候,我們的繼承,就發(fā)揮出了獨特的作用。我們可以設計一個基類(基類擁有一個公共的類方法),讓其他的子類繼承這個基類,這樣就可以避免重復寫類似的代碼。那么,唯一要解決的兩個:

  1. 基類類方法里的cell標識符如何根據不同的子類聲明不同
  2. 基類類方法的init類如何顯示為字類
    以上兩個問題剛好可以用多態(tài)來解決!
    WCBaseTableViewCell.m
@implementation WCBaseTableViewCell

+ (instancetype)wc_baseTableViewCellWithTableView:(UITableView *)tableView {
    NSString *ID = NSStringFromClass(self.class);
    WCBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[self.class alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self prepareUI];
    }
    return self;
}

- (void)prepareUI {
}

@end

WCBaseTableViewCell.h

@interface WCBaseTableViewCell : UITableViewCell

+ (instancetype)wc_baseTableViewCellWithTableView:(UITableView *)tableView;
- (void)prepareUI;

@end

這樣,一個基類就完成了,實戰(zhàn)如下
聲明一個繼承這個基類WCBaseTableViewCell的類
WCThirdTableViewCell.h

#import "WCBaseTableViewCell.h"

NS_ASSUME_NONNULL_BEGIN

@interface WCThirdTableViewCell : WCBaseTableViewCell

@end

NS_ASSUME_NONNULL_END

WCThirdTableViewCell.m

@implementation WCThirdTableViewCell

- (void)prepareUI {
    [super prepareUI];
    self.backgroundColor = [UIColor colorWithRed:random() % 255 / 255.0 green:random() % 255 / 255.0 blue:random() % 255 / 255.0 alpha:1.0];
}

@end

在VC中調用如下
ViewController

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    WCThirdTableViewCell *cell = [WCThirdTableViewCell wc_baseTableViewCellWithTableView:tableView];
    return cell;
}

效果如下


效果圖

后續(xù)如有要的新的cell,只需要繼承WCBaseTableViewCell,然后重寫prepareUI方法即可。


此方式的swift版本在后續(xù)更新

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容