iOS 代碼實(shí)踐總結(jié)
前幾個(gè)月完成對(duì)MVVM/RAC的學(xué)習(xí)之后,最近一直在默默地對(duì)項(xiàng)目代碼進(jìn)行重構(gòu),寫(xiě)碼比較多,過(guò)了一段時(shí)間回頭發(fā)現(xiàn)自己的代碼風(fēng)格還有代碼質(zhì)量都有大大的改善。過(guò)去幾年在一家小公司負(fù)責(zé)iOS客戶端后來(lái)負(fù)責(zé)客戶端的研發(fā)工作,被雜亂的事情分神比較多,所以到去年的時(shí)候,寫(xiě)碼已經(jīng)不太多了。在新公司待了大半年,目前只是寫(xiě)碼的小角色,所以精力基本上在寫(xiě)業(yè)務(wù)代碼和業(yè)余學(xué)習(xí)亂七八糟的技術(shù)上面。
最近一個(gè)月除了專門(mén)抽時(shí)間和精力重構(gòu)之外,還有就是遇到需要添加功能的模塊的時(shí)候,由于項(xiàng)目中的代碼歷史因素比較多,***件干的事情往往是重構(gòu)整理代碼,發(fā)現(xiàn)很多之前的代碼寫(xiě)的時(shí)候沒(méi)有注意的事情特別多,比如全局變量亂用;方法沒(méi)有層次感,胡亂添加;對(duì)業(yè)務(wù)不了解的情況下,通過(guò)打補(bǔ)丁的方式實(shí)現(xiàn)功能等等。所以我決定寫(xiě)一篇文章,把自己的覺(jué)得實(shí)踐中需要注意的一些事項(xiàng),具體總結(jié)一下分享給大家。
減少對(duì)象屬性
這個(gè)是最容易改善代碼質(zhì)量的一個(gè)點(diǎn),很多代碼一眼看上去就會(huì)讓人感覺(jué)很凌亂,一上來(lái)就是幾十個(gè)不同的對(duì)象變量定義在里面,這讓不同邏輯之間莫名其妙沒(méi)法分開(kāi)。一個(gè)是定義的方式不對(duì),很多莫名其妙的內(nèi)部變量暴露在頭文件中,讓外部調(diào)用者根本不知道哪些才是public可以操作的方法。另外實(shí)際上,經(jīng)過(guò)我自己這段時(shí)間的重構(gòu)經(jīng)驗(yàn)來(lái)看,大多數(shù)是可以通過(guò)局部變量或者_(dá)_block變量來(lái)代替的。
1. 頭文件中盡可能少暴露變量或方法,而要使用extension或者category放在.m文件,或者專門(mén)的private頭文件中
頭文件中暴露的信息越少越好,一切不必要的信息都不要暴露出來(lái)
m文件的extension中,定義conforms protocol和對(duì)象屬性,對(duì)于對(duì)象屬性的定義,使用getter/setter 來(lái)定義。
2. 使用局部變量或者_(dá)_block變量代替
局部變量不需要多說(shuō),需要寫(xiě)碼的時(shí)候思路清晰一些,寫(xiě)完之后在commit之前即使review一定要check一遍,對(duì)自己的代碼質(zhì)量負(fù)責(zé),code review往往檢查不出來(lái)冗余或者廢棄的代碼。不添加一個(gè)多余的對(duì)象屬性,不留注釋掉的代碼,不留沒(méi)有用途的代碼,這些都是基本功,但是很多開(kāi)發(fā)者就是做不到,或者說(shuō)對(duì)寫(xiě)碼沒(méi)有愛(ài),所以很多廢棄的代碼,我重構(gòu)代碼的時(shí)候,雖然對(duì)業(yè)務(wù)不熟悉,但是大多數(shù)模塊都能刪除掉十分之一的代碼和大量的對(duì)象屬性,這個(gè)是單純的不夠用心。
關(guān)于使用__block變量,這個(gè)是Android開(kāi)發(fā)中我感覺(jué)到最不滿意的地方,這個(gè)特性簡(jiǎn)直太他媽爽了。
比如這里,使用block的時(shí)候回傳一些變量
再比如這里,我需要記錄一個(gè)pan手勢(shì)開(kāi)始時(shí),headerView的頂部坐標(biāo),結(jié)合RAC之后,本來(lái)需要全局變量來(lái)記錄的值,使用__block變量即可搞定
3. 可以盡可能避免循環(huán)引用
有個(gè)地方很多開(kāi)發(fā)者會(huì)疏漏,在block中使用_XXX對(duì)象變量的時(shí)候,block會(huì)retain self指針,一不小心就會(huì)造成循環(huán)引用的出現(xiàn)。所以使用局部變量的話,就能扼殺這種問(wèn)題在搖籃之中。
減少和模塊化對(duì)象消息
1. 減少對(duì)象消息
減少UI的action類消息,感謝block和RAC,或者blockskit,讓我們得以通過(guò)hook來(lái)把之前target-action模型換為block來(lái)實(shí)現(xiàn),UI和action的代碼終于可以一起了,使整個(gè)邏輯變得緊湊,在查看代碼的時(shí)候終于不用跳來(lái)跳去了。還有就是日常開(kāi)發(fā)中,把自己寫(xiě)的各種protocol或者傳遞target/selector的地方,盡量使用block來(lái)代替,相信我,這個(gè)會(huì)使代碼好讀很多。
2. 模塊化
使用”#pragma mark - XXX”進(jìn)行分割不同邏輯之間的界限,讓整個(gè)文件閱讀起來(lái)更加結(jié)構(gòu)化。還有一個(gè)我現(xiàn)在最常用的就是是設(shè)置Xcode的快捷鍵,把Ctrl + 6 顯示文檔結(jié)構(gòu)的快捷鍵改為:Command + J ,搜索來(lái)快速跳轉(zhuǎn)到對(duì)應(yīng)的消息和模塊,要盡量避免文檔結(jié)構(gòu)顯示超過(guò)兩屏幕,超過(guò)兩屏幕說(shuō)明有點(diǎn)多了,你肯定考慮一下重構(gòu)了。
我個(gè)人習(xí)慣一般劃分的模塊有: life cycle,ui helper,datasource/delegate,依據(jù)功能進(jìn)行劃分的模塊等等,如下是我最近重構(gòu)的一個(gè)ViewController的文檔結(jié)構(gòu)
MVVM && RAC
我自己使用MVVM思路的感覺(jué)是太爽了,說(shuō)一下,MVVM不一定需要使用RAC,但是data binding少不了,在iOS中也就是KVO了,建議大家都去嘗試一下,我自己感覺(jué)這個(gè)基本上MVVM的最核心的東西了,連Android SDK也不得不引入這個(gè)特性。把數(shù)據(jù)部分的邏輯抽取放在ViewModel中,然后讓UI和ViewModel中的數(shù)據(jù)binding,這個(gè)不會(huì)減少代碼量,但是絕對(duì)可以大大簡(jiǎn)化開(kāi)發(fā)時(shí)邏輯的復(fù)度,再也不用重寫(xiě)-setXXX:方法來(lái)update一大堆不相關(guān)的UI了,關(guān)于UI開(kāi)發(fā),后面會(huì)專門(mén)再講講新的。這里說(shuō)一下我自己的理解,有人說(shuō)RAC影響性能,回調(diào)棧太深,這個(gè)的確是會(huì)有的,但是個(gè)人感覺(jué)RACObserver是基于KVO實(shí)現(xiàn)的,調(diào)用的時(shí)候是同步調(diào)用的,所以對(duì)性能的影響有限,也不會(huì)出現(xiàn)調(diào)用順序的問(wèn)題,所以我敢在列表開(kāi)發(fā)中使用data binding,實(shí)踐之后還好,對(duì)用戶體驗(yàn)沒(méi)什么影響。
關(guān)于RAC,即使你不使用RAC,有一些東西也是絕對(duì)值得你在項(xiàng)目中引入的,比如@weakify(self)/@strongify(self),通過(guò)預(yù)編譯查看的話,這個(gè)的做法是設(shè)置一個(gè)局部變量self來(lái)覆蓋全局的self,進(jìn)而避免循環(huán)引用的,需要注意的是block層次較深的時(shí)候使用的問(wèn)題,http://stackoverflow.com/questions/21716982/explanation-of-how-weakify-and-strongify-work-in-reactivecocoa-libextobjc。
RAC/MVVM,我剛開(kāi)始學(xué)習(xí)的時(shí)候,寫(xiě)了兩篇文章,算是我自己的總結(jié),理解上面還有不足,跟大家參考一下:http://blog.csdn.net/colorapp/article/details/46524893,http://blog.csdn.net/colorapp/article/details/46537729。大家可以通過(guò)我博客中文章的參考鏈接學(xué)習(xí)。
UI開(kāi)發(fā)
1. 重寫(xiě)setter方法和Code Block Evaluation C Extension語(yǔ)法
重寫(xiě)UI的getter方法,把UI的初始化放在getter中,減輕 -viewDidLoad的負(fù)荷,同時(shí)可以使整個(gè)頁(yè)面變得清晰;同時(shí),可以通過(guò)使用使用GCC Code Block Evaluation C Extension ({…})語(yǔ)法,結(jié)構(gòu)化局部變量初始化和處理的邏輯。關(guān)于這個(gè)語(yǔ)法,參考我之前的博客:http://blog.csdn.net/colorapp/article/details/47006771。關(guān)于setter代碼風(fēng)格,可以參考別人寫(xiě)的一篇文章,http://casatwy.com/iosying-yong-jia-gou-tan-viewceng-de-zu-zhi-he-diao-yong-fang-an.html,這個(gè)問(wèn)題之前在我們Q群里探討之后我也非常認(rèn)同這種方式寫(xiě)UI。
舉一個(gè)例子,-viewDidLoad中,做為邏輯的入口,代碼會(huì)變少但是變清晰,代碼如下:
然后重寫(xiě)bgView的getter方法,包括View和frame這些都可以使用({...})語(yǔ)法使代碼結(jié)構(gòu)化層次化:
2. 復(fù)雜UI的開(kāi)發(fā)
有時(shí)候我們開(kāi)發(fā)業(yè)務(wù)的時(shí)候,產(chǎn)品需求往往非常復(fù)雜,酷炫的UI加上各種考慮全面的邏輯,這個(gè)的結(jié)果就是,碼農(nóng)的超長(zhǎng)代碼,而我們平時(shí)工作面對(duì)的也大多數(shù)都是這類問(wèn)題。關(guān)于這個(gè)問(wèn)題,我的解決方式,組合式UI / custom view / child view controller來(lái)解決。
(1) 組合式view
這個(gè)概念是從Android中借鑒而來(lái)。重構(gòu)時(shí)查看項(xiàng)目中的代碼,發(fā)現(xiàn)大家用的做UI的時(shí)候,對(duì)這個(gè)概念不是很強(qiáng)烈,感覺(jué)是對(duì)UIView的view hierarchy理解不夠。比如一個(gè)復(fù)雜的UI,直接把所有的subviews直接堆積到super view上面,這樣的結(jié)果就是,調(diào)整subview的frame非常困難。我個(gè)人的做法是,首先對(duì)復(fù)雜UI進(jìn)行分塊,從左到右或者從上倒下,把各個(gè)UI元素放到不同的container view上面,然后組合這些container view放到super view上面,這樣的好處非常明顯,首先UI干凈清晰,閱讀起來(lái)不那么費(fèi)勁。其次就是你計(jì)算坐標(biāo)或者設(shè)置約束會(huì)變得很簡(jiǎn)單,因?yàn)槟阏{(diào)整一個(gè)UI元素的時(shí)候,只需要考慮它與包含它的container view的坐標(biāo)關(guān)系即可,而不是通過(guò)一大堆無(wú)趣計(jì)算跟最外層super view關(guān)聯(lián)起來(lái)。還有就是可以充分利用Auto Layout和autoresiziingmask這些UI利器,使用的時(shí)候會(huì)非常方便。再有就是結(jié)合RACObserver這個(gè)利器之后,你能很容易做到根據(jù)data來(lái)update ui。
舉個(gè)例子,是我們項(xiàng)目中前一段時(shí)間我重構(gòu)的一個(gè)頁(yè)面,這個(gè)首頁(yè)列表,性能要求比較高。并沒(méi)有使用Auto Layout來(lái)實(shí)現(xiàn),但是不使用Auto Layout并不是不把它寫(xiě)的很干凈的理由。
這是我對(duì)一個(gè)UITableViewCell的分層,最外層由 icon view / right view / bottom view這些container view組成,而right view這個(gè)container view則又是由right top view / right middle view /right bottom view 這些 sub container view組合而成,而具體的UI元素則是放在這些sub container view之中。這樣UI代碼就會(huì)以一種層次化樣式展示出來(lái),init/layoutsubviews只需要維護(hù)self與container view的關(guān)系即可,而具體展示數(shù)據(jù)的UI元素也只跟sub container view存在坐標(biāo)關(guān)系。我們看一下right view這個(gè)container view的代碼實(shí)現(xiàn):
關(guān)于性能的話,感謝iOS,我們不存在Android中頁(yè)面層次較深性能卡頓的問(wèn)題,放心把UI層次化就行
(2) custom view
對(duì)于非常復(fù)雜并且相對(duì)獨(dú)立或者可以重用的UI,及時(shí)使用custom view子類化。對(duì)于單純的展示UI,我們只需要簡(jiǎn)單通過(guò)組合式view就可以實(shí)現(xiàn)了。但是有時(shí)候,我們會(huì)遇到一些包含無(wú)論是動(dòng)畫(huà),邏輯都比較復(fù)雜的情況,這個(gè)時(shí)候使用組合式View去實(shí)現(xiàn),一方面容易把邏輯弄混亂,會(huì)把文件的文檔結(jié)構(gòu)變得很復(fù)雜,簡(jiǎn)單來(lái)說(shuō)就是對(duì)象的消息數(shù)量很多。這個(gè)時(shí)候,我們可以通過(guò)custom view來(lái)實(shí)現(xiàn),實(shí)際上這個(gè)也是組合式view,但是我們是把這些組合式view變成了一個(gè)類而已,只暴露少量的接口給外部調(diào)用。如果這個(gè)custom view會(huì)出現(xiàn)在多個(gè)業(yè)務(wù)模塊中,那么有必要使用一個(gè)單獨(dú)的文件來(lái)容納這個(gè)類,如果僅僅是這個(gè)模塊一個(gè)使用的話,可以直接寫(xiě)在這個(gè)業(yè)務(wù)模塊的文件中即可,沒(méi)有必要對(duì)所有的類都單獨(dú)一個(gè)文件,我們就當(dāng)作這個(gè)“內(nèi)部類”來(lái)弄了。
什么時(shí)候使用custom view而不是組合view,我想了很久,你覺(jué)得組合式view的代碼很亂的時(shí)候,別客氣,包裝為一個(gè)custom view就行了。我這邊最近遇到的幾個(gè)問(wèn)題是使用UICollectionView來(lái)做部分UI的時(shí)候,同時(shí)還有其他很多UI元素,我會(huì)寫(xiě)一個(gè)custom view。比如下面這個(gè)文件,把一個(gè)左右滑動(dòng)查看圖片的UI使用PhotoView這個(gè)custom view進(jìn)行包裝,內(nèi)部使用UICollectionView實(shí)現(xiàn)一部分相對(duì)獨(dú)立的模塊,這個(gè)時(shí)候這個(gè)控件實(shí)際上是可以包裝為一個(gè)相對(duì)獨(dú)立的模塊的,用子類我感覺(jué)比較合適一些。
(3) container view controller
這個(gè)用法很多開(kāi)發(fā)者不熟悉或者說(shuō)是用的不多,但實(shí)際業(yè)務(wù)中,這個(gè)技術(shù)非常有用途,可以大大提高開(kāi)發(fā)效率。對(duì)這部分知識(shí)不熟悉的,可以參考我之前的博客:http://blog.csdn.net/colorapp/article/details/45765601。對(duì)于有相對(duì)獨(dú)立業(yè)務(wù)邏輯以及生命周期要求的業(yè)務(wù),使用child view controller進(jìn)行包裝,如果parent view contrller與child view controller之間非常密切,則使用View Model以及block來(lái)對(duì)parent view controller和 child view controller 進(jìn)行銜接。
使用child view controller來(lái)開(kāi)發(fā)UI而不是custom view的優(yōu)勢(shì)很多,我個(gè)人認(rèn)為***優(yōu)勢(shì)在于可以方便利用View Controller的生命周期以及View Controller Hierarchy,比如在-viewWillAppear/-viewDidDisappear中做一些操作,再比如直接獲取UINavigationController指針等等。之前的做法一般是在View Controller的對(duì)應(yīng)生命周期內(nèi)調(diào)用custom view的方法,傳遞self.navigationController指針給custom view等。所以可以不僅僅把UI相關(guān)的代碼包裝進(jìn)入這個(gè)child view controller,也可以把網(wǎng)絡(luò)請(qǐng)求,數(shù)據(jù)處理這些這些邏輯放到child view controller中,這樣下來(lái)就能避免那種動(dòng)不動(dòng)超過(guò)1k行的view controller的出現(xiàn)了。
利用MVVM之后,還有一個(gè)比較有好處的用法,比如公用一些數(shù)據(jù)的時(shí)候,之前我們是把對(duì)象傳遞來(lái)傳遞去,這樣的問(wèn)題是很容易出現(xiàn)混亂,這個(gè)時(shí)候我們是傳遞ViewModel就可以避免這個(gè)問(wèn)題,ViewModel既負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求又負(fù)責(zé)數(shù)據(jù)處理,而parent view controller與child view controller所需要做的事情就是跟ViewModel進(jìn)行binding而已。
Auto Layout/Masonry
在一些性能要求不是那么強(qiáng)烈的非列表頁(yè),我們可以大量使用Auto Layout來(lái)開(kāi)發(fā)UI,充分利用UI根據(jù)數(shù)據(jù)的自適應(yīng)能力,連在container view中調(diào)整UI的步驟都不需要了。之前有一段時(shí)間我根本不想開(kāi)發(fā)iOS,原因很簡(jiǎn)單,Android的布局式以及可見(jiàn)式的開(kāi)發(fā)方式非常方便,再加上AS這樣的神器,我自己感覺(jué)效率不比iOS低。自從項(xiàng)目***支持變到iOS6之后,我才開(kāi)始使用Auto Layout,雖然比較費(fèi)勁,但是感覺(jué)這個(gè)對(duì)UI開(kāi)發(fā)來(lái)說(shuō)是個(gè)解脫。
至于Masonry這個(gè)框架,之前我對(duì)這個(gè)抱有一定的懷疑不敢使用,所以我把源碼讀了一遍,發(fā)現(xiàn)這個(gè)包裝很薄很巧妙,很多設(shè)計(jì)思路也值得借鑒,對(duì)源碼有興趣的可以參考我的博客:http://blog.csdn.net/colorapp/article/details/45030163。我讀完源碼之后,嘗試著完全使用Mansory來(lái)開(kāi)發(fā)一個(gè)展示信息的頁(yè)面,感覺(jué)太爽了!
這個(gè)的優(yōu)勢(shì)就是你設(shè)置UI的數(shù)據(jù)之后,不需要再考慮去update ui了,這樣世界瞬時(shí)就清凈了。。。。,下面是我一個(gè)簡(jiǎn)單的示例,結(jié)合({….})語(yǔ)法和RAC,可以使用最簡(jiǎn)單的label這樣的命名來(lái)對(duì)UI設(shè)置數(shù)據(jù),這個(gè)對(duì)我們開(kāi)發(fā)UI來(lái)說(shuō),絕對(duì)是一種解脫。
說(shuō)一下Auto Layout的問(wèn)題:
1. 首先一個(gè)問(wèn)題,是如果一個(gè)view不是leaf view的話,那么這個(gè)UIView如果hidden的話,它的約束仍然是work的,所以會(huì)留下空白,不會(huì)像Android中那樣設(shè)置GONE那么方便。國(guó)內(nèi)sunny大神開(kāi)源一個(gè)不錯(cuò)的解決方式,https://github.com/forkingdog/UIView-FDCollapsibleConstraints。這里說(shuō)一下我之前的解決方式,比較土逼,直接子類化:
2. 動(dòng)畫(huà)的問(wèn)題
使用Auto Layout有一個(gè)比較大的問(wèn)題在于動(dòng)畫(huà),通過(guò)更改約束來(lái)進(jìn)行動(dòng)畫(huà),一直是我比較頭疼的問(wèn)題,所以一般遇到這類問(wèn)題的時(shí)候,我都會(huì)盡量避免使用Auto Layout來(lái)解決,而是使用frame的方式來(lái)做??梢詤⒖紀(jì)bjc.io上面的一篇文章:http://www.objc.io/issues/3-views/advanced-auto-layout-toolbox/。
3. 多行UILabel的問(wèn)題
iOS7以及以下的操作系統(tǒng)上,UILabel顯示多行文本是又不足的,你需要設(shè)置UILabel的preferredMaxLayoutWidth為一個(gè)固定值才能顯示多行文本。在iOS8以后就不再需要設(shè)置這個(gè)了。
4. UIScrollView的問(wèn)題以及約束歧義和其他問(wèn)題
參考我的文章:http://blog.csdn.net/colorapp/article/details/47007143
這個(gè)地方,我的建議是根據(jù)具體問(wèn)題來(lái)選擇實(shí)現(xiàn)方式 :spring & structs也好,Auto Layout也好,那種解決問(wèn)題較為簡(jiǎn)潔快速就用那種,不一定非要固定于一種行為,尤其是開(kāi)發(fā)的頁(yè)面有大量動(dòng)畫(huà)的時(shí)候。
注釋
不要寫(xiě)一堆中文注釋,代碼不要出現(xiàn)大量的中文,OC已經(jīng)夠啰嗦,不要這么啰嗦地寫(xiě)碼。除了提供服務(wù)的public功能或者方法,業(yè)務(wù)代碼僅在某些關(guān)鍵點(diǎn)上注釋一下就行,不需要一大堆中文,這樣太low,代碼自注釋即可,需要注釋的,可以通過(guò)喵神的Xcode插件來(lái)實(shí)現(xiàn),https://github.com/onevcat/VVDocumenter-Xcode。
而對(duì)于出現(xiàn)拼音命名代碼的人,能做主的話,別猶豫,開(kāi)掉吧。這里吐一下槽,之前的公司就有這樣的哥們,不是我招進(jìn)來(lái)的,老板硬塞給我的。
善用OC的新語(yǔ)法
OC有很多新的語(yǔ)法糖,可以大大提高我們的效率,參考Apple Guide:https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html。
比如打印數(shù)字的時(shí)候,我們可以用@(xxx)來(lái)打印,定義枚舉的時(shí)候使用typedef NS_ENUM,使用instancetype而不用id等等。而最近又到了每年技能槽刷新的日子了,iOS 9發(fā)布了,OC又有了一些新語(yǔ)法,去學(xué)習(xí)一下多用用吧。
JSON數(shù)據(jù)的處理
新手往往會(huì)被這個(gè)稍微困惑一下,比如服務(wù)器返回的數(shù)據(jù)格式不正確啦,包含null啦,都很容易引起項(xiàng)目崩潰。這個(gè)問(wèn)題可以使用Mantle來(lái)解決,很多兄弟都在使用這個(gè),我自己倒是一直沒(méi)有用過(guò)。之前寫(xiě)了一個(gè)小框架放在了github上面,https://github.com/lihei12345/CYJSONValidator,這個(gè)在我們項(xiàng)目?jī)?nèi)部也在使用,效果不錯(cuò),用來(lái)解析數(shù)據(jù)的時(shí)候,對(duì)數(shù)據(jù)的類型以及是否為null等進(jìn)行校驗(yàn),確保解析出來(lái)數(shù)據(jù)類型的正確性。對(duì)于可能不存在key的時(shí)候,還可以設(shè)置一些默認(rèn)值。
舉個(gè)例子:
block
使用block代替delegate,這個(gè)沒(méi)啥可多說(shuō)的,把代碼變得非常緊湊,減少文件的消息數(shù)量,最主要的是關(guān)系沒(méi)那么緊密了。對(duì)于有大量的delegate方法才考慮使用protocol實(shí)現(xiàn),這個(gè)時(shí)候block太多也影響閱讀。
同時(shí),對(duì)于傳遞target/selector,也盡量使用block吧,這種閱讀查找起來(lái)太不方便了。
提交代碼
及時(shí)stage,這個(gè)非常重要,開(kāi)發(fā)過(guò)程中經(jīng)常需要經(jīng)常比對(duì)上一步的代碼,這樣才能***程度上確保自己的改動(dòng)是正確的。如果有一些小問(wèn)題,也可以即使找到歷史版本。
及時(shí)commit,每完成一個(gè)相對(duì)完整的需求,就commit,小提交是個(gè)好習(xí)慣。
PR code review要做好,要花大量的時(shí)間做,有條件的話,***每個(gè)版本開(kāi)一次總結(jié)會(huì)。
RAC封裝網(wǎng)絡(luò)請(qǐng)求
返回的signal要避免多次出現(xiàn)side effect,但不使用replay/replayLazily,因?yàn)閐ispose不會(huì)被調(diào)用。
使用RACCommand封裝請(qǐng)求,查看這幾篇文章:http://codeblog.shape.dk/blog/2013/12/05/reactivecocoa-essentials-understanding-and-using-raccommand/,https://github.com/ReactiveCocoa/ReactiveCocoa/issues/963,https://github.com/ReactiveCocoa/ReactiveCocoa/issues/1326。
結(jié)合RACCommand和takeUntil:來(lái)封裝一個(gè)可以cancel的請(qǐng)求。