概念
封裝:提供可以調(diào)用的接口含思,隱藏具體實現(xiàn)方案
繼承:子類擁有父類的成員變量和方法崎弃,可以較大程度減少代碼的重復(fù)率
多態(tài):父類指針指向子類對象(實例對象調(diào)用的方法會尋找到真實的類進(jìn)行調(diào)用)
應(yīng)用
封裝一個常用的UITableView為例子
-
普通的tableView復(fù)用代碼
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對象都需要寫這么一大段代碼甘晤,那么是否可以把這些代碼復(fù)用起來(如果WCBaseTableViewCell在多個控制器中使用到,那么就會使得控制器會有很多重復(fù)的代碼)饲做,于是线婚,我們想到了類方法來進(jìn)行對象的實例化,方法如下:
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;
}
總結(jié)
以上的普通的tableView復(fù)用代碼和UITableViewCell的初步封裝結(jié)果是一致的盆均,使用了工廠方法塞弊,將一部分在控制器中常使用的代碼放到了cell里面,使得控制器的代碼更加易讀和簡潔泪姨,而WCBaseTableViewCell類中的這一部分代碼游沿,提供了接口供外部使用聲明變量,這驴娃,就是封裝奏候。
-
UITableViewCell的二次封裝(進(jìn)階-多態(tài)和繼承)
從以上的方法來看,是將原本應(yīng)該在VC中的cell的實例化的代碼封裝到了cell里作為類方法來使用唇敞,這解決了以下問題:在不同地方用到相同的cell的時候需要寫一大段的代碼進(jìn)行變量的聲明蔗草。但是!這同樣會有重復(fù)代碼的問題疆柔,比如咒精,不同的cell,一樣會需要寫一大段類似的類方法進(jìn)行聲明旷档,如下
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ù)的寫模叙,那么,有沒有方法可以避免問題的產(chǎn)生呢鞋屈?范咨!當(dāng)然有,這個時候厂庇,我們的繼承渠啊,就發(fā)揮出了獨特的作用。我們可以設(shè)計一個基類(基類擁有一個公共的類方法)权旷,讓其他的子類繼承這個基類替蛉,這樣就可以避免重復(fù)寫類似的代碼。那么拄氯,唯一要解決的兩個:
- 基類類方法里的cell標(biāo)識符如何根據(jù)不同的子類聲明不同
- 基類類方法的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中調(diào)用如下
ViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WCThirdTableViewCell *cell = [WCThirdTableViewCell wc_baseTableViewCellWithTableView:tableView];
return cell;
}
效果如下
后續(xù)如有要的新的cell镣煮,只需要繼承WCBaseTableViewCell,然后重寫prepareUI方法即可鄙麦。
此方式的swift版本在后續(xù)更新