iOS之項(xiàng)目總結(jié)二:關(guān)于項(xiàng)目中一些功能的改進(jìn)建議(從一個(gè)維護(hù)者的角度)

前言:

最近一直在維護(hù)老的項(xiàng)目绝葡,遇到的問題也千奇百怪,需要修補(bǔ)的腹鹉,需要優(yōu)化的藏畅,需要特殊處理的,感覺總是那么的無語功咒。也許這時(shí)候也應(yīng)該感嘆一句:路漫漫其修遠(yuǎn)兮愉阎,吾將上下而求索吧。
這篇文章就只是講講老項(xiàng)目中遇到的種種不敢茍同的代碼寫法力奋,以及遇到一些問題時(shí)的處理方法榜旦。


1、關(guān)于按鈕事件的重復(fù)點(diǎn)擊問題

我們開發(fā)中大概都經(jīng)歷過這樣的事情景殷,我的一個(gè)<code>button</code>被重復(fù)的快速點(diǎn)擊溅呢,(我們開發(fā)者應(yīng)該更清楚的知道這意味著什么)。那我們再深入的想一下(給這樣的事件安排一個(gè)特定的環(huán)境):例如當(dāng)網(wǎng)絡(luò)較差的情況下猿挚,再例如當(dāng)<code>button</code>的執(zhí)行事件較為耗時(shí)時(shí)咐旧。這時(shí)就會(huì)出現(xiàn)很多的問題:有時(shí)是界面出現(xiàn)問題(當(dāng)<code>button</code>執(zhí)行事件中出現(xiàn)調(diào)節(jié)界面<code>frame</code>的時(shí)候);有時(shí)則會(huì)出現(xiàn)卡頓亭饵,更甚至?xí)霈F(xiàn)崩潰現(xiàn)象。對于這種問題梁厉,我們要提前考慮到辜羊,做好防范處理:即點(diǎn)擊按鈕事件時(shí),添加防止重復(fù)點(diǎn)擊功能。
思路是:防止按鈕重復(fù)點(diǎn)擊
比較推薦的解決方法代碼:
<pre> - (void)btnClicked:(id)sender {
//在這里做按鈕的想做的事情词顾。
}

  • (void)buttonClicked:(id)sender {
    //先將未到時(shí)間執(zhí)行前的任務(wù)取消八秃。
    [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(btnClicked:)object:sender];
    [self performSelector:@selector(btnClicked:)withObject:sender afterDelay:0.2f];
    }</pre>

原理是 :我們每次點(diǎn)擊按鈕時(shí),先執(zhí)行取消之前的按鈕點(diǎn)擊執(zhí)行事件肉盹,然后再去執(zhí)行一個(gè)延遲執(zhí)行方法(方法中執(zhí)行的是按鈕執(zhí)行的事件)昔驱。

還有一種方法也是可以實(shí)現(xiàn)的:具體的看《iOS之防止用戶重復(fù)點(diǎn)擊Button(按鈕)問題


2、很多界面共用一個(gè)界面時(shí):使用枚舉做類型判斷

老的項(xiàng)目中會(huì)出現(xiàn)很多這樣的現(xiàn)象:很多界面重復(fù)使用一個(gè)界面上忍,這樣就自然而然的需要在不同的界面跳轉(zhuǎn)到復(fù)用的界面時(shí)去做判斷骤肛。而奇怪的地方在于:判斷的依據(jù)是<code>self.title</code>纳本。那么就會(huì)出現(xiàn)這樣一種現(xiàn)象:在跳轉(zhuǎn)界面后會(huì)有一大段<code>if</code>去判斷字符串是否等于<code>self.title</code> 。
如果我們做一些改變:使用枚舉來做界面類型的判斷腋颠,使用<code>switch case</code>語句做判斷執(zhí)行代碼繁成。這樣會(huì)不會(huì)更優(yōu)美,簡潔一些淑玫。


3巾腕、關(guān)于老項(xiàng)目中iOS10以上的情況下,導(dǎo)航欄中按鈕不顯示問題

如果你的<code>viewController</code>都繼承于基類絮蒿,那么在基類中添加這樣一段代碼(這也是目前我發(fā)現(xiàn)的最省事的方法):
<pre>- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];
}

  • (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.navigationController setNavigationBarHidden:YES animated:NO];
    [self.navigationController setNavigationBarHidden:NO animated:NO];
    }</pre>

4尊搬、事件方法要每個(gè)界面區(qū)分開

老項(xiàng)目中會(huì)有這種情況:在本界面 command點(diǎn)擊一個(gè)<code>button</code>執(zhí)行事件方法或者手勢事件方法時(shí),會(huì)莫名其妙的跳轉(zhuǎn)到另外一個(gè)界面土涝。
我們在開發(fā)時(shí)最好給不同界面<code>button</code>的<code>clicked</code>事件命名是區(qū)分開來佛寿,例如:界面名 + <code>ButtonClicked</code>


5、對象為空現(xiàn)象

在開發(fā)中如果存在<code>image</code>為空回铛,或者必須顯示的<code>String</code>為空現(xiàn)象狗准,
記得在代碼中作判斷,圖片可以直接設(shè)置默認(rèn)圖片茵肃,字符串也可以設(shè)置默認(rèn)字符串
這一點(diǎn)可以學(xué)一下SDWebImage庫中對于網(wǎng)絡(luò)請求圖片不存在的處理方法:
<pre>//給一張默認(rèn)圖片腔长,先使用默認(rèn)圖片,當(dāng)圖片加載完成后再替換
[self.image1 sd_setImageWithURL:imagePath1 placeholderImage:[UIImage imageNamed:@"default"]];</pre>
例如:
<pre>
UIImage *image = [UIImage imageNamed:@"image"];

UIImage *defaultImage = [UIImage imageNamed:@"defaultImage"];

UIImageView *imageView = [[UIImageView alloc]initWithImage:image==nil ? image:defaultImage];
</pre>
字符串當(dāng)然也是類似验残,其實(shí)看似有些費(fèi)事甚至有的顯得多余的寫法捞附,會(huì)使以后的維護(hù)變得更加的如意。


6您没、一個(gè)界面多網(wǎng)絡(luò)請求問題鸟召,而且需要多個(gè)請求都完成后,對界面有一些操作氨鹏。

這是一個(gè)老的話題了欧募,我之所以重新提及這個(gè)話題,原因是我從一些文章中發(fā)現(xiàn)了一個(gè)從來沒使用過的方法仆抵,這個(gè)下面會(huì)提到跟继,現(xiàn)在就讓我們列舉出來比較常用的方法。就以一個(gè)界面兩個(gè)網(wǎng)絡(luò)請求為例 A和B
1镣丑、兩個(gè)請求互套)(也是最笨的方法)
具體是這樣的舔糖,我在A請求成功后,再請求B莺匠。當(dāng)然如果請求多的話金吗,這個(gè)肯定是作廢的。
2、使用GCD中的通知
<pre>
dispatch_group_t serviceGroup = dispatch_group_create();
// 開始第一個(gè)網(wǎng)絡(luò)請求
servicedispatch_group_enter(serviceGroup);
[self.configService startWithCompletion:^(ConfigResponse results, NSError error) {
//請求成功后的操作
configError = error;
dispatch_group_leave(serviceGroup);//完成后離開分組
}];
// 開始第二個(gè)請求
dispatch_group_enter(serviceGroup);
[self.preferenceService startWithCompletion:^(PreferenceResponse results, NSError error) {
//請求成功后的操作
preferenceError = error;
dispatch_group_leave(serviceGroup);//完成后離開分組
}];
dispatch_group_notify(serviceGroup,dispatch_get_main_queue(),^{
// Assess any errors
NSError *overallError = nil;
if (configError || preferenceError) {
// 判斷時(shí)候請求有失敗
overallError = configError ?: preferenceError;
}
// 最后完成后執(zhí)行的block
completion(overallError);
});
</pre></code>

3摇庙、利用GCD中的信號(hào)量
在GCD中有三個(gè)函數(shù)是<code>semaphore</code>的操作旱物,分別是:  
<code>dispatch_semaphore_create</code> 創(chuàng)建一個(gè)semaphore  
<code>dispatch_semaphore_signal</code> 發(fā)送一個(gè)信號(hào) 
<code>dispatch_semaphore_wait</code> 等待信號(hào)  
簡單的介紹一下這三個(gè)函數(shù),第一個(gè)函數(shù)有一個(gè)整形的參數(shù)跟匆,我們可以理解為信號(hào)的總量异袄,<code>dispatch_semaphore_signal</code>是發(fā)送一個(gè)信號(hào),自然會(huì)讓信號(hào)總量加1玛臂,<code>dispatch_semaphore_wait</code>等待信號(hào)烤蜕,當(dāng)信號(hào)總量少于0的時(shí)候就會(huì)一直等待,否則就可以正常的執(zhí)行迹冤,并讓信號(hào)總量-1讽营,根據(jù)這樣的原理,我們便可以快速的創(chuàng)建一個(gè)并發(fā)控制來同步任務(wù)和有限資源訪問控制泡徙。

利用這樣的機(jī)制橱鹏,當(dāng)信號(hào)量達(dá)到我們網(wǎng)絡(luò)請求的數(shù)量時(shí),請求結(jié)束堪藐。
4莉兰、這個(gè)也是我上面說的無意中看到的一個(gè)方法,僅拿出來作為參考
<pre>dispatch_async(concurrent_queue, ^{
NSLog(@"---并發(fā)任務(wù)1---");
});
dispatch_async(concurrent_queue, ^{
NSLog(@"---并發(fā)任務(wù)2---");
});
dispatch_barrier_async(concurrent_queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"---所有并發(fā)任務(wù)結(jié)束后回到主線程刷新---");
});
}); </pre></code>

以上就是關(guān)于一界面多請求的不同解決方案礁竞。


7糖荒、代碼規(guī)范問題

  • 為什么這個(gè)普通的話題放到最后呢,大概是因?yàn)槲矣X得這個(gè)很重要的問題吧模捂,畢竟技術(shù)水平不高捶朵,還是可以提升的。但代碼不規(guī)范的話狂男,養(yǎng)成習(xí)慣后很難改的综看,我見過太多項(xiàng)目中使用【拼音命名、不注意駝峰命名法岖食、define預(yù)處理指令滿天飛等等的代碼】這些出現(xiàn)在項(xiàng)目中就像時(shí)時(shí)刻刻在提醒你红碑,看這樣的項(xiàng)目是一種煎熬。
  • 其實(shí)代碼規(guī)范不僅僅是公司對開發(fā)者的要求,也是開發(fā)者對自己的一個(gè)要求泡垃。因?yàn)槿绻y(tǒng)一每個(gè)人的寫作規(guī)范析珊,是一件耗時(shí),耗材的事情兔毙。小一些的公司是做不來唾琼,中型的公司大多是不想做兄春。而大型的公司總是花費(fèi)近幾個(gè)月的時(shí)間去培養(yǎng)員工的代碼規(guī)范澎剥,這就是財(cái)大氣粗吧。而且開發(fā)者本身對于技術(shù)的提升、追求等哑姚,都無形中要求自己注意代碼規(guī)范問題祭饭。
  • 對于這部分,建議看看《Effective Objective-C 2.0》這本書叙量,其中起到的倡蝙。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绞佩,隨后出現(xiàn)的幾起案子寺鸥,更是在濱河造成了極大的恐慌,老刑警劉巖品山,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胆建,死亡現(xiàn)場離奇詭異,居然都是意外死亡肘交,警方通過查閱死者的電腦和手機(jī)笆载,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涯呻,“玉大人凉驻,你說我怎么就攤上這事「垂蓿” “怎么了涝登?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長市栗。 經(jīng)常有香客問我缀拭,道長,這世上最難降的妖魔是什么填帽? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任蛛淋,我火速辦了婚禮,結(jié)果婚禮上篡腌,老公的妹妹穿的比我還像新娘褐荷。我一直安慰自己,他們只是感情好嘹悼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布叛甫。 她就那樣靜靜地躺著,像睡著了一般杨伙。 火紅的嫁衣襯著肌膚如雪其监。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天限匣,我揣著相機(jī)與錄音抖苦,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛锌历,可吹牛的內(nèi)容都是我干的贮庞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼究西,長吁一口氣:“原來是場噩夢啊……” “哼窗慎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起卤材,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤遮斥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后扇丛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伏伐,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年晕拆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了藐翎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡实幕,死狀恐怖吝镣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昆庇,我是刑警寧澤末贾,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站整吆,受9級(jí)特大地震影響拱撵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜表蝙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一拴测、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧府蛇,春花似錦集索、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至穷遂,卻和暖如春函匕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蚪黑。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工盅惜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吸耿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓酪劫,卻偏偏與公主長得像撬讽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

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