美文网首页
再看SnapKit

再看SnapKit

作者: 桂宁813 | 来源:发表于2018-06-01 13:00 被阅读37次

    连续两个多月高强度的工作,每天几乎加班到8点才下班,项目在今天上午终于是提交到 App Store 了。整个人瞬时如释重负,但却有种空虚感,不知道做什么了。再看下SnapKit吧。发现之前一直认为就那么用来设置约束即可,没留意到的地方还挺多。下面分别概述下。

    一、inset 和 offset

    相信大部分小伙伴们都是使用 offset 来控制边距的吧。

    cciView.snp.makeConstraints { (make) in
        make.top.equalTo(researchView.snp.bottom).offset(kHeight.d10)
        make.left.equalTo(10)
        make.right.equalTo(-10)
        make.bottom.equalTo(bottomView.snp.bottom)
    }
    

    其实 offset 使用的是绝对值,尤其是设置右、下约束的时候,子控件相对于父控件都需要加-号。这一点使用久了,和苹果的 xib 比起来,或多或少觉得有点不太合理。其实该框架是有 inset 来抽象控制的。下面贴下框架的源码:

    public class ConstraintMakerEditable: ConstraintMakerPriortizable {
        
        @discardableResult
        public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
            self.description.multiplier = amount
            return self
        }
        
        @discardableResult
        public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
            return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue)
        }
        
        @discardableResult
        public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable {
            self.description.constant = amount.constraintOffsetTargetValue
            return self
        }
        
        @discardableResult
        public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable {
            self.description.constant = amount.constraintInsetTargetValue
            return self
        }
        
    }
    

    使用 inset,之前的代码就可以简化成这样(只是举例):

       make.top.equalTo(researchView.snp.bottom).offset(kHeight.d10)
            make.left.equalTo(10)
            make.right.equalToSuperview().inset(10)
            make.bottom.equalTo(bottomView.snp.bottom)
        }
    

    总结下来就是:在描述 view 与 superview 关系时,应该使用 inset,而描述 view 与同一层级的其它 view 时,应该使用 offset。

    二、ConstraintConstantTarget

    在布局 view 的时候,一般来说设计师都会给 content 一个统一的边距,类似于 html 中的 padding,在构建约束时我们经常会把这个 padding 分散到各处。但事实上,将 padding 分散去处理是一件很糟糕的事情,代码不美观是其次,最重要的是后期维护起来费时费力,更好的方式是使用已有的抽象 UIEdgeInsets。

    在调用 equalTo, offset 或者 inset 传入数值时,我们会发现传入的参数类型实际上只有 ConstraintConstantTarget,这是一个协议,SnapKit 把它作为一个类簇在使用,通过一个方法将它转化为 CGFloat 来作为 constraint 的 constant。

    UIEdgeInsets 也遵循了这个协议,所以我们可以更加优雅地去处理边距:

    //  如果视觉稿中所有的页面的左右边距都遵循左右距离相同,该属性可以改为全局属性。
    let containerInsets = UIEdgeInsets(top: 5, left: 15, bottom: 5, right:15)
    
    container.addSubview(a)
    container.addSubview(b)
    
    a.snp.makeConstraints {
        $0.top.left.right.equalToSuperview().inset(containerInsets)
    }
    
    b.snp.makeConstraints {
        $0.top.equalTo(a.snp.bottom).offset(5)
        $0.left.bottom.right.equalToSuperview().inset(containerInsets)
    }
    

    这样,后期修改起来会很容易,代码也简洁了很多。另外 CGPoint 和 CGSize 也遵循了这个协议,大家可以去研究下更多有趣的用法,例如 size.equalTo(20)。

    三、修改约束尽量用 updateConstraints

    如果要更新布局约束,小弟之前的做法是仿照苹果,用局部变量来引用,然后更新。如下:

    // 局部变量保存约束属性
    private var bottomViewConsT: Constraint?
    
    // 展示 view 时更新底部约束
    bottomViewConsT?.update(offset: -tmpBottomConsH)
    UIView.animate(withDuration: kTime.duration, animations: {[weak self] in
            self?.layoutIfNeeded()
    }) {  (_) in
    }
    
    // 设置约束
    bottomView.snp.makeConstraints { (make) in
        make.left.right.equalTo(self).offset(0)
        make.height.equalTo(frame.height * 0.35)
        bottomViewConsT = make.top.equalTo(self.snp.bottom).offset(0).constraint
        }
    
    // 隐藏 view 时更新底部约束
    bottomViewConsT?.update(offset: 0)
      UIView.animate(withDuration: 0.1, animations: { [weak self] in
        self?.layoutIfNeeded()
    }) { [weak self] (_) in
        self?.removeFromSuperview()
    }
    

    其实可以改为:

    // 展示 view 时更新底部约束
    bottomView.snp.updateConstraints { (make) in
        make.top.equalTo(self.snp.bottom).inset(0)
    }
    
    // 设置约束
    bottomView.snp.makeConstraints { (make) in
        make.left.right.equalTo(self).offset(0)
        make.height.equalTo(frame.height * 0.35)
        bottomViewConsT = make.top.equalTo(self.snp.bottom).offset(0).constraint
    }
    // ……
    

    这么做的好处就是语法更简洁一致,让约束表现得更像是 view 的属性。但缺点也很明显,只能更新 constant。

    暂时就这些吧(^_^)~~~

    相关文章

      网友评论

          本文标题:再看SnapKit

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