1. 程式人生 > >關於如何寫UI及螢幕適配的一些技巧(上)

關於如何寫UI及螢幕適配的一些技巧(上)

因為公司開啟了一個新的iOS專案, 所以近期比較忙, 沒有更新部落格,今天打算總結一下關於UI佈局及螢幕適配的一些實戰技巧,尤其使用純程式碼,會對提升效率及程式碼易於維護等方面有明顯幫助,這裡提到的沒有使用任何Xib, 如果不是在外包公司,也推薦大家多使用甚至完全使用純程式碼佈局UI,優缺點下面會說明,本文佈局使用masonry。貨不太乾,只是工作中的一點點小技巧與基礎知識,大家可以來分享更多的技巧。

12345678 提綱:1.關於xib/storyboard與純程式碼的對比2.一條規範(又提了一點關於命名的)3.UI工廠類與程式碼塊4.懶載入,View使用strong還是weak5.複雜介面要會分割槽,要會障眼法6.masonry均布View,及其佈局時約束依賴關係7.關於螢幕適配的一點技巧
1. 關於xib/storyboard 與 純程式碼的對比

a. xib快,純程式碼慢,但是在純程式碼熟練的情況下, 並不會慢很多
b. xib不易於修改,怎麼修改,就是今天讓一個View上的元素這麼排布,明天就要換種排布方式,後天又要加些東西。。。
c. xib不靈活,什麼叫靈活,一個View上有10個元素, 其中5個都是不一定出現的,並且它們不是集中的佈局在哪個位置, 亂七八糟的,多一個少一個佈局還都有點影響,這就知道靈活的重要性了
d. xib不利於螢幕適配,怎麼適配,5s上一個View距左10畫素,產品說6p上就要距左20才協調,xib上拖線佈局怎麼搞,約束拖出來改變它嗎,複雜View有10個需要這樣處理的地方呢。。。
e. xib寫多了純程式碼手生,當然純程式碼寫多了,拖線也有點不熟練,這個不作為純程式碼更好的原因。。。
f. 但是!面試的時候如果你說我xib用的多,純程式碼佈局有點不熟練, 不好意思, 拜拜(本人經歷過),你說我都是純程式碼佈局的, xib會,不熟,大多公司聽到以前都是純程式碼,那沒問題,因為他們公司也不用xib。。。

2. 一條規範(又提了一點關於命名的)

“ .h 和 .m 的類擴充套件裡面不要隨便加東西,尤其 .h 裡的東西一定要是必須放在這裡,放在別處不行,實在有不太重要還必須放在這的,打好註釋 ”

這個東西無數次在專案中見到過隨意在這加東西的做法, 剛寫完當時還好, 一個月以後再看, 瞬間懵逼。。。
這是什麼鬼。。。
當時為啥要寫這個量。。。
這怎麼還有個沒用過的量。。。
這個東西要不要傳, 為啥A類用的時候穿了, B類就不傳了。。。

再提一下另外一個規範, “名字不要隨便起,弄個坑爹名字,自己隔天都不知道啥意思,是跟公司結了仇了還是怕洩露天機”

112162015-9c415a7de4ecd20c 不算特別不規範的命名

為什麼說這些命名不是特別不規範, 因為這裡面雖然有些vBack啦, lbl啦, tbl啦, 不是那麼容易理解, 但是好歹是lbl,都用lbl了,不過為啥非得把Label放前面,官方命名的時候比如btn.titleLabel,Label也是放在後面的啊, 也沒縮寫成什麼lbl,我們就簡簡單單的叫nickNameLabel不行嗎。。。

說到命名就再多說一點, 如果一個複雜View內部佈局的時候需要分割成幾部分,在能想出名字的情況下最好不要按位置命名,比如topView,midView之類,明天產品說把位置調一下,最下面的部分比較重要提到最上面,這怎麼辦, 儘量想一想這部分大概負責什麼,要表達個什麼意思

3. UI工廠類 與 程式碼塊

UI工廠類: 其實程式碼很簡單,就是把對Label, Button等控制元件的屬性賦值封裝一下, 做到一行程式碼就能建立一個VIew, 如下圖, 雖然這一句程式碼有點長, 但是習慣之後寫個View是真心快

122162015-4724f8b0b1058e9e UI工廠類.h 132162015-752f5478446f364c UI工廠類.m

程式碼塊: 程式碼塊就是下圖的東西, 應該沒人不知道,不會新增隔壁百度

142162015-86b1e18f9c7557e6 程式碼塊

這個東西不光是UI佈局用, 很多位置都比較方便, 我常用的有這樣幾個

152162015-bb6bc82c0cc1e261 懶載入 162162015-0b45d4237662c234 masonry定義過的一部分 172162015-2e9ed2d4d6b945e8 masonry填空模式

尤其是純程式碼masonry佈局, 這樣的程式碼塊會讓你佈局的速度直逼甚至超越拖線, 只需要打出make就會出現已經定義好的各種約束, 比如要佈局高度, 打出makeh, 回車, 就直接進入填空模式,tab切換填空即可

4. 懶載入, View使用strong還是weak

為什麼要用懶載入, 有一種說法是用到的時候在建立,節省記憶體開銷,這種說法固然沒問題,但是對於大部分UI來說,基本遲早都會被建立。
所以,主要優點不在這裡,本著的做人原則,程式碼也該這樣寫,你既然是個View,那你就把自己解決好再來見我, 我要用你的時候只需要self.testView就可以了,下面兩張圖對比一下就會看到區別了,第二張為剛到公司時上一任的大作,這裡選取了一種比較看的清的貼出來

182162015-b2514e2773f669e8 弱引用懶載入 masonry佈局

上圖注意:masonry的block沒有進行copy,即當前物件沒有引用這個block,是區域性的引用,不會形成迴圈引用的,可以不用weakSelf

192162015-806a6349e80af3e1 混亂的還好的示例

對比一下即可看出來, 由於上圖使用中的控制元件均使用懶載入, 所以佈局方法裡連addSubView都不用寫了, 只需逐條佈局即可, 下圖中建立控制元件, 屬性賦值, 新增到父檢視的程式碼都混在一起, 並且還沒有使用masonry, 用上之後只會更亂。。。

View使用strong還是weak: 關於這個問題,其實還是有很多可以說一下的地方
懶載入寫法:

123456789101112131415161718192021222324252627282930313233343536373839 @interfaceViewController()@property(nonatomic,weak)UIView *weakView;@property(nonatomic,strong)UIView *strongView;@end@implementation ViewController/** UI控制元件使用弱引用建立方法 1. UIView *weakView = [[UIView alloc] init]; 這句必須宣告一個區域性變數, 不能用_weakView,    因為用 _weakView = [[UIView alloc] init], 等號右側建立了一個View之後,給了一個弱引用持有,相當於沒有持有,直接就釋放掉了    而 UIView *weakView = [[UIView alloc] init],等號左側的weakView預設是一個強引用,會暫時持有保住它,但是生命週期就在這個懶載入的大括號內,所有會有其他程式碼配合, 使這個View存活下來, 不被釋放 2. _weakView = weakView; 這句程式碼為屬性賦值, 以後在其他位置不管通過self.weakView還是_weakView才能找到這個View,    基本作用可以說等同於強引用的 _strongView = [[UIView alloc] init]; 3. [self.view addSubview:weakView], 第一條註釋中說了,UIView *weakView 的生命週期就是在這個{}內,那麼如何保證出了括號依舊存在,就是要給這個View加到一個不會被釋放的View(不一定強引用弱引用)上,即self.view, 這樣就不會被釋放掉了 */-(UIView *)weakView{if(!_weakView){UIView *weakView=[[UIView alloc]init];_weakView=weakView;weakView.backgroundColor=[UIColor redColor];[self.view addSubview:weakView];}return_weakView;}-(UIView *)strongView{if(!_strongView){_strongView=[[UIView alloc]init];_strongView.backgroundColor=[UIColor greenColor];}return_strongView;}

佈局時區別:

123456789101112131415161718 -(void)configView{WeakSelf(ws);//弱引用由於懶載入直接加到父檢視上,所以點語法完了直接呼叫masonry佈局方法即可[self.weakView mas_makeConstraints:^(MASConstraintMaker *make){make.centerX.equalTo(ws.view);make.top.equalTo(ws.view).offset(100);make.size.mas_equalTo(CGSizeMake(100,100));}];[self.view addSubview:self.strongView];[self.strongView mas_makeConstraints:^(MASConstraintMaker *make){make.centerX.equalTo(ws.view);make.bottom.equalTo(ws.view).offset(-100);make.size.mas_equalTo(CGSizeMake(100,100));}];}

移除之後的區別(重點,涉及到理解強弱指標):執行上述程式碼後,螢幕上出現一上一下兩個View, 點選空白區域, 移除掉兩個View, 1秒後看一下,1秒後看是因為, 出了這個方法, 也就是執行到結束的括號之後, 才會把View移除掉, 注意看坐下控制檯兩個View,weakView為nil, 即已被釋放, strongView還是存在, 因為即使從父檢視上移除, self本身對其還有一個強引用, 不會釋放掉,那麼如果想把這個View釋放掉需要怎麼辦, 就是在[_strongView removeFromSuperview]後面加一句_strongView = nil;

202162015-980f7f8b8d685aae 注意weakView為nil,strongView還存在 212162015-9320e145dfabf97c 強指標View置空

下面圖解一下, 為什麼不置空, strongView就不被釋放

222162015-df7686b7905e5f92 強弱指標View實際區別

總結起來的話, 其實如果理解到位,使用強弱都沒有問題,但是一般來說,由於弱引用會被及時的釋放掉,所以需求允許的話,一般建議使用弱引用,那什麼情況不能使用弱引用呢,這個要看具體需求,舉個例子,如果一個View,需要從父View移除掉,但是之後還有可能加回來,還要保持移除之前的樣子,這種情況強引用會更適合。

收集了一些意見:

  1. 懶載入不一定一定要, 這是完全沒問題的,有人習慣把建立View,屬性賦值,新增到父檢視的程式碼寫在一起,認為這樣便於管理,順著看更清晰,沒問題。
  2. 如果View層次複雜,用懶載入弱引用View的時候注意層級關係,如果理解不到位,容易產生問題,因為addSubView寫在懶載入裡,極易造成層次不清晰,這時就要個人理解,用自己認為最適合的方法了。
  3. 我為什麼喜歡將UI寫成懶載入?aView就是aView,bLabel就是bLabel,每個控制元件做好自己事情,給自己顏色字號都弄好了,等我要用你的時候,比如要往父檢視添加了,拿來直接加就好,所以在新增View這個方法裡都是新增,無關程式碼沒有,要修改aView背景色,去找aView(aView的懶載入裡面改)啊

本篇暫時先寫到這裡,後面的這兩天會發出來,感覺有幫助的話可以關注一下,點個贊,碼字不易,共同進步。