Apple资讯

当前位置: 爱新闻 > 移动互联网

iOS开发 | 看待view要像看待模块一样

1.jpg

Yoona

背景

最近产品部门提了一点需求,修改了一下“选择收货时间”页面,我也因此回顾了一下前年(16年)写的代码,不得不说,太臭了。

2.jpg

详情

如图:

1.png

这里面有个温馨提示view:

1.png

展示数据来自后台,这里只是一条数据,其实有可能是多条数据,如:

1.png

多条数据

16年的做法

那个时候我对MVC的理解还不到位,这种模块view我都是一口气写到控制器里的。

2.jpg

或许你觉得这个view并不复杂,但是写个上百行代码还是没问题的。

现在的做法

将这个view看作一个模块,然后抽离出来。代码文件如下:

1.png

总共分成了三个类:

1. CQPickTimeAlertModel

@interface CQPickTimeAlertModel : NSObject/** 标题 */@property (nonatomic, copy) NSString *title;/** 内容 */@property (nonatomic, copy) NSString *desc;@end

2. CQPickTimeAlertItem

对应一个model,它的表现形式如下:

1.png

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);        // 设置富文本:首行缩进    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

也就是这整个的模块view:

1.png

.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;    }        // 调整自身高度    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年的代码有何进步?

极大的减少了C层的代码,更加简洁及优雅。

现在创建这个模块只需几行代码:

CQPickTimeAlertView *aview = [[CQPickTimeAlertView alloc] initWithFrame:CGRectMake(50, 100, self.view.frame.size.width - 100, 20)];[self.view addSubview:aview];aview.itemsArray = modelsArray;

分层更清晰了修改自然也就更容易了。

有用的知识点

1.首行缩进:

NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc]init];style.firstLineHeadIndent = self.titleLabel.frame.size.width + 4;

这个很关键,要不然处理下面这两个label的时候你可能会走弯路。

1.png

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];

Demo

https://github.com/CaiWanFeng/BeautifulView

demo效果

总结

看待view要像看待模块一样;

对待装备要像对待情人一样。

1.png

5d3dd8b7ly1fmoj3j28ekg2068097npg.gif

死肥宅.gif

作者:无夜之星辰

链接:https://www.jianshu.com/p/400450be1e37

热门推荐

回到顶部