本篇源于對(duì)一個(gè)監(jiān)聽(tīng)鍵盤(pán)通知的處理。
監(jiān)聽(tīng)鍵盤(pán)高度代碼十分簡(jiǎn)單:
// 添加監(jiān)聽(tīng)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardChange:)
name:UIKeyboardWillChangeFrameNotification object:nil];
// 處理事件
- (void)keyboardChange:(NSNotification*)notifiction{
CGFloat during = [notifiction.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect begin = [notifiction.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect end = [notifiction.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat diff = end.origin.y - begin.origin.y;
if (diff == 0)
return;
}
else if (diff < 0) {
// 上升 鍵盤(pán)的高度包含了安全區(qū)高度
// code...
} else {
// 下降
// code...
}
}
問(wèn)題是:是否需要銷毀監(jiān)聽(tīng)?
看到的很多帖子都寫(xiě)了[[NSNotificationCenter defaultCenter] removeObserver:self]; 這樣的代碼。
然而,我們看文檔里的說(shuō)法:

意思就是iOS 9.0 往后,這樣的方式不用主動(dòng)去取消監(jiān)聽(tīng),系統(tǒng)會(huì)自動(dòng)清除這個(gè)監(jiān)聽(tīng)者在下次發(fā)出這個(gè)通知的時(shí)候。猜想,這里系統(tǒng)對(duì)observer采用了弱引用的方式,當(dāng)前的viewcontroller 銷毀后,系統(tǒng)保存的observe就變成了nil,這樣,先去判斷是否是nil,如果是nil就移除即可。
這里不是想說(shuō)代碼應(yīng)該怎樣去寫(xiě),而是引出者如何查文檔的問(wèn)題,因?yàn)楣P者發(fā)現(xiàn)一個(gè)問(wèn)題:
很多開(kāi)發(fā)者竟然認(rèn)為注釋就是文檔。比如我們進(jìn)入系統(tǒng)的這個(gè)類,看到如下內(nèi)容,然后就認(rèn)為這個(gè)類沒(méi)什么文檔,只有最下面綠色的那兩行說(shuō)明。

當(dāng)光標(biāo)放到方法的最后時(shí),注意光標(biāo)的位置(左邊箭頭),真正的文檔在右邊就會(huì)顯示:

右邊紅框中的內(nèi)容才是真正的文檔??梢钥吹接泻芏辔淖中缘恼f(shuō)明,這才是我們需要去看的地方。點(diǎn)擊右下角的Open in Developer Documentation可以打開(kāi)獨(dú)立的文檔窗口,可以更方便的查看。
一、查看文檔:
1.在線文檔
1.1>舊版在線文檔:文檔地址
雖然蘋(píng)果明確說(shuō)明了該文檔已經(jīng)過(guò)期,但左側(cè)的結(jié)構(gòu)更方便查找,往往結(jié)合新版的使用,作為查找的備選方案。

1.2>新版在線文檔:文檔地址
2.本地文檔
打開(kāi)Xcode,按Command + shift + 0 ,即可看到本地文檔。

二、如何使用文檔
三、如何保持進(jìn)步
正如本文一開(kāi)始的遇到的問(wèn)題一樣,開(kāi)發(fā)中經(jīng)常會(huì)這樣的小問(wèn)題,通常會(huì)選擇簡(jiǎn)單的百度一下去解決,而忽略了文檔(有時(shí)候文檔也寫(xiě)的不清晰,這就需要仔細(xì)去寫(xiě)代碼測(cè)試辨別),就跟著別人的帖子寫(xiě)了很多不必要的代碼,甚至是錯(cuò)誤的代碼。
仔細(xì)想想,這其實(shí)是一個(gè)開(kāi)發(fā)者不探索代碼原理的必然結(jié)果:
只要?jiǎng)e人的代碼有用,拷貝過(guò)來(lái)改改就行了,中間有什么問(wèn)題等出了再說(shuō)。而不去探究別人代碼的邏輯、思路。長(zhǎng)此以往,水平就被固化了,也難有進(jìn)步。
如何保持進(jìn)步?答案也很簡(jiǎn)單: 保持好奇心并持續(xù)探索。遇到疑問(wèn)就去查,去探究,去分析,去追根問(wèn)底。
要做到這些并不容易,需要毅力和耐心,以及長(zhǎng)時(shí)間的積累。
有時(shí)候我們會(huì)感覺(jué)到自己基礎(chǔ)不好,然而又說(shuō)不上來(lái)哪里不好,往往就是這一步做的不夠。
在經(jīng)過(guò)上述一段時(shí)間的沉淀后,就會(huì)對(duì)系統(tǒng)級(jí)別的API就有了理解,對(duì)原理也清楚了許多。寫(xiě)代碼也更有底氣,甚至有點(diǎn)隨心所欲起來(lái)。注意,到這里其實(shí)已經(jīng)有了很大的成長(zhǎng),也為后續(xù)拓寬打下了基礎(chǔ)(原理往往都是類似的)。
再往后就會(huì)有對(duì)寫(xiě)法、結(jié)構(gòu)的疑問(wèn),這時(shí)往往就摸到了設(shè)計(jì)模式的邊緣,去研究不同的設(shè)計(jì)模式,去理解,去設(shè)計(jì),去比較,在設(shè)計(jì)模式上去沉淀。
再往后就需要去嘗試其他的技術(shù)棧,比如 js、node、java、c++等, 去感受其他語(yǔ)言的設(shè)計(jì)。通過(guò)學(xué)習(xí)其他技術(shù)棧提升自己的對(duì)原有技術(shù)棧的理解。有人肯定覺(jué)得奇怪,我的回答是不要懷疑,做就是了,很快你就會(huì)理解這一點(diǎn)。
再往后,筆者還沒(méi)達(dá)到那樣的高度??梢噪[約感受到的是去學(xué)習(xí)大量?jī)?yōu)秀開(kāi)源庫(kù)、開(kāi)源框架的源碼,在架構(gòu)上去沉淀。
以上就是筆者自己學(xué)習(xí)的一個(gè)過(guò)程,體會(huì)最深的就是一個(gè)東西不管多難多復(fù)雜都不要緊,一定要有持續(xù)探究的勇氣和耐心。
筆者曾經(jīng)寫(xiě)過(guò)一段時(shí)間的Vue,學(xué)習(xí)的方法就是上面這樣,一步一步從教程和文檔中沉淀,很快就發(fā)現(xiàn)和公司中其他原本寫(xiě)前端的人寫(xiě)出的代碼的差異。明顯可以看出自己的代碼更加”官方“,而其他人的野路子就很多。不是說(shuō)野路子不好,有些問(wèn)題的確需要一些野路子去處理。 但是,往往這些遇到的問(wèn)題都是早已有了解決方法。基礎(chǔ)的東西就像是公式,業(yè)務(wù)的東西就像是做題。當(dāng)公式靈活掌握后,業(yè)務(wù)這些東西早已不是問(wèn)題。
以上便是筆者的一點(diǎn)點(diǎn)心得,記錄了從遇到問(wèn)題到反思的過(guò)程,希望可以給讀者帶來(lái)一點(diǎn)點(diǎn)啟發(fā)。