iOS 開發中的得力魯班尺 - SnapKit | 掘金技術徵文

Binboy_王興彬發表於2016-12-20

iOS 開發中的得力魯班尺 - SnapKit | 掘金技術徵文
SnapKit

先來談談何為 DSL

DSL(Domain Specific Language),即領域特定語言,指的是一種針對特定問題的程式語言,與此相對便是 GPL(General Purpose Language),也就是我們平常所用的程式語言,用途更為寬泛。DSL含有建模所需的特定語法和語義,因此可在與問題域相同的抽象層次高效對概念建模。

A specialized computer language designed for a specific task.

—— Wikipedia

軟體開發大師 Martin Fowler 的解讀則更加明晰

DSL 通過在表達能力上做的妥協換取在某一領域內的高效。

舉個栗子,正規表示式(Regex)SQLHTML & CSS,便是 DSL。

那麼,為什麼要先講 DSL,因為 SnapKit 就是針對高效使用 AutoLayout 的 DSL。是的,所以 SnapKit 不僅僅是一個個框架,它是一門程式語言。

安裝 SnapKit

使用 CocoapodsCarthage 可以非常方便地進行安裝,就不多費篇幅了

  • Cocoapods

    pod 'SnapKit'

  • Carthage

    github "SnapKit/SnapKit"

基本使用

在開篇我們知道了 SnapKit 是一門程式語言,並且是一門專門針對高效使用 AutoLayout 的特定語言,因此它被設計得十分簡便易用。

iOS 開發中的得力魯班尺 - SnapKit | 掘金技術徵文
SnapKit-Sample

let containerView = UIView()
superview.addSubview(containerView)

containerView.snp.makeConstraints { (make) -> Void in
    make.top.equalTo(superview).offset(5)
    make.left.equalTo(superview).offset(5)
    make.bottom.equalTo(superview).offset(-5)
    make.right.equalTo(superview).offset(-5)

    // 或者可以更簡潔
    // make.edges.equalTo(superview).inset(UIEdgeInsetsMake(5, 5, 5, 5))
}

let avatarView = UIView()
containerView.addSubview(avatarView)

avatarView.snp.makeConstraints { (make) -> Void in
    make.size.equalTo(35)
    make.left.equalTo(superview).offset(5)
    make.centerY.equalTo(container)
}複製程式碼

於是,SnapKit 便能夠將所有約束新增妥當。可以看到,這樣的寫法非常簡潔明瞭,並且可讀性高。

幾個至關重要的 Tips :

  • 確定最佳父檢視佈置約束
  • 記住安裝的約束以便在之後可以快速移除
  • 確保相關檢視 setTranslatesAutoresizingMaskIntoConstraints(false)

相等(equalTo)之外

.equalTo 相當於 NSLayoutRelation.Equal

.lessThanOrEqualTo 相當於 NSLayoutRelation.LessThanOrEqual

.greaterThanOrEqualTo 相當於 NSLayoutRelation. GreaterThanOrEqual

這三個約束關係可接受以下某個引數:

1.檢視屬性
make.centerX.lessThanOrEqualTo(view2.snp.left)複製程式碼

iOS 開發中的得力魯班尺 - SnapKit | 掘金技術徵文

2.某個檢視 UIView/NSView

用於描述與其他檢視之間的佈局關係

// 這兩行語句是等效的
make.left.greaterThanOrEqualTo(label)
make.left.greaterThanOrEqualTo(label.snp.left)複製程式碼
3.固定常量

用於描述本身的寬高約束

//  200 <= 寬度 <= 400
make.width.greaterThanOrEqualTo(200)
make.width.lessThanOrEqualTo(400)複製程式碼

用於描述與父檢視的佈局關係

// 建立約束使得 view.left <= view.superview.left + 10
make.left.lessThanOrEqualTo(10)複製程式碼

更多固定常量的示例

make.top.equalTo(42)
make.height.equalTo(20)
make.size.equalTo(CGSizeMake(50, 100))
make.edges.equalTo(UIEdgeInsetsMake(10, 0, 10, 0))
make.left.equalTo(view).offset(UIEdgeInsetsMake(10, 0, 10, 0))複製程式碼

學會應用約束的優先順序

.priority 允許你指定某個約束的優先順序

優先順序一般跟在約束鏈的末尾:

make.top.equalTo(label.snp.top).priority(600)複製程式碼

組合多種約束

SnapKit 支援同時組合不同的約束條件,方便高效

邊緣(edges)

make.edges.equalTo(view2);
make.edges.equalTo(superview).inset(UIEdgeInsetsMake(5, 10, 15, 20))複製程式碼
尺寸(size)
make.size.greaterThanOrEqualTo(titleLabel)
make.size.equalTo(superview).offset(CGSizeMake(100, -50))複製程式碼
居中(center)
make.center.equalTo(button1)
make.center.equalTo(superview).offset(CGPointMake(-5, 10))複製程式碼

懂得改變

有時我們需要通過改變一些現有的佈局約束來實現動畫,又或者是根據不同情況來調整佈局,因此,SnapKit 也提供了不同的方式來實現。

1. 約束引用

即通過新增對應約束的全域性引用變數,來實現對約束的控制

var topConstraint: Constraint? = nil

...

// 建立佈局約束
view1.snp.makeConstraints { (make) -> Void in
  self.topConstraint = make.top.equalTo(superview).offset(padding.top).constraint //新增全域性引用
  make.left.equalTo(superview).offset(padding.left)
}
...
// 之後若是要移除該約束
self.topConstraint.uninstall()

// 或者更改該約束
self.topConstraint.updateOffset(5)複製程式碼

這個方式在大多數情況下有些繁瑣,因此在開發工程中並不常用。

2. snp.updateConstraints
// 官方推薦在這個方法中來新增或更改佈局
override func updateConstraints() {
    self.growingButton.snp.updateConstraints { (make) -> Void in
        make.center.equalTo(self);
        make.width.equalTo(self.buttonSize.width).priority(250)
        make.height.equalTo(self.buttonSize.height).priority(250)
        make.width.lessThanOrEqualTo(self)
        make.height.lessThanOrEqualTo(self)
    }

   // 別忘記在最後呼叫父類的該方法
     super.updateConstraints()
}複製程式碼

這是在開發中最為常用的修改佈局的方式

3. snp.remakeConstraints

這個方法與 snp.updateConstraints 十分相似,不同的是,這個方法會先將已存在的SnapKit佈局約束全部移除。

func changeButtonPosition() {
  self.button.snp.remakeConstraints { (make) -> Void in 
    make.size.equalTo(self.buttonSize)

    if topLeft {
      make.top.left.equalTo(10)
    } else {
      make.bottom.equalTo(self.view).offset(-10)
      make.right.equalTo(self.view).offset(-10)
    }
  }
}複製程式碼

總結

說白了,SnapKit 真的是手動 AutoLayout 的超級利器。
另外,它也有 Objective-C 版本,Masonry,設計理念與使用方法一致。

更多參考


掘金技術徵文活動連結:

gold.xitu.io/post/58522d…

相關文章