公司須要寫一個代碼規範,本人第一次寫,完成後記錄在blogweb
1、命名規範數據庫
一、類定義編程
例: ThisIsAClass,
採用蘋果推薦的方式,首字母大寫,多個有實際意義的英文單詞組成,每一個單詞的首字母大寫。json
在此基礎上類名須要體現出這個類的類型swift
試圖控制器:ThisIsAViewController
試圖:ThisIsAView
按鈕:ThisIsAButton
等等數組
我的不建議使用縮寫,由於代碼補全很是完善,單詞再長也不會影響方便性,但縮寫影響可讀性
可討論決定是否可以使用相似 ThisIsAVC,ThisABtn,之類的縮寫方式緩存
二、屬性安全
例:thisIsAObjectruby
首字母小寫,多個有實際意義的英文單詞組成,每一個單詞的首字母大寫。bash
在此基礎上,須要提示這個變量的類型或者用途。
例如:
UITextField * userNameTextField;
UIButton * leftTopButton,doSomeActionButton;
等等
縮寫問題同上,可討論。
三、成員變量
_menberObject
在屬性的基礎上,須要如下劃線開頭。
其餘規則和屬性同樣。
四、局部變量
參照屬性
五、函數命名
首字母小寫,多個有意義的單詞組成,:後面首字母小寫
例:
- (void)loginButtonDidPressed; - (void)loginWithUserName:(NSString) userName password:(NSString *) password;
等等
六、函數形參
參照屬性
如有可能與屬性命名相同或者衝突,建議加上in,a等前綴
例:
- (void) someMethod:(id) inValue anotherObject:(id) aObject
{
_vlaue = inVlaue;
self.object = aObject;
}
7 、前綴
因爲oc沒有命名空間的概念,全部蘋果建議使用前綴來防止第三方庫、子工程之間命名衝突。
目前咱們的工程中有的沒有前綴,有前綴的又不統一,須要討論是否統一。
2、代碼組織
一、概述
目前咱們的工程都採用MVC構架
因此頁面代碼都至少要包含,View(特別簡單的可能省略),VewController(UIVewController子類),ModelManager(這麼命名是區分於瘦model,也就是entity)
三者之間最好經過接口互相訪問,隱藏實現細節。
好比,VC不須要知道view有哪些label,textfileld,只須要view提供加載數據的方法就能夠,實現鬆耦合。這樣若是隻是頁面排版變了,只要修改接口實現就能夠,不用修改其餘部分。這也是swift發佈後,蘋果提出的面相接口(協議)編程的思想。
規則提出的目的,都是指導咱們對各模塊之間職能劃分,使各自功能單一,鬆散耦合,任一一方修改,儘量的不影響其餘模塊。
二、頁面
UIView:只作顯示邏輯不作業務邏輯,它應該是純被動的接受VC提供的數據,進行展現。
對用戶操做進行收集,提示VC事件發生。
下面提供一些開發場景的處理建議:
case 1
若是view包含一個imageview,性別變量sex,值爲male,顯示圖a,sex爲female,顯示圖b,這種邏輯應該在VC中實現,而不該該把sex傳給給View去保存。
//VC中
- (void) someMethod
{
if (self.sex == male) //假設male爲枚舉
{
[view loadImage:imageA];
}
else
{
[view loadImage:imageB];
}
}
//view中
- (void)loadImage:(UIImage *)inImage
{
self.imageView.image = inImage;
}
case 2
不要在init方法中,去取自身的frame,並以此對子view設置frame,而應該在layoutSubviews中設置
由於不少時候,init方法中,view自己的frame並非最後顯示的frame
- (void)layoutSubviews
{
// 必定要調用super的方法
[super layoutSubviews];
//子view的frame設置
…
}
case 3
只是堆砌子View的狀況通常不太須要自定義view。
自定義view,其實更應該發生在須要重載drawRect方法,或者事情響應touchesBegan/touchesEnded等方法時。而大部分狀況其實不須要重載這些方法。只須要addSubvew。
這種狀況其實更應該考慮是建一個子視圖控制器,畢竟管理一個視圖層級(view hierarchy)是VC的事情。
三、視圖控制器
試圖控制器負責:從而且只從modelManager獲取數據,展現到View上。而且接受modelManager數據變化發生時通知,提供回調方法。
開發場景:
case 1
loadView:通常不建議重載,實在要用根據文檔所訴,只應該建立視圖層級(view hierarchy)也就是隻應該作alloc和addSubview。而且若是重載它了,不要調用super,額外的賦值需在viewDidload以後再作。
注意:若是使用了xib或者storyboad就不要重載這個函數。而應該使用awakeFromNib。
case 2
viewDidload:做爲入口,但願它能比較簡潔直觀,因此建議它內部只出現toDoList型的函數,具體的實現到各個函數中實現。
例如:
- (void) viewDidLoad
{
[super viewDidLoad];
[self setupViews];
[self registerNotifications];
[self setupModelManager];
[self doOtherThing];
}
建議在viewDidload中使用自動佈局來管理View及子view的frame
case 3
viewwill/DidlayoutSubviews:這對函數在 view調用layoutSubviews先後調用。若是你沒用使用自動佈局,應該在這兩個函數中對view進行位置的設置。
case 4
關於展現用的數據,除非必要,不建議用額外的屬性/成員變量保存。而直接經過modelManager的函數得到。以便由modelManager控制數據保存的位置是內存變量,仍是持久化方式。
實在須要在內部函數間傳遞,也儘可能根據最小知道原則,保存索引,狀態值之類的數據。
四、modelManager
modelmananger負責從一個或多個數據源,採集數據業務操做後提供給VC,數據來源多是數據庫,內存緩存,網絡等中的一個或多個。
開發場景
case 1
對VC隱藏數據源的原始數據結構。
也就是說盡可能不要把數據源原始數據直接交給VC,而應該與VC約定好相互之間須要傳遞的最小單元(實體/瘦model),把從一個或多個數據源獲取的原始數據,轉化成該最小單元。提供給VC
case 2
與VC交互的協議接口定義,應足夠獨立,一個事件/一次數據請求,一般不該該須要調用到其餘接口(這裏不是說不能調其餘內部函數,而是對VC 開放的其餘接口)
case 3
接口實現優先進行內存操做,內存沒有的數據再操做數據庫,尚未再進行網絡操做。實現多級緩存及時反饋。
case 4
頁面之間的數據變動響應,應該在modelManager之間通知和響應
具體來講:
vc1某操做,致使vc1的modelManager有數據變動,這個變動影響到v2,那麼不該該由v2去接受這個變動通知,而應該由vc2的modelManager接受並修改自身的數據,經過本身的數據變動接口通知vc2。
也就是說一個VC只接受一個modelManager的數據更新通知。
case 5
儘管上面的建議一個VC只對應一個modelManager。但有些場景下,多個VC能夠共享一個modelManager。
例:
設置功能下有多個子設置項,這些設置項是不一樣子頁面操做去設置的而且很簡單,當咱們把設置項的數據做爲一個總體去考慮的時候,這些子設置項操做的其實應該是同一個數據對象。此時應該支持這些頁面傳遞modelManager對象來共享它。
五、其餘衍生組件
在MVC的框架下,可根據功能單一原則,拆分出多個功能組件,供三大框架模塊使用,好比數據庫模塊,網絡模塊,加密模塊,播放器模塊等等。
3、代碼優化建議
case 1
任何狀況下老是使用setValue:forKey代替setObject:forKey
由於前者在value非nil狀況下等於後者。
在value爲nil刪除key所對應的鍵值。因爲賦值時通常當前並不會存在key的鍵值,即便是覆蓋某對鍵值,在值爲空的狀況下,刪除了它也是合理的。
因此前者效果徹底等效於檢測value非空後調用後者。
後者object爲nil則直接crash。
因此使用setValue:forKey更安全。
case 2
隱藏沒必要要的接口和屬性。
那些只在內部使用的屬性和函數,應定義在類擴展之中,把少數願意暴露出去的函數和屬性定義在頭文件中。
case 3
儘可能不要使用成員變量,用類擴展中的屬性代替它。而後老是使用self.去訪問它。
這樣有更清晰的內存管理。
而且,當有一天你忽然須要在賦值或者取值的時候作一些事情的時候,你就只須要在set/get中操做。而不用整個類裏面處處修改了。
case 4
儘可能不要阻塞主線程,儘可能把非UI操做放到其餘線程執行,完成後回到主線程通知UI刷新。
case 5
NSSet/NSArray,他們的區別是,NSSet是無序的,當一個數據集合不關注排序時,使用NSSet,查找元素是否存在和移除效率是高於NSArray的。
例:
維護一個操做中的數據集合,操做開始後加到集合中,操做完成後移除出集合,這種狀況下應當使用NSSet
case 6
不管何時經過索引訪問數組都應該進行越界判斷。或者try catch
case 7
懶加載,對不經常使用的View,不要在頁面打開時就建立,採用懶加載的方式去實現。以減小頁面啓動時間。
case 8
預加載,對於加載速度比較慢,又須要進入頁面就直接顯示的數據,考慮在適當的時間提早加載好,駐留在內存中。空間換時間。
case 9
tableView的使用除了注意cell正確重用之外,還需注意,數據源的count變化,特別是變小是要及時reloadData。若是使用insertRow/removerow操做,必定要保證數據源數量等於變化前數量加/減變化數量,不然就會crash
case 10
實體中只能進行簡單的數據操做,例如json轉字典,數值轉字符,取整之類的。不能進行業務操做,如存取數據庫,網絡操做等。
case 11
使用大量臨時變量時,可用@autoreleasepool來包含起來及時釋放。