iOS項(xiàng)目重構(gòu)周記(一)

最近開(kāi)始做公司的iOS項(xiàng)目重構(gòu)惹悄,現(xiàn)準(zhǔn)備每周做一次匯總春叫,把重構(gòu)過(guò)程中遇到的問(wèn)題和解決方案記錄下來(lái),做一個(gè)記錄和分享泣港。

1.文件目錄結(jié)構(gòu)

我們?cè)赬code中使用“new group”創(chuàng)建一個(gè)新的目錄時(shí)暂殖,對(duì)應(yīng)的文件系統(tǒng)中并不會(huì)相應(yīng)的創(chuàng)建一個(gè)實(shí)體文件夾,只是在Xcode中創(chuàng)建一個(gè)便于管理的虛擬文件夾当纱。這樣就導(dǎo)致添加的所有文件最終都放在文件系統(tǒng)的同一目錄下呛每,這里面可能會(huì)包含.h文件、.m文件坡氯、nib文件晨横,圖片等等一系列的資源文件。當(dāng)項(xiàng)目最終變的比較龐大時(shí)箫柳,眾多的文件將變的極難管理手形。而且,當(dāng)我們使用SVN或Git來(lái)做版本控制時(shí)悯恍,一旦產(chǎn)生工程文件沖突库糠,重新添加文件也很難定位,并且容易遺漏文件涮毫。

所以我們應(yīng)該使用實(shí)體文件夾來(lái)構(gòu)建項(xiàng)目中的Group瞬欧,另外當(dāng)項(xiàng)目比較龐大時(shí)贷屎,Group的劃分也是需要斟酌的一項(xiàng)。好的結(jié)構(gòu)劃分能夠幫助我們快速定位代碼艘虎,有助于理解整個(gè)項(xiàng)目的架構(gòu)和邏輯豫尽。所以我建議基于以下幾條來(lái)區(qū)分目錄結(jié)構(gòu)。

  • 公共部分和各功能模塊的區(qū)分
    公共部分和各功能模塊應(yīng)該區(qū)分開(kāi)來(lái)顷帖,公共模塊一般包含公共模型、方法渤滞、視圖贬墩、第三方庫(kù)。我們寫(xiě)的任何可被其他功能模塊調(diào)用的組件都應(yīng)該包含到公共目錄下妄呕。

  • 資源類(lèi)型的區(qū)分
    所有的圖片陶舞、數(shù)據(jù)庫(kù)文件、bundle绪励、plist等等資源文件都應(yīng)該統(tǒng)一包含到資源目錄下肿孵。

  • MVC的區(qū)分
    各功能模塊都可按MVC來(lái)區(qū)分,視圖模型控制器的區(qū)分可以幫助自己和他人更快的定位代碼疏魏。

另外說(shuō)一下添加文件夾到工程中時(shí)停做,“Create groups”和“Create folder references”的區(qū)別。

img
img

Create group類(lèi)似于我們“new group”時(shí)創(chuàng)建的組大莫,其中包含的文件會(huì)自動(dòng)添加到Compile Sources中蛉腌,Create folder references只會(huì)引用文件夾,文件夾里面的東西都會(huì)直接拷貝到bundle包只厘,不參與編譯烙丛。

2.注釋

注釋也是重構(gòu)中的一部分,好的注釋能夠極大程度上幫助自己和他人理解代碼羔味。我相信對(duì)注釋負(fù)責(zé)的人河咽,也從側(cè)面證明是一個(gè)靠譜的人。只是這里要注意注釋的格式赋元。

這里推薦一個(gè)喵神寫(xiě)的自動(dòng)注釋工具:VVDocumentor
這是一個(gè)Xcode插件忘蟹,只需要在要寫(xiě)文檔的代碼上面連打三個(gè)斜杠,就能自動(dòng)提取參數(shù)等生成規(guī)范的Javadoc格式文檔注釋?zhuān)螺d編譯一下们陆,然后重啟Xcode就可以使用了寒瓦。

img
img

使用這種方式的注釋?zhuān)灰醋ption鍵+鼠標(biāo)左鍵,是可以在調(diào)用時(shí)直接查看注釋內(nèi)容的:
img
img

3.手寫(xiě)代碼 or Xib坪仇?

關(guān)于這個(gè)問(wèn)題相信很多同學(xué)都有困惑杂腰,國(guó)內(nèi)iOS界的大神唐巧和喵神對(duì)這個(gè)問(wèn)題也都有自己的見(jiàn)解,大家可以移步到他們的博客看看:
唐巧:http://blog.devtang.com/blog/2015/03/22/ios-dev-controversy-2/
喵神:http://onevcat.com/2013/12/code-vs-xib-vs-storyboard/
借用唐巧的幾句話:

  • 對(duì)于復(fù)雜的椅文、動(dòng)態(tài)生成的界面喂很,建議使用手工編寫(xiě)界面惜颇。
  • 對(duì)于需要統(tǒng)一風(fēng)格的按鈕或UI控件,建議使用手工用代碼來(lái)構(gòu)造少辣。方便之后的修改和復(fù)用凌摄。
  • 對(duì)于需要有繼承或組合關(guān)系的 UIView 類(lèi)或 UIViewController 類(lèi),建議用代碼手工編寫(xiě)界面漓帅。
  • 對(duì)于那些簡(jiǎn)單的锨亏、靜態(tài)的、非核心功能界面忙干,可以考慮使用 xib 或 storyboard 來(lái)完成器予。

4.多用類(lèi)型常量,少用#define

一個(gè)龐大的項(xiàng)目中捐迫,常常使用了大量的宏定義乾翔。宏定義的初衷之一是提高了程序的可讀性,同時(shí)也方便進(jìn)行修改施戴》磁ǎ可是過(guò)度的宏定義往往違背了它的初衷。

例如

#define ANIMATION_DURATION 0.3 

我們并不能很直觀的理解它其中的時(shí)間含義赞哗,而

static const NSTimeInterval kAnimationDuration = 0.3;

就很好的描述了常量的含義雷则。

此外,為什么要加一個(gè)static和const來(lái)同時(shí)命名肪笋?因?yàn)閟tatic意味著該變量?jī)H在定義此變量的編譯單元中可見(jiàn)巧婶。編譯器每收到一個(gè)編譯單元,就會(huì)相應(yīng)的輸出一份目標(biāo)文件(object file即.o文件)涂乌。假如我們不聲明static艺栈,編譯器就會(huì)為它創(chuàng)建一個(gè)“外部符號(hào)”。此時(shí)如果另一個(gè)編譯單元也聲明了一個(gè)同名變量湾盒,那么編譯器就會(huì)拋出一條錯(cuò)誤消息湿右。事實(shí)上,如果同時(shí)用static和const命名罚勾,編譯器根本不會(huì)創(chuàng)建符號(hào)毅人,而是會(huì)像#define預(yù)處理指令一樣,把所有遇到的變量都替換為常值尖殃。不過(guò)還是有一點(diǎn)區(qū)別的丈莺,用這種方式定義的常量是帶有類(lèi)型信息的。

不管是#define還是static const都不應(yīng)該在頭文件里聲明送丰,因?yàn)槌A棵Q很有可能互相沖突缔俄,如果一定要這么做的話,要加上前綴,表明它輸入哪個(gè)類(lèi)俐载。

再延伸的說(shuō)一下extern:
extern常用于NSNotification中等蟹略,供外部使用,extern常量放在“全局符號(hào)表”中遏佣,以便可以在定義該常量的編譯單元之外使用挖炬。這也是不用使用#import引入其所在頭文件的原因,需注意状婶,此類(lèi)常量必須要定義意敛,而且只能定義一次。

5.Reveal

對(duì)于龐大的項(xiàng)目膛虫,純代碼構(gòu)建的UI空闲,使用Reveal來(lái)調(diào)試界面的用處還是很大的∽叩校可以幫助我們更直觀的了解代碼,快速定位UI細(xì)節(jié)逗噩。顏色掉丽,位置,大小异雁,間距捶障,和View之間的相對(duì)關(guān)系都可以一目了然。Reveal甚至比Xcode自帶的Interface Builder做的還要好纲刀。對(duì)于越獄的設(shè)備项炼,Reveal還可以用來(lái)分析其他應(yīng)用程序的UI,實(shí)在是不可多得的利器示绊。

img
img

Reveal加載的三個(gè)方法

加載方法1

下載Reveal之后打開(kāi)锭部,在菜單中的Help中可以找到集成到Xcode項(xiàng)目的方法,這里不再贅述面褐。

加載方法2

此方法可以在不改變工程設(shè)置的前提下加載Reveal
打開(kāi)終端拌禾,輸入

vim ~/.lldbinit

LLDB每次啟動(dòng)的時(shí)候都會(huì)加載這個(gè)文件。輸入:

command alias reveal_load_sim expr (void*)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2);

command alias reveal_load_dev expr (void*)dlopen([(NSString*)[(NSBundle*)[NSBundle mainBundle] pathForResource:@"libReveal" ofType:@"dylib"] cStringUsingEncoding:0x4], 0x2);

command alias reveal_start expr (void)[(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];

command alias reveal_stop expr (void)[(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStop" object:nil];

然后輸入control+c展哭,w q enter退出終端湃窍。
上述文件創(chuàng)建了4個(gè)命令:

reveal_load_sim,reveal_load_dev, reveal_start 和 reveal_stop
  • reveal_load_sim 這個(gè)只在iOS模擬器上有效。它從Reveal的應(yīng)用程序bundle中找到并加載libReveal.dylib(請(qǐng)確保你把Reveal安裝到了系統(tǒng)的Application文件夾匪傍,如果你換地方了您市,你修改上述的文件)。

  • reveal_load_dev 這個(gè)命令在iOS設(shè)備和模擬器上都有效役衡。不過(guò)茵休,它需要你在Build Phase中的的Copy Bundle Resources中加上libReveal.dylib,請(qǐng)確保沒(méi)有放到Link Binary With Libraries這個(gè)地方。

  • reveal_start 這個(gè)命令發(fā)出一個(gè)通知啟動(dòng)Reveal Server泽篮。

  • reveal_stop 這個(gè)命令發(fā)出一個(gè)通知停止Reveal Server盗尸。

如果在模擬器下調(diào)試,只需要在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中加入一個(gè)斷點(diǎn)并且如圖所示編輯:

img
img

編譯運(yùn)行即可帽撑。

在真機(jī)下泼各,需在工程中導(dǎo)入Reveal的動(dòng)態(tài)庫(kù),打開(kāi)Reveal亏拉,點(diǎn)擊Help-Show Library in Finder扣蜻,將libReveal.dylib文件拖動(dòng)到目標(biāo)Xcode工程中,Xcode默認(rèn)情況下錯(cuò)誤地將libReveal.dylib設(shè)置到了”Link Binary With Libraries”下及塘,我們需要進(jìn)行一下調(diào)整莽使,將其中”Link Binary With Libraries”中刪除,然后將其添加到“Copy Bundle Resources”下面笙僚。

img
img

之后用Reveal連接真機(jī)的方式和連接模擬器的方式類(lèi)似芳肌,我們只需要把模擬器調(diào)試下的斷點(diǎn)Action的內(nèi)容從reveal_load_sim改成reveal_load_dev即可。

加載方法3

對(duì)于越獄的機(jī)器肋层,可以用Reveal來(lái)”調(diào)試“其它應(yīng)用界面亿笤,什么時(shí)候會(huì)有這種奇怪的需求呢?——當(dāng)我們想學(xué)習(xí)別人是如何實(shí)現(xiàn)界面效果的時(shí)候栋猖。iOS設(shè)備的目錄/Library/MobileSubstrate/DynamicLibraries下存放著所有在系統(tǒng)啟動(dòng)時(shí)就需要加載的動(dòng)態(tài)鏈接庫(kù)净薛,所以我們只需要將Reveal的動(dòng)態(tài)鏈接庫(kù)上傳到該目錄即可。

對(duì)于越獄的設(shè)備蒲拉,我們可以在安裝OpenSSH之后肃拜,用scp來(lái)上傳該文件。具體步驟如下:
1.將libReveal.dylib 上傳到/Library/MobileSubstrate/DynamicLibraries
2.如果libReveal.dylib沒(méi)有執(zhí)行權(quán)限雌团,用chmod +x libReveal.dylib命令燃领,給其增加執(zhí)行權(quán)限
3.執(zhí)行killall SpringBoard重啟桌面

另外需要注意的是,使用Reveal真機(jī)測(cè)試時(shí)手機(jī)和電腦應(yīng)處于同一網(wǎng)絡(luò)下锦援。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柿菩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子雨涛,更是在濱河造成了極大的恐慌枢舶,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件替久,死亡現(xiàn)場(chǎng)離奇詭異凉泄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蚯根,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)后众,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胀糜,“玉大人,你說(shuō)我怎么就攤上這事蒂誉〗淘澹” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵右锨,是天一觀的道長(zhǎng)括堤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)绍移,這世上最難降的妖魔是什么悄窃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮蹂窖,結(jié)果婚禮上轧抗,老公的妹妹穿的比我還像新娘。我一直安慰自己瞬测,他們只是感情好横媚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著月趟,像睡著了一般灯蝴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上狮斗,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音弧蝇,去河邊找鬼碳褒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛看疗,可吹牛的內(nèi)容都是我干的沙峻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼两芳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼摔寨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起怖辆,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤是复,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后竖螃,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體淑廊,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年特咆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了季惩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖画拾,靈堂內(nèi)的尸體忽然破棺而出啥繁,到底是詐尸還是另有隱情,我是刑警寧澤青抛,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布旗闽,位于F島的核電站,受9級(jí)特大地震影響脂凶,放射性物質(zhì)發(fā)生泄漏宪睹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一蚕钦、第九天 我趴在偏房一處隱蔽的房頂上張望亭病。 院中可真熱鬧,春花似錦嘶居、人聲如沸罪帖。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)整袁。三九已至,卻和暖如春佑吝,著一層夾襖步出監(jiān)牢的瞬間坐昙,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工芋忿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炸客,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓戈钢,卻偏偏與公主長(zhǎng)得像痹仙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子殉了,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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

  • Swift版本點(diǎn)擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 25,365評(píng)論 7 249
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件隔箍、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,093評(píng)論 4 62
  • 還記得我們剛踏進(jìn)學(xué)校那會(huì)嗎田轧? 那時(shí)候我們就像迷路的小羔羊 身上滿滿的都是稚氣 眼里是前所未有的迷茫和害怕 每個(gè)人心...
    江瀟然閱讀 287評(píng)論 0 1
  • 昨日的汗 浸濕地面 是份苦咸 我的明天 今日的天 十分蔚藍(lán) 苦中有甘 我的明天 明日的山 會(huì)更巍然 涌出甘甜 ...
    雨林筆墨閱讀 148評(píng)論 0 1
  • 選擇 人一生的過(guò)程在于選擇,所有的痛苦源于選擇鞍恢。 嬰兒時(shí)傻粘,吃了睡每窖,睡了吃,便無(wú)選擇弦悉,便沒(méi)有痛苦...
    石三英語(yǔ)閱讀 230評(píng)論 0 0