簡(jiǎn)單好用的iOS自動(dòng)布局框架

有感于iOS自動(dòng)布局代碼的冗長(zhǎng)和繁瑣,閑來(lái)無(wú)事,便自己封裝了一下。
寫(xiě)的過(guò)程中我借鑒了NSLayoutAnchor和masonry的一些思路,寫(xiě)了充分的單元測(cè)試用例,并對(duì)框架的性能(耗時(shí)和內(nèi)存占用)做了一個(gè)簡(jiǎn)單評(píng)估。

優(yōu)點(diǎn)

  • 簡(jiǎn)單,17KB大小。易用,對(duì)于許多布局,用起來(lái)跟frame差不多
  • 支持iOS8和swift
  • 速度是masonry的1.7倍,接近系統(tǒng)方法速度,占用內(nèi)存小
  • 跟蹤所有約束,不需要額外寫(xiě)成員屬性引用約束
  • 充分的單元測(cè)試
  • 支持iOS11,相對(duì)safeAreaLayoutGuide的布局約束書(shū)寫(xiě)非常簡(jiǎn)便!
和系統(tǒng)方法、Masonry在性能上的比較

設(shè)置約束

所有約束設(shè)置都遵循系統(tǒng)的公式:

firstItem.firstAttribute {=,<=,>=} secondItem.secondAttribute * multiplier + constant

簡(jiǎn)便寫(xiě)法(適用于NSLayoutRelationEqual、multiplier = 1 且除了寬、高以外的約束的constant = 0的情況)

[self.redView activateConstraints:^{
    self.redView.height_attr.constant = 100; // redView的高度 = 100
    self.redView.width_attr = self.blueView.width_attr; // redView的寬度 = blueView的寬度
    self.redView.top_attr = self.blueView.top_attr; // redView的頂部 = blueView的頂部
    self.redView.left_attr = self.blueView.right_attr; // redView的左邊 = blueView的右邊
}];

常規(guī)寫(xiě)法

[self.redView activateConstraints:^{
    self.redView.height_attr.constant = 150; // redView的高度 = 150
    [self.redView.width_attr equalTo:self.blueView.width_attr constant:50]; // redView的寬度 = blueView的寬度 + 50
    [self.redView.top_attr equalTo:self.blueView.top_attr constant:-10]; // redView的頂部 = blueView的頂部 - 10
    [self.redView.left_attr greaterThan:self.blueView.right_attr constant:20]; // redView的左邊 >= blueView的右邊 + 20
}];

activateConstraints方法會(huì)將block里所有約束都綁定給調(diào)用者,這里就是self.redView,這么做是為了方便以后獲取約束。
也可以用更接近系統(tǒng)的風(fēng)格設(shè)置約束,但這樣以后想獲取特定的某個(gè)約束就比較麻煩,需要?jiǎng)?chuàng)建一個(gè)成員變量引用以后想改變的約束。

NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:4];
[arrayM addObject:[self.redView.height_attr equalTo:nil constant:100]];
[arrayM addObject:[self.redView.width_attr equalTo:self.blueView.width_attr]];
[arrayM addObject:[self.redView.top_attr equalTo:self.blueView.top_attr]];
[arrayM addObject:[self.redView.left_attr equalTo:self.blueView.right_attr]];
[NSLayoutConstraint activateConstraints:arrayM];

更新safeAreaLayoutGuide布局寫(xiě)法,不需要寫(xiě)版本判斷

[self.redView activateConstraints:^{
    self.redView.height_attr.constant = 100; // redView的高度 = 100
    self.redView.width_attr = self.blueView.width_attr; // redView的寬度 = blueView的寬度
    self.redView.top_attr = self.view.top_attr_safe; // redView的頂部 = view的safeAreaLayoutGuide的頂部,非iOS11則是view的頂部
    self.redView.left_attr = self.view.right_attr_safe; // redView的左邊 = view的safeAreaLayoutGuide的右邊,非iOS11則是view的右邊
}];

改變約束值

self.blueView.width_attr.constant = 100;

或者

[self.redView constraintAccordingToAttribute:self.redView.height_attr].constant = 100;

獲取約束

獲取非常方便,當(dāng)初創(chuàng)建約束是怎樣的相對(duì)關(guān)系,通過(guò)相同的關(guān)系就可以獲取約束。

NSLayoutConstraint *cons = [self.titleLabel constraintAccordingToAttribute:self.titleLabel.bottom_attr andAttribute:self.subtitleLabel.top_attr];

激活和關(guān)閉約束

[self.redView activateConstraintAccordingToAttribute:self.redView.height_attr];
[self.redView deactivateConstraintAccordingToAttribute:self.redView.height_attr];

注意:調(diào)用deactivateConstraintAccordingToAttribute會(huì)將該約束對(duì)象銷(xiāo)毀,這里保持跟系統(tǒng)的deactivateConstraint方法一致。如果只是想暫時(shí)關(guān)閉約束,以后想再activate,則應(yīng)該獲取約束后,設(shè)置.active = NO

解釋一下核心方法 -(void)activateConstraints:(void (^)())constraints;
這是UIView的一個(gè)對(duì)象方法,一般來(lái)說(shuō)每個(gè)UIView的布局代碼寫(xiě)在自己的block里, 只有調(diào)一次該方法,才會(huì)給這個(gè)方法的調(diào)用者創(chuàng)建一個(gè)用來(lái)引用布局對(duì)象的可變數(shù)組,以后才可以通過(guò)這個(gè)調(diào)用者拿到里面的布局對(duì)象。
并且只要調(diào)用了一次該方法,以后即使不在該方法的block里寫(xiě)的約束,約束的firstItem如果和該方法的調(diào)用者是一個(gè)對(duì)象,也會(huì)把這個(gè)約束添加到firstItem(調(diào)用者)的數(shù)組里。
如果調(diào)用了activateConstraints后,又希望移除對(duì)應(yīng)view的數(shù)組,可以調(diào)用
- (void)deactivateAllConstraintsAndAssociatedObjects

具體使用請(qǐng)移步github下載示例代碼。


添加到項(xiàng)目

使用CocoaPods
在podfile中加入 'NSLayoutConstraint-SSLayout'
直接使用源代碼
將Source文件夾下的文件copy到項(xiàng)目

傳送門(mén):https://github.com/suruihai/NSLayoutConstraint-SSLayout

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容