
如果你要讓兩個iOS開發(fā)吵起來,只需要說一句:Frame布局比Masonry好!
iOS常見的布局方式有三種:xib, Masonry,frame,相信對于iOS開發(fā)者來說,這三種布局并不陌生,并且時常會看到Frame與Masonry誰更好的爭論,其實(shí)并沒有誰比誰好這一說,只有誰比誰更合適當(dāng)前項(xiàng)目,靈活運(yùn)用才是王道
- Xib: 基于Autolayout,簡單,上手快,可視化視圖大大提升了開發(fā)效率,缺點(diǎn)是靜態(tài)布局不夠靈活,修改麻煩,性能相對其他會稍低一點(diǎn),適合需要快速開發(fā),頁面較為固定的項(xiàng)目
- Masonry: 基于Autolayout,布局上比Xib靈活,適配方便快速,缺點(diǎn)是約束有錯誤不直觀,且容易代碼冗余,性能次于Frame,適合需要快速迭代,產(chǎn)品經(jīng)理腦洞賊大經(jīng)常修改的UI的項(xiàng)目
- Frame: 純手工計算,適用于復(fù)雜、多變的頁面,性能最好,布局最靈活,做動畫相對比Masonry方便;缺點(diǎn)是需要大量的計算,容易造成閱讀困難,接手難度大
這里一般會有三個疑問
一. 為什么說Frame的性能比Masonry的好,Xib的次之?
Masonry和Xib都是基于Autolayout相對布局,所有的相對布局最終都會轉(zhuǎn)換成Frame絕對布局;AutoLayout是線性方程組求解,當(dāng)計算過多時,會占據(jù)較大系統(tǒng)內(nèi)存,甚至影響GPU繪制造成卡頓,這也是很多人盡量壓縮視圖層級,減少計算量的原因;Frame則干脆得多,基于XY坐標(biāo)軸系統(tǒng)的布局。從數(shù)學(xué)上限定了UI控件的具體位置,是iOS開發(fā)中最底層、最基本的界面布局機(jī)制。
就像是去電影院找位置,直接說第幾排第幾座肯定比“距離最右邊第三個距上邊第十個位置”這種說法來的省力一些;至于Xib原理和Autolayout一樣,但多耗費(fèi)了些性能在圖形轉(zhuǎn)化上
二. 上面三種對各種尺寸屏的適配和使用上如何?
這點(diǎn)綜合起來Masonry占優(yōu),純代碼設(shè)計,在頁面布局的操控上會更為方便,控件間的關(guān)系也一目了然。但這里需要提一下一些沒接觸過Xib和Frame上的一些錯誤理解
在Xib設(shè)置的高度是死的,且不能根據(jù)屏幕大小適配?
Xib可以可以將高度約束NSLayoutConstraint引出,設(shè)置NSLayoutConstraint的constant即可隨意修改高度,而且可以通過添加分類
- (void)setAdapterScreen:(BOOL)adapterScreen{
adapterScreen = adapterScreen;
if (adapterScreen) {
//這里也可以改成以其他屏幕為基準(zhǔn)
self.constant = self.constant * ([UIScreen mainScreen].bounds.size.width / 375.0);
}
}
- (BOOL)adapterScreen{
return YES;
}
后面在需要適配的NSLayoutConstraint上Adapter Screen修改為On即可,修改后的NSLayoutConstraint都會跑這個方法適配。這兩個配合基本可以滿足大部分頁面的適配需求。
Frame是停留在4s年代的遠(yuǎn)古布局,各種值也是死的,不能根據(jù)屏幕大小適配?
Frame不是停留在4S年代的布局,而是怎么都不會變動的的基礎(chǔ),所有布局最終轉(zhuǎn)換的目的,誠然使用Autolayout能幫我們減少大量的計算,但這些是基于損耗性能的情況下進(jìn)行的,如果對性能有較高的追求的話,一般都建議用Frame布局。
沒接觸過的很多人不理解Frame的情況下,會本能的認(rèn)為Frame就是寫死幾個值,后續(xù)根據(jù)各種屏幕判斷值,劉海屏什么的都要單獨(dú)適配,這個認(rèn)知是錯誤的,一般在熟悉Frame布局的人都會設(shè)置好宏定義
// 屏幕寬
#define kScreenW ([UIScreen mainScreen].bounds.size.width)
// 屏幕高
#define kScreenH ([UIScreen mainScreen].bounds.size.height)
// 適配iPhone X 狀態(tài)欄高度
#define kScreenStatusBarHeight (iPhoneX ? 44.f : 20.f)
// 適配iPhone X 導(dǎo)航欄高度
#define kScreenNavHeight (iPhoneX ? 88.f : 64.f)
// 狀態(tài)欄
#define kNavH (iPhoneX ? 88.f : 64.f)
// iPhone X
#define iPhoneX (([[UIScreen mainScreen] bounds].size.height - 812) ? NO : YES)
使用時
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, kScreenW, self.view.height - kNavH) style:UITableViewStyleGrouped];
這樣就很方便的根據(jù)各種情況進(jìn)行適配,本身代碼量并不會增加多少,而性能卻提升不少。
三. 這些布局應(yīng)該如何選取
在我看來,這三種布局的優(yōu)缺點(diǎn)都非常的明顯,根據(jù)項(xiàng)目本身需求選取對應(yīng)的方式即可。上面提到非常多次的性能問題,但隨著手機(jī)性能的不斷提高,一些性能損耗的對App的影響越來越小
- 在項(xiàng)目較小,頁面變動不大,需要快速開發(fā)的情況下,Xib也是一個很好的選擇,蘋果本身推出Xib的原因就是為了讓程序員把更多的精力放在業(yè)務(wù)邏輯上;
- 在項(xiàng)目迭代頻率較高,產(chǎn)品腦洞奇大,經(jīng)常需要修改UI的情況下,建議用Masonry。
- 在頁面較為復(fù)雜,或追求操作順滑,或頁面有動畫的情況下Frame才是最佳。