今天看到《代碼大全第二版》裏面對ADT及類抽象能力的描述讓我受益不淺,查看咱們的iOS項目,立刻就找到了這樣的壞味道(不良好的類接口設計),下面就分享一下個人改進方法。(這裏的類名作了修改,並不是實際項目中的類名)bash
這是一個自定義單元格類:ide
@protocol CustomCellDeletage <NSObject>
- (void)checkDidTouch:(CustomCell *)cell;
@end
@interface CustomCell : UITableViewCell
@property (nonatomic, weak)id<CustomCellDeletage> delegate;
@property (nonatomic, retain)UIButton * checkBtn;
//這裏直接暴露了類的成員變量細節,致使類對自身內部控制的鬆動,按鈕的狀態改變將難以追蹤,而且這個類和按鈕對象如何使用也會讓調用方摸不着頭腦,此次的改動將以此爲重
@end
@implementation CustomCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
_checkBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_checkBtn addTarget:self action:@selector(checkBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
//...省略部分代碼
}
return self;
}
- (void)checkBtnPressed:(id)sender {
// 切換選中狀態
_checkBtn.selected = !_checkBtn.selected;
if (self.delegate && [self.delegate respondsToSelector:@selector(checkDidTouch:)]) {
[self.delegate checkDidTouch:self];
}
}
複製代碼
外部Controller調用:函數
cell.checkBtn.selected = [self isChecked:orderDict[@"orderId"]];
複製代碼
外部Controller回調:ui
#pragma mark CustomCellDeletage ---- 點擊選擇按鈕事件
- (void)checkDidTouch:(CustomCell *)cell {
// 若是是選中狀態,就添加 反之這移除
if (cell.checkBtn.selected) {
[self.checkArray addObject:cell.orderDict];
} else {
[self.checkArray removeObject:cell.orderDict];
}
[self updateViewInfo];
}
複製代碼
若是數據類型發生改變,你只需在一處修改而不會影響程序的其他部分。例如這裏若是由UIButton類型變爲UISwitch,應只須要改動接口的具體實現,而不影響接口調用方atom
例如這裏後面改進了類的接口爲selectOn和selectOff一組更具說明意義的方法spa
例如這裏cell單元格類,應提供選中單元格和取消選中單元格的接口,而不是直接暴露成員變量設計
把對按鈕的操縱隔離到一組子程序裏,爲須要操做按鈕的其它程序部分提供更好的抽象層,同時能夠在針對按鈕屬性狀態的操做發生變化時提供一層保護。 像在現實世界中那樣操做實體,而不用在底層實現上操做它code
@protocol CustomCellDeletage <NSObject>
- (void)customCellDidSelectOn:(CustomCell *)cell;
- (void)customCellDidSelectOff:(CustomCell *)cell;
@end
@interface CustomCell : UITableViewCell
@property (nonatomic, weak)id<CustomCellDeletage> delegate;
- (void)selectOn;
- (void)selectOff;
@end
@interface CustomCell ()
@property (nonatomic, strong)UIButton * checkBtn;
@end
@implementation CustomCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
_checkBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_checkBtn addTarget:self action:@selector(checkBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
//...省略部分代碼
}
return self;
}
- (void)checkBtnPressed:(id)sender {
if (_checkBtn.selected) {
[self selectOff];
if (self.delegate && [self.delegate respondsToSelector:@selector(customCellDidSelectOff:)]) {
[self.delegate customCellDidSelectOff:self];
}
} else {
[self selectOn];
if (self.delegate && [self.delegate respondsToSelector:@selector(customCellDidSelectOn:)]) {
[self.delegate customCellDidSelectOn:self];
}
}
}
- (void)selectOn {
_checkBtn.selected = YES;
}
- (void)selectOff {
_checkBtn.selected = NO;
}
@end
複製代碼
外部Controller調用:對象
if ([self isChecked:orderDict[@"orderId"]]) {
[cell selectOn];
} else {
[cell selectOff];
}
複製代碼
外部Controller回調:接口
#pragma mark <CustomCellDelegate>
- (void)customCellDidSelectOn:(CustomCell *)cell {
[self.checkArray addObject:cell.orderDict];
[self updateViewInfo];
}
- (void)customCellDidSelectOff:(CustomCell *)cell {
[self.checkArray removeObject:cell.orderDict];
[self updateViewInfo];
}
複製代碼
勿以惡小而爲之,勿以善小而不爲