iOS學(xué)習(xí)(三十七) 一種masonry布局代碼的最佳實踐

Best Practice.jpg

使用masonry進行布局構(gòu)建的時候,代碼邏輯往往比較長抠刺。在布局頁面時往往會有嵌套的情況發(fā)生叶堆,組件的創(chuàng)建代碼就和布局代碼交織在一起阱飘,一段代碼看起來更是復(fù)雜,讓人難以理解。

本文僅僅通過一些UI寫法上的調(diào)整讓整體UI布局易讀沥匈、易改蔗喂。如果你有同樣的問題,耐心花5分鐘讀完高帖,稍加實踐即可事半功倍缰儿。

為了應(yīng)對這樣的情況,通常的做法是將UI構(gòu)建代碼寫在上面散址,布局代碼全部寫在最后(布局的組件必須先要被添加到父組件上)乖阵,這樣的好處是構(gòu)建和布局分開了,看起來似乎整齊了一些预麸,但是調(diào)試幾乎是災(zāi)難性的瞪浸,實踐一段時間后發(fā)現(xiàn)一些難以解決的問題。

一吏祸、遇到的問題:

1.元素分散不內(nèi)聚

原本頁面構(gòu)建時对蒲,會根據(jù)設(shè)計結(jié)構(gòu)先把一個大的頁面分割成幾部分,然后分別進行布局贡翘。在實踐中蹈矮,由于純代碼代碼量多,所以大多數(shù)情況下往往能少寫組件就少寫鸣驱,這樣原本該通過添加適當?shù)母竀iew去分離的UI結(jié)構(gòu)就不會去分離泛鸟,導(dǎo)致各個組件之間關(guān)系過緊密,不利于后期的修改丐巫,相似UI復(fù)用不易谈况。

2.命名困難

由于布局在一起,則每個組件都應(yīng)該有自己有意義的名稱递胧,往往導(dǎo)致命名困難碑韵。但大多數(shù)都只是在布局中使用一次,動態(tài)變化的少缎脾。這樣也不利于讀代碼祝闻。

二、一種最佳實踐

經(jīng)過一段時間的實踐和總結(jié)遗菠,找到一種比較清晰的寫法:

1.利用{}構(gòu)成代碼塊對每一個組件進行分離
2.在每個代碼塊中將布局代碼寫在最后
3.每個子view都盡可能的之依托于自己的父組件進行布局

舉例說明:
中間有個view联喘,view中有兩個label, 一個居上,一局下辙纬,效果如圖


例子.png

代碼如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    UIView *bgView = [[UIView alloc] init];
    {
        [self.view addSubview:bgView];
        bgView.backgroundColor = [UIColor blackColor];
        
        UILabel *label1 = [[UILabel alloc] init];
        {
            [bgView addSubview:label1];
            self.nameLabel = label1;
            
            label1.font = [UIFont systemFontOfSize:18];
            label1.textAlignment = NSTextAlignmentCenter;
            label1.textColor = [UIColor systemYellowColor];
            
            [label1 mas_makeConstraints:^(MASConstraintMaker *make) {
                
                make.top.left.right.mas_equalTo(0);
            }];
        }

        UILabel *label2 = [[UILabel alloc] init];
        {
            [bgView addSubview:label2];
            self.infoLabel = label2;
            
            label2.textColor = [UIColor whiteColor];
            label1.textAlignment = NSTextAlignmentCenter;

            [label2 mas_makeConstraints:^(MASConstraintMaker *make) {
                make.bottom.left.right.mas_equalTo(0);
            }];
        }
        
        [bgView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            make.center.mas_equalTo(0);
            make.size.mas_equalTo(CGSizeMake(200, 200));
        }];
    }
    
    self.nameLabel.text = @"Jack";
    self.infoLabel.text = @"Jack is a good student";
}
三豁遭、寫法說明:

1.每一個組件本身都使用{}進行封閉,在封閉區(qū)域的最上面寫添加到父組件代碼贺拣,然后是該組件本身的屬性設(shè)置蓖谢,賦值全局變量等捂蕴。在最下面寫布局代碼。如果還有子組件闪幽,就寫在兩者之間(截選上方代碼部分):

    UIView *bgView = [[UIView alloc] init];
    {
        [self.view addSubview:bgView];
        bgView.backgroundColor = [UIColor blackColor];

        //  這里添加子組件

        [bgView mas_makeConstraints:^(MASConstraintMaker *make) {
 
            make.center.mas_equalTo(0);
            make.size.mas_equalTo(CGSizeMake(200, 200));
        }];
    }
  1. 子組件寫法同理啥辨,一個子組件可以命名隨意一點不必十分有意義,比如leftLabel盯腌、rightLabel溉知、label1、label2等腕够。
    因為頁面結(jié)構(gòu)復(fù)雜以后级乍,層級會很多,不少組件其實本身只是用于定位燕少、占位或者分隔等卡者,這樣可以極大的簡化命名也不影響對代碼的理解(用于需要保留到全局的變量仍然需要使用有意義的命名)

  2. 對動態(tài)賦值的元素放到最下面進行 賦值 或 邏輯處理。不變的內(nèi)容放在布局代碼中賦值客们。

四、可能的疑問
1.為什么不將組件的聲明也放到代碼塊中材诽?

組件之間往往有約束關(guān)系底挫,全部放到代碼塊中再要使用需要將其放到全局變量中進行引用,這樣別的代碼塊中才能訪問到脸侥,違背了初衷建邓。

2.為什么不把UI的創(chuàng)建拆分成一個個的方法調(diào)用,在方法內(nèi)部去寫布局睁枕?

通過這樣的方式構(gòu)建UI官边,表面看起來可以簡化一部分代碼,但是缺點也是顯而易見的:

方法要接收父組件作為參數(shù)(需要添加到父組件上才能設(shè)置約束外遇,否則會報錯)注簿,同時,如果需要參考其他元素的位置跳仿,那么方法的參數(shù)也需要傳入這個元素诡渴。很明顯,這樣的方式只是轉(zhuǎn)移了雜亂的代碼菲语,并沒有簡化妄辩,后期頁面修改時帶來的問題也是災(zāi)難性的。

當然山上,我們可以把組件的創(chuàng)建和一些設(shè)置寫到一個方法去代替寫在{}前的創(chuàng)建和{}中的屬性設(shè)置眼耀,比如:

    UIView *bgView = [self createBgView];
    {
        [self.view addSubview:bgView];

        //  這里添加子組件

        [bgView mas_makeConstraints:^(MASConstraintMaker *make) {
 
            make.center.mas_equalTo(0);
            make.size.mas_equalTo(CGSizeMake(200, 200));
        }];
    }

createBgView這個方法中進行創(chuàng)建,設(shè)置屬性等操作佩憾。這樣的寫法其實對于通用的View創(chuàng)建才有用哮伟,如果定制的比較多干花,那么這樣的做法也只是增加了麻煩(因為每一個定制的都需要這樣一個方法),反而得不償失澈吨。

3.其他的優(yōu)化方法

如果可能的話把敢,其實還是更推薦使用storyboard / xib的布局方式,固定的直接布局谅辣,動態(tài)顯示內(nèi)容用一個父控件去占位修赞,只把動態(tài)的部分去代碼構(gòu)建。畢竟GUI的所帶來的效率提升是顯而易見的桑阶。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柏副,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蚣录,更是在濱河造成了極大的恐慌割择,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萎河,死亡現(xiàn)場離奇詭異荔泳,居然都是意外死亡,警方通過查閱死者的電腦和手機虐杯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門玛歌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人擎椰,你說我怎么就攤上這事支子。” “怎么了达舒?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵值朋,是天一觀的道長。 經(jīng)常有香客問我巩搏,道長昨登,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任塔猾,我火速辦了婚禮篙骡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丈甸。我一直安慰自己糯俗,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布睦擂。 她就那樣靜靜地躺著得湘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪顿仇。 梳的紋絲不亂的頭發(fā)上淘正,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天摆马,我揣著相機與錄音,去河邊找鬼鸿吆。 笑死囤采,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的惩淳。 我是一名探鬼主播蕉毯,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼思犁!你這毒婦竟也來了代虾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤激蹲,失蹤者是張志新(化名)和其女友劉穎棉磨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體学辱,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡乘瓤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了策泣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馅扣。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖着降,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拗军,我是刑警寧澤任洞,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站发侵,受9級特大地震影響交掏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刃鳄,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一盅弛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叔锐,春花似錦挪鹏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至步责,卻和暖如春返顺,著一層夾襖步出監(jiān)牢的瞬間禀苦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工遂鹊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留振乏,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓秉扑,卻偏偏與公主長得像慧邮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子邻储,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容