Yoona
背景
最近產(chǎn)品部門提了一點(diǎn)需求荧嵌,修改了一下“選擇收貨時(shí)間”頁(yè)面呛踊,我也因此回顧了一下前年(16年)寫的代碼指蚜,不得不說鸽扁,太臭了苟呐。
詳情
如圖:
這里面有個(gè)溫馨提示view:
展示數(shù)據(jù)來自后臺(tái)低斋,這里只是一條數(shù)據(jù),其實(shí)有可能是多條數(shù)據(jù)蜻底,如:
多條數(shù)據(jù)
16年的做法
那個(gè)時(shí)候我對(duì)MVC的理解還不到位骄崩,這種模塊view我都是一口氣寫到控制器里的。
或許你覺得這個(gè)view并不復(fù)雜薄辅,但是寫個(gè)上百行代碼還是沒問題的要拂。
現(xiàn)在的做法
將這個(gè)view看作一個(gè)模塊,然后抽離出來站楚。代碼文件如下:
總共分成了三個(gè)類:
1. CQPickTimeAlertModel
@interface?CQPickTimeAlertModel?:?NSObject
/**?標(biāo)題?*/
@property?(nonatomic,?copy)?NSString?*title;
/**?內(nèi)容?*/
@property?(nonatomic,?copy)?NSString?*desc;
@end
2. CQPickTimeAlertItem
對(duì)應(yīng)一個(gè)model脱惰,它的表現(xiàn)形式如下:
item
.h文件:
@interface?CQPickTimeAlertItem?:?UIView
@property?(nonatomic,?strong)?CQPickTimeAlertModel?*model;
@end
.m文件:
@interface?CQPickTimeAlertItem?()
@property?(nonatomic,?strong)?UILabel?*titleLabel;
@property?(nonatomic,?strong)?UILabel?*descLabel;
@end
@implementation?CQPickTimeAlertItem
-?(instancetype)initWithFrame:(CGRect)frame?{
????if?(self?=?[super?initWithFrame:frame])?{
????????[self?setUpUI];
????}
????return?self;
}
-?(void)setUpUI?{
????self.titleLabel?=?[[UILabel?alloc]?init];
????[self?addSubview:self.titleLabel];
????self.titleLabel.font?=?[UIFont?systemFontOfSize:10];
????self.titleLabel.textColor?=?[UIColor?redColor];
????self.titleLabel.textAlignment?=?NSTextAlignmentCenter;
????self.titleLabel.layer.cornerRadius?=?3;
????self.titleLabel.layer.borderWidth?=?1;
????self.titleLabel.layer.borderColor?=?[UIColor?redColor].CGColor;
????self.descLabel?=?[[UILabel?alloc]?init];
????[self?addSubview:self.descLabel];
????self.descLabel.font?=?[UIFont?systemFontOfSize:12];
????self.descLabel.textColor?=?[UIColor?orangeColor];
????self.descLabel.numberOfLines?=?0;
????[self?bringSubviewToFront:self.titleLabel];
}
-?(void)setModel:(CQPickTimeAlertModel?*)model?{
????_model?=?model;
????self.titleLabel.text?=?_model.title;
????self.descLabel.text??=?_model.desc;
????[self?layoutIfNeeded];
}
-?(void)layoutSubviews?{
????[super?layoutSubviews];
????[self.titleLabel?sizeToFit];
????self.titleLabel.frame?=?CGRectMake(0,?0,?self.titleLabel.frame.size.width?+?6,?self.titleLabel.frame.size.height?+?2);
????//?設(shè)置富文本:首行縮進(jìn)
????NSMutableParagraphStyle?*style?=?[[NSMutableParagraphStyle?alloc]init];
????style.firstLineHeadIndent?=?self.titleLabel.frame.size.width?+?4;
????NSMutableAttributedString?*attrString?=?[[NSMutableAttributedString?alloc]?initWithString:self.descLabel.text];
????[attrString?addAttribute:NSParagraphStyleAttributeName?value:style?range:NSMakeRange(0,?self.titleLabel.text.length)];
????self.descLabel.attributedText?=?attrString;
????self.descLabel.frame?=?CGRectMake(0,?0,?self.frame.size.width,?30);
????[self.descLabel?sizeToFit];
????self.frame?=?CGRectMake(self.frame.origin.x,?self.frame.origin.y,?self.frame.size.width,?CGRectGetMaxY(self.descLabel.frame));
}
@end
3. CQPickTimeAlertView
也就是這整個(gè)的模塊view:
.h文件:
@interface?CQPickTimeAlertView?:?UIView
@property?(nonatomic,?strong)?NSArray?*itemsArray;
@end
.m文件:
@implementation?CQPickTimeAlertView
-?(instancetype)initWithFrame:(CGRect)frame?{
????if?(self?=?[super?initWithFrame:frame])?{
????????[self?setUpUI];
????}
????return?self;
}
-?(void)setUpUI?{
????UILabel?*titleLabel?=?[[UILabel?alloc]?initWithFrame:CGRectMake(5,?5,?100,?30)];
????[self?addSubview:titleLabel];
????titleLabel.text?=?@"溫馨提示";
????titleLabel.font?=?[UIFont?systemFontOfSize:14];
????titleLabel.textColor?=?[UIColor?greenColor];
}
-?(void)setItemsArray:(NSArray?*)itemsArray?{
????_itemsArray?=?itemsArray;
????UIView?*lastView?=?nil;
????for?(int?i?=?0;?i?<?_itemsArray.count;?i?++)?{
????????CQPickTimeAlertItem?*itemView?=?[[CQPickTimeAlertItem?alloc]?init];
????????[self?addSubview:itemView];
????????if?(!lastView)?{
????????????itemView.frame?=?CGRectMake(5,?40,?self.frame.size.width-10,?0);
????????}?else?{
????????????itemView.frame?=?CGRectMake(5,?CGRectGetMaxY(lastView.frame)?+?5,?self.frame.size.width-10,?0);
????????}
????????itemView.model?=?_itemsArray[i];
????????lastView?=?itemView;
????}
????//?調(diào)整自身高度
????self.frame?=?CGRectMake(self.frame.origin.x,?self.frame.origin.y,?self.frame.size.width,?CGRectGetMaxY(lastView.frame)+10);
????//?虛線邊框
????CAShapeLayer?*imaginaryLine?=?[CAShapeLayer?layer];
????imaginaryLine.frame?=?CGRectMake(0,?0,?self.frame.size.width,?self.frame.size.height);
????imaginaryLine.path?=?[UIBezierPath?bezierPathWithRoundedRect:self.bounds?cornerRadius:0].CGPath;
????imaginaryLine.lineWidth?=?1.?/?[[UIScreen?mainScreen]?scale];
????imaginaryLine.lineDashPattern?=?@[@2,?@2];
????imaginaryLine.fillColor?=?[UIColor?clearColor].CGColor;
????imaginaryLine.strokeColor?=?[UIColor?grayColor].CGColor;
????[self.layer?addSublayer:imaginaryLine];
}
@end
注:以上是我demo里的代碼,沒有用任何三方或category窿春,命名也比較隨意拉一,大家就別吐槽了。主要看思路旧乞。
相比16年的代碼有何進(jìn)步蔚润?
極大的減少了C層的代碼,更加簡(jiǎn)潔及優(yōu)雅尺栖。
現(xiàn)在創(chuàng)建這個(gè)模塊只需幾行代碼:
CQPickTimeAlertView?*aview?=?[[CQPickTimeAlertView?alloc]?initWithFrame:CGRectMake(50,?100,?self.view.frame.size.width?-?100,?20)];
[self.view?addSubview:aview];
aview.itemsArray?=?modelsArray;
分層更清晰了修改自然也就更容易了嫡纠。
有用的知識(shí)點(diǎn)
1.首行縮進(jìn):
NSMutableParagraphStyle?*style?=?[[NSMutableParagraphStyle?alloc]init];
style.firstLineHeadIndent?=?self.titleLabel.frame.size.width?+?4;
這個(gè)很關(guān)鍵,要不然處理下面這兩個(gè)label的時(shí)候你可能會(huì)走彎路延赌。
2.虛線邊框
用CAShapeLayer:
CAShapeLayer?*imaginaryLine?=?[CAShapeLayer?layer];
imaginaryLine.frame?=?CGRectMake(0,?0,?self.frame.size.width,?self.frame.size.height);
imaginaryLine.path?=?[UIBezierPath?bezierPathWithRoundedRect:self.bounds?cornerRadius:0].CGPath;
imaginaryLine.lineWidth?=?1.?/?[[UIScreen?mainScreen]?scale];
imaginaryLine.lineDashPattern?=?@[@2,?@2];
imaginaryLine.fillColor?=?[UIColor?clearColor].CGColor;
imaginaryLine.strokeColor?=?[UIColor?grayColor].CGColor;
[self.layer?addSublayer:imaginaryLine];
總結(jié)
看待view要像看待模塊一樣除盏;
對(duì)待裝備要像對(duì)待情人一樣。