今年WWDC蘋果官方除了把整個生態系統做了一次全面升級之外,伴隨而來還有同期發布的Swift 3.0 . 如果一年前你還猶豫是否把項目核心語言切換Swift有所忌憚的話,也許稍后Swift 3.0正式版的發布會漸漸打消你在這方面的顧慮. 隨著近兩年Swift迅猛的發展,而在它開源之后,得意與開源社區源源不斷的貢獻更是如井噴一樣的勢頭. 當然除了iOS平臺,Swift同時還支持了Linux. Swift語言給我更直觀的感受是,終于不用在寫出類似Object-C冗長的代碼風格,調用簡潔且易讀的Swift讓人感到很清爽. 我對語言本身其實沒有太大的期望,不過如果能有類似 C# 之類的語言的異步風格函數(Async-Style Function)的話,那就再好不過了. 當然從官方放出的Swift路線圖可以看出,3.0版本大的革新內容并不多,主要的方向還是剔除掉C語言的影響為主. 如果說Swift在3.0之前還存在生產力的問題(缺少成熟的第三方框架),有時間看看github相關資源,也許現在就是切入的好時機.
提到AutoLayout,我在使用OC語言開發時一直經常使用的是Masonry框架,在慢慢切入Swift之后,雖然其語言特性能夠支持OC的混編,但依然讓人覺得很麻煩. Masonry使用開發者眾多,而其原作者也在眾多開發者要求支持Swift版本呼聲中推出了SnapKit. 和Masonry一樣,SnapKit是一套輕量級的布局框架,同樣適用鏈式語法封裝Apple的自動布局約束. 項目發布至今大約一年多的時間,已經在github上有六千多個Star,當然了,這其中也少不了利用Masonry影響力給他打的那些廣告。
如果你還記得StoryBoard中那些約束的線條,那么你也一定記得其中 Constriants 的寫法。而SnapKit所做的就是這樣一件事——讓你采用鏈式語法封裝的方式寫 Constraints:
當然如果使用過Masonry上面沒什么大驚小怪的,但SnapKit比Masonry更為靈活(具體細節后面詳細說明):
安裝
在安裝前需要注意SnapKit要求的環境配置:
[iOS 7.0+ / OS X 10.9+] ?/ ?[Swift 2.0] ?/ ?[Xcode 7.0+]
采用Carthage安裝SnapKit:
github "SnapKit/SnapKit" >= 0.21.1
安裝時指向當前發布的最新版本.通過carthage update 命令生成引用,在項目根目錄下找到生成的:
Carthage -> Build -> iOS -> SnapKit.framework
文件,然后把文件集成到:
Project -> General -> Embedded Binaries
選項中,在項目代碼中引入:
import SnapKit
編譯成功,則安裝完成. 當然如果你更習慣CocoaPod或者更多的安裝方法請參見官方文檔.
基礎用法
因為SnapKit設計思路延續了OC版本的Masonry, 只不過換了一種實現語言Swift, 如果你對Masonry非常熟悉,那么其二者基本用法上大同小異.
先看一個基本示例,我們在UI布局中首先嘗試布局一個GrayBox:
基本寫法跟Masonry沒有多磨大的區別, 但在SnapKit中,如果多個屬性值一致,可以串連視圖屬性,增加其可讀性,類似上面寫法有一個更簡單的實現方式:
在SnapKit通過 ‘snp_makeConstraints' 給元素增加約束,約束主要分為邊距、寬、高、左上右下距離、基準線, 當然增加約束同樣也是可以修正的, 修正方式有位移修正 [‘inset、offset’] 和倍率修正 [multipliedBy].?
SnapKit支持的屬性與 NSLayoutAttrubute 對照表如下:
其中leading與left、trailing與right 在正常情況下是等價的, 但是當一些布局是從右至左時(比如阿拉伯文) 則會對調. 換句話說大部分情況二者其實是等價的.?
修正約束語法一般就是三種,跟Masonry完全一致.
.equalTo:等于
.lessThanOrEqualTo:小于等于
.greaterThanOrEqualTo:大于等于
關于基本用法,官方文檔和示例中非常詳細這里就不多介紹. 重點說一下其其他Masonry少見的用法.
倍率修正
在布局我們有兩個正方形色塊,現在采用倍率修正方式,采用倍率修正方式吧橙色視圖縮小為灰色視圖的一半,如下圖:
可以采用multipliedBy實現:
注意這里不得不說是這個multipliedBy方法,?當前只是需要橙色視圖大小也就是Size屬性,而該方法能夠接受的值我們能從其定義中找到,有如下幾種值的類型:
同理DividedBy也是如此.
約束引用
在日常布局中,我們可能在多個地方更新同一個約束的值. 這就需要對現有定義的約束能夠修改、移除、替代等操作. 而SnapKit可以將約束的結果賦值給一個局部變量或一個類屬性,然后對這個約束的引用進行操作. 這樣就大大簡化我們操作一個約束的成本,同時保證其靈活性.
在頁面我們有一個橙色的視圖,距離頂部100,橫向位置居中. 點擊頁面Button時移除掉該約束,效果如下:
實現很簡單:
首先什么一個約束對象topConstraint, 在對橙色視圖添加約束時,引用SuperView頂部間距的約束. 當點擊Button移除約束按鈕時則觸發移除操作:
在觸發移除時,通過調用topConstraint的uninstall方法則完成操作. 移除完成后如果更新改約束,例如把橙色視圖到頂部距離由原來100改為現在200像素. 直接采用updateOffset(200)即可,當然這個操作之前因為使用uninstall,所以導致約束不可用,在調用updateOffset方法前需要把通過activate將其激活,要不然沒有任何效果.
約束優先級
當同一個元素有多個建立多個約束時,可以定義約束的優先級。這樣當約束出現沖突的時候,優先級高的約束覆蓋優先級低的約束.
SnapKit中元素默認優先級是500(最大數值是1000),也就是priorityMedium()中等級別.除此之外還可以設置如下幾個優先級:
priorityLow():設置低優先級,優先級為250
priorityMedium():設置中優先級,優先級為500(默認優先級)
priorityHigh():設置高優先級,優先級為750
priority():可以設置任意的優先級,接受的參數是0-1000的數字.
優先級使用語法是一般放在約束鏈的結束處,例如:
make.width.height.equalTo(100 *self.view.width).priorityLow()
篇幅所限關于用法參見官方的Demo或者本篇演示的github上源代碼.?這里就不做過多贅述.
小結
SnapKit和Masonry一出同源,在設計思想極為相似,但在用法上原作者坐了一些創新,使SnapKit更為靈活適應更多的場景. 雖然SnapKit很好用,但我想很多純代碼進行界面的人應該都知道,它的弊端是非常的耗時且細節瑣碎繁多, 極大自主帶來的是生產力的不足. 我想很多人跟我一樣都有同感. 所以我最近開始嘗試是否可以xib/storyboard+SnapKit混合使用,主要布局使用xib/storyboard,在需要動態更新布局的時候使用SnapKit. 效率是提升了一些,但遇到很多特別棘手的問題. xib/storyboard在界面開發上的確可以大大提升開發效率,在部分界面設計場景也的確需要手寫代碼的靈活性. 如果有更好方案不放可以探討一下.