今天看到《代码大全第二版》里面对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];
}
复制代码
勿以恶小而为之,勿以善小而不为