美文网首页iOS开发实用技术ios实用开发技巧iOS大咖
iOS开发 | 看待view要像看待模块一样

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

作者: 无夜之星辰 | 来源:发表于2018-01-02 17:19 被阅读606次
Yoona

背景

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

详情

如图:

这里面有个温馨提示view:

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

多条数据

16年的做法

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

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

现在的做法

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


总共分成了三个类:

1. CQPickTimeAlertModel

@interface CQPickTimeAlertModel : NSObject

/** 标题 */
@property (nonatomic, copy) NSString *title;
/** 内容 */
@property (nonatomic, copy) NSString *desc;

@end

2. CQPickTimeAlertItem

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


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:


.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的时候你可能会走弯路。

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要像看待模块一样;
对待装备要像对待情人一样。

死肥宅.gif

相关文章

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

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

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

    Yoona 背景 最近产品部门提了一点需求,修改了一下“选择收货时间”页面,我也因此回顾了一下前年(16年)写的代...

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

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

  • 单位如家

    如果你是小草,单位就是你的地。家庭离不开你,而你离不了单位。没有单位,你,什么也不是。要像看待家一样看待单位,要像...

  • 随笔二

    文章忌俗滥,生活也要忌俗滥,为什么人就不能像看待一只绣花鞋一样看待女阴?为什么人就不能像看待一匹马一样看待一只阴茎?

  • iOS runtime方法交换防按钮暴力点击

    在iOS 开发的过程,离不开按钮.自己开发的程序当孩子看待,测试当前男友看待,所以在测试的过程中,暴力点击按钮是无...

  • 像看待钻石一样,看待每一样你要描述的事物

    9/100 像看待钻石一样,看待每一样你要描述的事物,难道是说,把所有的东西都当成超级贵的“一颗永流传”吗?emm...

  • 像爱家一样爱着单位——《我的单位观》学习体会

    学习了《我的单位观》,感受颇深。我们平时就要像作者说的那样,把单位看成家。像看待家一样看待单位,像爱护家一...

  • 劝退iOS开发如何看待?

    近日在知乎看到一个提问?如今想学iOS开发的为什么总有人劝退?说学完后悔一辈子? 我们来看看都怎么回答的! 这个回...

  • 固有思维的限制

    我们常常带有我执的想法,来看待世界,看待事物,看待他人,看待自己。心要时常打开,不然就像牢笼一样,监狱一样,围墙一...

网友评论

  • 奔跑的鸿:你好,文章中CQPickTimeAlertView *aview = [[CQPickTimeAlertView alloc] initWithFrame:CGRectMake(50, 100, self.view.frame.size.width - 100, 20)];
    这个控件高度20是不是随便给的?真正的CQPickTimeAlertView高度在内部的- (void)setItemsArray:(NSArray *)itemsArray 设定了?
    无夜之星辰:是的,实际高度是根据array决定的
  • ebay_Happy:你其实可以放在一起,富文本的形式单独设置 最前面的标题。在计算一下高度就可以。你的方法也不错
    无夜之星辰:给部分文本设置边框?我开始也想这样,但没有找到相关方法。
  • PGOne爱吃饺子:楼主写文章质量越来越好了,真的思想太重要了,加油,继续写出好文章
    无夜之星辰:快师傅和你一起成长:sunglasses:
  • 伯陽:做开发要“”用耳去听。用心去斩。“”
    无夜之星辰:那些年GSD告诉我们的道理。
  • 4c0ed4bd48d8:这个首行缩进有什么使用限制么 为什么我写了没用
    无夜之星辰:是富文本哦,你可以看下demo
  • TinXie:持續跟著大哥的腳步走!
  • 天然酱油:整体来说还可以,开发悟性很重要 哈哈哈哈
    无夜之星辰:要多思考:smile:

本文标题:iOS开发 | 看待view要像看待模块一样

本文链接:https://www.haomeiwen.com/subject/qaafnxtx.html