再看SnapKit
連續兩個多月高強度的工作,每天幾乎加班到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入門教程APK
- SnapKit 最佳實踐APK
- SnapKit 中文文件翻譯APK
- SnapKit 原始碼解讀(二):DSLsAPK原始碼
- SnapKit 原始碼解讀(一):ExtensionsAPK原始碼
- 再看MongoDB副本集MongoDB
- 再看阿里雲阿里
- CocoaPods 整合 SnapKit 踩坑記錄APK
- Snapkit,呼叫layoutIfNeeded後x、y為負數。APK
- 再看JVM:垃圾回收那些事JVM
- [譯] 再看 Flask 視訊流Flask
- 再看雲端計算是否安全
- sql之20再看查詢SQL
- 【iOS開發】SnapKit是怎樣煉成的iOSAPK
- 再看ibatis Order By注入問題BAT
- 再看GET與POST的區別
- SnapKit 是怎樣煉成的 | 掘金技術徵文APK
- Android角落 不妨再看LinearLayoutAndroid
- 再看 Composer 自動載入原始碼原始碼
- 看了此文,Oracle SQL優化文章不必再看!OracleSQL優化
- 十年之後再看“物件導向”物件
- iOS 解決 Xcode 8中更新 SnapKit 3.0 的錯誤iOSXCodeAPK
- iOS 開發中的得力魯班尺 - SnapKit | 掘金技術徵文iOSAPK
- 2021再看Deno(CDN for JavaScript modules的思考)JavaScript
- 【正視CSS07】再看vertical-alignCSS
- 再看rabbitmq的交換器和佇列的關係MQ佇列
- 金雞落幕,從《流浪地球》再看人工智慧人工智慧
- 從原始碼的角度再看 React JS 中的 setState原始碼ReactJS
- 老樹開新花,再看 HTTP Response Splitting 攻擊HTTP
- 從Vue.js原始碼角度再看資料繫結Vue.js原始碼
- 從控制程式碼的概念再看分層設計
- 從0.1+0.2=0.30000000000000004再看JS中的Number型別JS型別
- 成為MySQL DBA後,再看ORACLE資料庫(十三、物理備份)MySqlOracle資料庫
- 這遊戲到底怎麼了? 一年後,再看《刺客信條奧德賽》遊戲
- MySQL alter table時執行innobackupex全備再看Seconds_Behind_MasterMySqlAST
- 成為MySQL DBA後,再看ORACLE資料庫(七、日誌體系)MySqlOracle資料庫
- 成為MySQL DBA後,再看ORACLE資料庫(五、記憶體管理)MySqlOracle資料庫記憶體
- 瞭解JavaScript中的Memoization以提高效能,再看React的應用JavaScriptReact