美文网首页
iOS开发 | 看待view要像看待模块一样

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

作者: 软件iOS开发 | 来源:发表于2018-01-04 10:55 被阅读2次

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

    总结

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

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

    相关文章

      网友评论

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

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