架構(gòu)師不是寫SDK出來交付業(yè)務(wù)方使用就沒事兒了的笨奠,每家公司一定都有一套代碼規(guī)范,架構(gòu)師的職責(zé)也包括定義代碼規(guī)范波势。按照道理來講或辖,定代碼規(guī)范應(yīng)該是屬于通識,放在這里講的原因只是因?yàn)槲疫@邊需要為View添加一個(gè)規(guī)范橙依。
制定代碼規(guī)范嚴(yán)格來講不屬于View層架構(gòu)的事情证舟,但它對View層架構(gòu)未來的影響會(huì)比較大,也是屬于架構(gòu)師在設(shè)計(jì)View層架構(gòu)時(shí)需要考慮的事情窗骑。制定View層規(guī)范的重要性在于:
提高業(yè)務(wù)方View層的可讀性可維護(hù)性
防止業(yè)務(wù)代碼對架構(gòu)產(chǎn)生腐蝕
確保傳承
保持架構(gòu)發(fā)展的方向不輕易被不合理的意見所左右
在這一節(jié)里面我不打算從頭開始定義一套規(guī)范女责,蘋果有一套Coding Guidelines,當(dāng)我們定代碼結(jié)構(gòu)或規(guī)范的時(shí)候创译,首先一定要符合這個(gè)規(guī)范抵知。
然后,相信大家各自公司里面也都有一套自己的規(guī)范软族,具體怎么個(gè)規(guī)范法其實(shí)也是根據(jù)各位架構(gòu)師的經(jīng)驗(yàn)而定刷喜,我這邊只是建議各位在各自規(guī)范的基礎(chǔ)上再加上下面這一點(diǎn)。
viewController的代碼應(yīng)該差不多是這樣:
要點(diǎn)如下:
所有的屬性都使用getter和setter
不要在viewDidLoad里面初始化你的view然后再add互订,這樣代碼就很難看吱肌。在viewDidload里面只做addSubview的事情,然后在viewWillAppear里面做布局的事情(勘誤1)仰禽,最后在viewDidAppear里面做Notification的監(jiān)聽之類的事情氮墨。至于屬性的初始化纺蛆,則交給getter去做。
比如這樣:
#pragma mark - life cycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.firstTableView];
[self.view addSubview:self.secondTableView];
[self.view addSubview:self.firstFilterLabel];
[self.view addSubview:self.secondFilterLabel];
[self.view addSubview:self.cleanButton];
[self.view addSubview:self.originImageView];
[self.view addSubview:self.processedImageView];
[self.view addSubview:self.activityIndicator];
[self.view addSubview:self.takeImageButton];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CGFloat width = (self.view.width - 30) / 2.0f;
self.originImageView.size = CGSizeMake(width, width);
[self.originImageView topInContainer:70 shouldResize:NO];
[self.originImageView leftInContainer:10 shouldResize:NO];
self.processedImageView.size = CGSizeMake(width, width);
[self.processedImageView right:10 FromView:self.originImageView];
[self.processedImageView topEqualToView:self.originImageView];
CGFloat labelWidth = self.view.width - 100;
self.firstFilterLabel.size = CGSizeMake(labelWidth, 20);
[self.firstFilterLabel leftInContainer:10 shouldResize:NO];
[self.firstFilterLabel top:10 FromView:self.originImageView];
... ...
}
這樣即便在屬性非常多的情況下规揪,還是能夠保持代碼整齊桥氏,view的初始化都交給getter去做了∶颓Γ總之就是盡量不要出現(xiàn)以下的情況:
- (void)viewDidLoad
{
[super viewDidLoad];
self.textLabel = [[UILabel alloc] init];
self.textLabel.textColor = [UIColor blackColor];
self.textLabel ... ...
self.textLabel ... ...
self.textLabel ... ...
[self.view addSubview:self.textLabel];
}
這種做法就不夠干凈字支,都扔到getter里面去就好了。關(guān)于這個(gè)做法奸忽,在唐巧的技術(shù)博客里面有一篇文章和我所提倡的做法不同堕伪,這個(gè)我會(huì)放在后面詳細(xì)論述。
getter和setter全部都放在最后
因?yàn)橐粋€(gè)ViewController很有可能會(huì)有非常多的view栗菜,就像上面給出的代碼樣例一樣欠雌,如果getter和setter寫在前面,就會(huì)把主要邏輯扯到后面去疙筹,其他人看的時(shí)候就要先劃過一長串getter和setter富俄,這樣不太好。然后要求業(yè)務(wù)工程師寫代碼的時(shí)候按照順序來分配代碼塊的位置而咆,先是life cycle霍比,然后是Delegate方法實(shí)現(xiàn),然后是event response暴备,然后才是getters and setters悠瞬。這樣后來者閱讀代碼時(shí)就能省力很多。
每一個(gè)delegate都把對應(yīng)的protocol名字帶上馍驯,delegate方法不要到處亂寫阁危,寫到一塊區(qū)域里面去
比如UITableViewDelegate的方法集就老老實(shí)實(shí)寫上#pragma mark - UITableViewDelegate。這樣有個(gè)好處就是汰瘫,當(dāng)其他人閱讀一個(gè)他并不熟悉的Delegate實(shí)現(xiàn)方法時(shí)狂打,他只要按住command然后去點(diǎn)這個(gè)protocol名字,Xcode就能夠立刻跳轉(zhuǎn)到對應(yīng)這個(gè)Delegate的protocol定義的那部分代碼去混弥,就省得他到處找了趴乡。
event response專門開一個(gè)代碼區(qū)域
所有button、gestureRecognizer的響應(yīng)事件都放在這個(gè)區(qū)域里面蝗拿,不要到處亂放晾捏。
關(guān)于private methods,正常情況下ViewController里面不應(yīng)該寫
不是delegate方法的哀托,不是event response方法的惦辛,不是life cycle方法的,就是private method了仓手。對的胖齐,正常情況下ViewController里面一般是不會(huì)存在private methods的玻淑,這個(gè)private methods一般是用于日期換算、圖片裁剪啥的這種小功能呀伙。這種小功能要么把它寫成一個(gè)category补履,要么把他做成一個(gè)模塊,哪怕這個(gè)模塊只有一個(gè)函數(shù)也行剿另。
ViewController基本上是大部分業(yè)務(wù)的載體箫锤,本身代碼已經(jīng)相當(dāng)復(fù)雜,所以跟業(yè)務(wù)關(guān)聯(lián)不大的東西能不放在ViewController里面就不要放雨女。另外一點(diǎn)谚攒,這個(gè)private method的功能這時(shí)候只是你用得到,但是將來說不定別的地方也會(huì)用到戚篙,一開始就獨(dú)立出來五鲫,有利于將來的代碼復(fù)用。
勘誤1:其實(shí)在viewWillAppear這里改變UI元素不是很可靠岔擂,Autolayout發(fā)生在viewWillAppear之后,嚴(yán)格來說這里通常不做視圖位置的修改浪耘,而用來更新Form數(shù)據(jù)乱灵。改變位置可以放在viewWilllayoutSubview或者didLayoutSubview里,而且在viewDidLayoutSubview確定UI位置關(guān)系之后設(shè)置autoLayout比較穩(wěn)妥七冲。另外痛倚,viewWillAppear在每次頁面即將顯示都會(huì)調(diào)用,viewWillLayoutSubviews雖然在lifeCycle里調(diào)用順序在viewWillAppear之后澜躺,但是只有在頁面元素需要調(diào)整時(shí)才會(huì)調(diào)用蝉稳,避免了Constraints的重復(fù)添加。