MVC 具有什么樣的優(yōu)勢桐经,各個模塊之間怎么通信几缭,比如點擊 Button 后 怎么通知 Model?
MVC 是一種設(shè)計思想伶授,一種框架模式断序,是一種把應(yīng)用中所有類組織起來的策略,它把你的程序分為三塊谎砾,分別是:
M(Model):實際上考慮的是“什么”問題逢倍,你的程序本質(zhì)上是什么,獨立于 UI 工作景图。是程序中用于處理應(yīng)用程序邏輯的部分较雕,通常負(fù)責(zé)存取數(shù)據(jù)。
C(Controller):控制你 Model 如何呈現(xiàn)在屏幕上挚币,當(dāng)它需要數(shù)據(jù)的時候就告訴 Model亮蒋,你幫我獲取某某數(shù)據(jù);當(dāng)它需要 UI 展示和更新的時候就告訴 View妆毕,你幫我生成一個 UI 顯示某某數(shù)據(jù)慎玖,是 Model 和 View 溝通的橋梁。
V(View):Controller 的手下笛粘,是 Controller 要使用的類趁怔,用于構(gòu)建視圖湿硝,通常是根據(jù) Model 來創(chuàng)建視圖的。
要了解 MVC 如何工作润努,首先需要了解這三個模塊間如何通信关斜。
Controller to Model
可以直接單向通信。Controller 需要將 Model 呈現(xiàn)給用戶铺浇,因此需要知道模型的一切痢畜,還需要有同 Model 完全通信的能力,并且能任意使用 Model 的公共 API鳍侣。
Controller to View
可以直接單向通信丁稀。Controller 通過 View 來布局用戶界面。
Model to View
永遠(yuǎn)不要直接通信倚聚。Model 是獨立于 UI 的线衫,并不需要和 View 直接通信,View 通過 Controller 獲取 Model 數(shù)據(jù)惑折。
View to Controller
View 不能對 Controller 知道的太多桶雀,因此要通過間接的方式通信。
Target action唬复。首先 Controller 會給自己留一個 target矗积,再把配套的 action 交給 View 作為聯(lián)系方式。那么 View 接收到某些變化時敞咧,View 就會發(fā)送 action 給 target 從而達(dá)到通知的目的棘捣。這里 View 只需要發(fā)送 action,并不需要知道 Controller 如何去執(zhí)行方法休建。
代理乍恐。有時候 View 沒有足夠的邏輯去判斷用戶操作是否符合規(guī)范,他會把判斷這些問題的權(quán)力委托給其他對象测砂,他只需獲得答案就行了茵烈,并不會管是誰給的答案。
DataSoure砌些。View 沒有擁有他們所顯示數(shù)據(jù)的權(quán)力呜投,View 只能向 Controller 請求數(shù)據(jù)進行顯示,Controller 則獲取 Model 的數(shù)據(jù)整理排版后提供給 View存璃。
Model 訪問 Controller
同樣的 Model 是獨立于 UI 存在的仑荐,因此無法直接與 Controller 通信,但是當(dāng) Model 本身信息發(fā)生了改變的時候纵东,會通過下面的方式進行間接通信粘招。
Notification & KVO一種類似電臺的方法,Model 信息改變時會廣播消息給感興趣的人 偎球,只要 Controller 接收到了這個廣播的時候就會主動聯(lián)系 Model洒扎,獲取新的數(shù)據(jù)并提供給 View辑甜。
從上面的簡單介紹中我們來簡單概括一下 MVC 模式的優(yōu)點。
1.低耦合性
2.有利于開發(fā)分工
3.有利于組件重用
4.可維護性
兩個無限長度鏈表(也就是可能有環(huán)) 判斷有沒有交點
給定單鏈表袍冷,檢測是否有環(huán)栈戳。如果有環(huán),則求出進入環(huán)的第一個節(jié)點难裆。
判斷單向鏈表是否有環(huán),可以采用快指針與慢指針的方式來解決镊掖。即定義一個快指針fast和一個慢指針slow乃戈,使得fast每次跳躍兩個節(jié)點,slow每次跳躍一個節(jié)點亩进。如果鏈表沒有環(huán)的話症虑,則slow與fast永遠(yuǎn)不會相遇(這里鏈表至少有兩個節(jié)點);如果有環(huán)归薛,則fast與slow將會在環(huán)中相遇谍憔。
然后獲取環(huán)的入口點方法如圖所示:
給定兩個單鏈表(鏈表自身無環(huán)),檢測兩個鏈表是否有交點主籍,如果有返回第一個交點习贫。
檢測兩個單鏈表是否有交點是很容易的,因為如果兩個鏈表有交點千元,那么這兩個鏈表的最后一個節(jié)點必須相同苫昌,所以只需比較最后一個節(jié)點即可。但是這種方案是無法求出第一個交點的幸海,所以需要另辟蹊徑祟身。另外,判斷是否有交點可以轉(zhuǎn)換成鏈表是否有環(huán)的問題物独。讓一個鏈表的最后一個節(jié)點指向第二個鏈表的頭結(jié)點袜硫,這樣的話,如果相交挡篓,則新的鏈表是存在環(huán)的婉陷,并且交點便是環(huán)的入口點。
給定兩個單鏈表(不確定是否帶環(huán))官研,判斷是否有交點
先判斷兩個鏈表是否帶環(huán)憨攒;
i).如果兩個都不帶環(huán),可以用:判斷兩個無環(huán)單鏈表是否有交點阀参。
ii).兩個都帶環(huán):找到兩個入環(huán)點r1,r2肝集,環(huán)1的入環(huán)點為r1,從r1開始遍歷一圈蛛壳,每個結(jié)點如r2比較
iii).一個帶環(huán)一個不帶環(huán)杏瞻,則肯定不相交所刀。
給定單鏈表頭結(jié)點,刪除鏈表中倒數(shù)第k個結(jié)點
這個問題的關(guān)鍵是需要獲取倒數(shù)第k個節(jié)點捞挥。如何獲取呢野舶?這里烹植,需要兩個指針p和q,p指向頭結(jié)點,q指向距離頭結(jié)點為k的節(jié)點闸衫。這樣p和q每次遍歷一個節(jié)點,當(dāng)q遍歷到末尾的時候泡挺,p指向的節(jié)點即為倒數(shù)第k個節(jié)點渐裸,然后刪除即可。
只給定單鏈表中某個結(jié)點p(并非最后一個結(jié)點仍劈,即p->next!=NULL)指針厕倍,刪除該結(jié)點;
只給定單鏈表中某個結(jié)點p(非空結(jié)點)贩疙,在p前面插入一個結(jié)點讹弯。
上訴兩種方法的原理都是一樣的。
UITableView 的相關(guān)優(yōu)化
1.基礎(chǔ)的優(yōu)化準(zhǔn)則(高度緩存, cell 重用...)
? ? ?滾動很快時这溅,只加載目標(biāo)范圍內(nèi)的Cell组民,這樣按需加載,極大的提高流暢度悲靴。提前計算并緩存 ? ? ? ?好高度(布局)邪乍,因為heightForRowAtIndexPath:是調(diào)用最頻繁的方法。異步繪制对竣,遇到復(fù) ? ? ? ?雜界面庇楞,遇到性能瓶頸時,可能就是突破口否纬÷郎危滑動時按需加載,這個在大量圖片展示临燃,網(wǎng)絡(luò)加 ? ? ?載的時候很管用>Σ怠(SDWebImage已經(jīng)實現(xiàn)異步加載,配合這條性能杠杠的)膜廊。
? ? ? 除了上面最主要的三個方面外乏沸,還有很多幾乎大伙都很熟知的優(yōu)化點:?
? ? ? 正確使用reuseIdentifier來重用Cells
? ? ? 盡量使所有的viewopaque,包括Cell自身
? ? ? 盡量少用或不用透明圖層
? ? ? ?如果Cell內(nèi)現(xiàn)實的內(nèi)容來自web爪瓜,使用異步加載蹬跃,緩存請求結(jié)果
? ? ? ? 減少subviews的數(shù)量
? ? ? ? 在heightForRowAtIndexPath:中盡量不使用cellForRowAtIndexPath:,如果你需要用到 ? ? ? ? ? ? 它铆铆,只用一次然后緩存結(jié)果
? ? ? ? 盡量少用addView給Cell動態(tài)添加View蝶缀,可以初始化時就添加丹喻,然后通過hide來控制是否顯 ? ? ? ??
2.學(xué)會使用調(diào)試工具分析問題
http://www.reibang.com/p/af6b095aaaf3
http://blog.csdn.net/icetime17/article/details/46709975
KVO、Notification翁都、delegate 各自的優(yōu)缺點碍论,效率還有使用場景
在開發(fā)ios應(yīng)用的時候,我們會經(jīng)常遇到一個常見的問題:在不過分耦合的前提下柄慰,controllers間怎么進行通信鳍悠。在IOS應(yīng)用不斷的出現(xiàn)三種模式來實現(xiàn)這種通信:
1.委托delegation;
2.通知中心Notification Center坐搔;
3.鍵值觀察key value observing藏研,KVO
delegate的優(yōu)勢:
1.很嚴(yán)格的語法,所有能響應(yīng)的時間必須在協(xié)議中有清晰的定義
2.因為有嚴(yán)格的語法薯蝎,所以編譯器能幫你檢查是否實現(xiàn)了所有應(yīng)該實現(xiàn)的方法,不容易遺忘和出錯
3.使用delegate的時候谤绳,邏輯很清楚占锯,控制流程可跟蹤和識別
4.在一個controller中可以定義多個協(xié)議,每個協(xié)議有不同的delegate
5.沒有第三方要求保持/監(jiān)視通信過程缩筛,所以假如出了問題消略,那我們可以比較方便的定位錯誤代碼。
6.能夠接受調(diào)用的協(xié)議方法的返回值瞎抛,意味著delegate能夠提供反饋信息給controller
delegate的缺點:
需要寫的代碼比較多
有一個“Notification Center”的概念艺演,他是一個單例對象,允許當(dāng)事件發(fā)生的時候通知一些對象桐臊,滿足控制器與一個任意的對象進行通信的目的胎撤,這種模式的基本特征就是接收到在該controller中發(fā)生某種事件而產(chǎn)生的消息,controller用一個key(通知名稱)断凶,這樣對于controller是匿名的伤提,其他的使用同樣地key來注冊了該通知的對象能對通知的事件作出反應(yīng)。
notification的優(yōu)勢:
1.不需要寫多少代碼认烁,實現(xiàn)比較簡單
2.一個對象發(fā)出的通知肿男,多個對象能進行反應(yīng),一對多的方式實現(xiàn)很簡單
缺點:
1.編譯期不會接茬通知是否能被正確處理
2.釋放注冊的對象時候却嗡,需要在通知中心取消注冊
3.調(diào)試的時候舶沛,程序的工作以及控制流程難跟蹤
4.需要第三方來管理controller和觀察者的聯(lián)系
5.controller和觀察者需要提前知道通知名稱、UserInfo dictionary keys窗价。如果這些沒有在工作區(qū)間定義如庭,那么會出現(xiàn)不同步的情況
6.通知發(fā)出后,發(fā)出通知的對象不能從觀察者獲得任何反饋撼港。
KVO
KVO是一個對象能觀察另一個對象屬性的值柱彻,前兩種模式更適合一個controller和其他的對象進行通信豪娜,而KVO適合任何對象監(jiān)聽另一個對象的改變,這是一個對象與另外一個對象保持同步的一種方法哟楷。KVO只能對屬性做出反應(yīng)瘤载,不會用來對方法或者動作做出反應(yīng)。
優(yōu)點:
1.提供一個簡單地方法來實現(xiàn)兩個對象的同步
2.能對非我們創(chuàng)建的對象做出反應(yīng)
3.能夠提供觀察的屬性的最新值和先前值
4.用keypaths 來觀察屬性卖擅,因此也可以觀察嵌套對象
缺點:
1.觀察的屬性必須使用string來定義鸣奔,因此編譯器不會出現(xiàn)警告和檢查
2.對屬性的重構(gòu)將導(dǎo)致觀察不可用
3.復(fù)雜的“if”語句要求對象正在觀察多個值,這是因為所有的觀察都通過一個方法來指向
KVO有顯著的使用場景惩阶,當(dāng)你希望監(jiān)視一個屬性的時候挎狸,我們選用KVO
而notification和delegate有比較相似的用處,
當(dāng)處理屬性層的消息的事件時候断楷,使用KVO锨匆,其他的盡量使用delegate,除非代碼需要處理的東西確實很簡單冬筒,那么用通知很方便
如何手動通知 KVO
重寫Controller里面某個屬性的setter方法恐锣,聯(lián)動給View賦值,使用Controller監(jiān)控Model里面某個值的變化舞痰,在controller的dealloc函數(shù)中用一行代碼了結(jié):removeObserver土榴。
Objective-C 中的 copy 方法
Objective-c中對象的Copy、MutableCopy响牛、淺拷貝玷禽、深拷貝
runtime 中,SEL 和 IMP 的區(qū)別
方法名 SEL – 表示該方法的名稱呀打;
一個 types – 表示該方法參數(shù)的類型矢赁;
一個IMP ? ? – 指向該方法的具體實現(xiàn)的函數(shù)指針,說白了IMP就是實現(xiàn)方法贬丛。
autoreleasepool 的使用場景和原理
Autorelease Pool全名叫做NSAutoreleasePool坯台,是OC中的一個類。autorelease pool并不是天生就有的瘫寝,你需要手動的去創(chuàng)建它蜒蕾。一般地,在新建一個iphone項目的時候焕阿,xcode會自動地為你創(chuàng)建一個Autorelease Pool咪啡,這個pool就寫在Main函數(shù)里面。在NSAutoreleasePool中包含了一個可變數(shù)組暮屡,用來存儲被聲明為autorelease的對象撤摸。當(dāng)NSAutoreleasePool自身被銷毀的時候,它會遍歷這個數(shù)組,release數(shù)組中的每一個成員(注意准夷,這里只是release钥飞,并沒有直接銷毀對象)。若成員的retain count 大于1衫嵌,那么對象沒有被銷毀读宙,造成內(nèi)存泄露。默認(rèn)的NSAutoreleasePool 只有一個楔绞,你可以在你的程序中創(chuàng)建NSAutoreleasePool结闸,被標(biāo)記為autorelease的對象會跟最近的NSAutoreleasePool匹配【贫洌可以嵌套使用NSAutoreleasePool桦锄。
Objective-C Autorelease Pool 的實現(xiàn)原理
RunLoop 的實現(xiàn)原理和數(shù)據(jù)結(jié)構(gòu),什么時候會用到
block 為什么會有循環(huán)引用
產(chǎn)生原因:如下圖所示蔫耽,對象A和對象B相互引用了對方作為自己的成員變量结耀,只有自己銷毀的時候才能將成員變量的引用計數(shù)減1。對象A的銷毀依賴于對象B的銷毀匙铡,同時對象B銷毀也依賴與對象A的銷毀图甜,從而形成循環(huán)引用,此時慰枕,即使外界沒有任何指針訪問它具则,它也無法釋放即纲。
循環(huán)引用示例圖
多個對象間依然會存在循環(huán)引用問題具帮,形成一個環(huán),在編程中低斋,形成的環(huán)越大越不容易察覺蜂厅,如下圖所示:
多個對象引用示例圖
解決方法:
事先知道存在循環(huán)引用的地方,在合理的位置主動斷開一個引用膊畴,是對象回收,使用弱引用的方法掘猿。
使用 GCD 如何實現(xiàn)這個需求:A、B唇跨、C 三個任務(wù)并發(fā)稠通,完成后執(zhí)行任務(wù) D。
NSOperation 和 GCD 的區(qū)別
GCD是基于c的底層api买猖,NSOperation屬于object-c類改橘。ios 首先引入的是NSOperation,IOS4之后引入了GCD和NSOperationQueue并且其內(nèi)部是用gcd實現(xiàn)的玉控。
相對于GCD:
1飞主,NSOperation擁有更多的函數(shù)可用,具體查看api。
2碌识,在NSOperationQueue中碾篡,可以建立各個NSOperation之間的依賴關(guān)系。
3筏餐,有kvo开泽,可以監(jiān)測operation是否正在執(zhí)行(isExecuted)、是否結(jié)束(isFinished)胖烛,是否取消(isCanceld)眼姐。
4,NSOperationQueue可以方便的管理并發(fā)佩番、NSOperation之間的優(yōu)先級众旗。
GCD主要與block結(jié)合使用。代碼簡潔高效趟畏。
GCD也可以實現(xiàn)復(fù)雜的多線程應(yīng)用贡歧,主要是建立個個線程時間的依賴關(guān)系這類的情況,但是需要自己實現(xiàn)相比NSOperation要復(fù)雜赋秀。
具體使用哪個利朵,依需求而定。從個人使用的感覺來看猎莲,比較合適的用法是:除了依賴關(guān)系盡量使用GCD绍弟,因為蘋果專門為GCD做了性能上面的優(yōu)化。
NSOprationQueue 與 GCD 的區(qū)別與選用
CoreData 的使用著洼,如何處理多線程問題
如何設(shè)計圖片緩存樟遣?
有沒有自己設(shè)計過網(wǎng)絡(luò)控件?
怎么判斷某個 cell 是否顯示在屏幕上
iOS基礎(chǔ)--UITableViewCell的重用機制
進程和線程的區(qū)別
TCP 與 UDP 區(qū)別
這是兩個工作在TCP/IP協(xié)議傳輸層的兩個不同的協(xié)議身笤,是用來傳輸數(shù)據(jù)用的豹悬。
TCP:Transfer Control Protocol,傳輸控制協(xié)議液荸。
這是一個全雙工的瞻佛、面向連接的、可靠的并且是精確控制的協(xié)議娇钱。
主要是用在那些實時性不強伤柄、但要求不能出錯的應(yīng)用。比如說文搂,網(wǎng)頁的瀏覽适刀、文件的下載(不是BT、電驢下載)细疚、郵件的收發(fā)等場合蔗彤,就需要TCP協(xié)議進行傳輸(因為不會出錯)川梅。
當(dāng)然,它在網(wǎng)絡(luò)方面的開銷是昂貴的然遏。
UDP:User Datagram Protocol贫途,用戶數(shù)據(jù)報協(xié)議。
這是一個不可靠的傳輸協(xié)議待侵。因為它不排序所要發(fā)送的數(shù)據(jù)段丢早、不關(guān)心這些數(shù)據(jù)段到達(dá)目的方的順序(所以它才不可靠),所以它在網(wǎng)絡(luò)的開銷要比TCP小很多秧倾。因此UDP適合用在那些實時性強怨酝、允許出錯的場合。
比如說:即時通信(MSN那先、QQ)农猬,視頻,語音等方面
TCP 流量控制
滑動窗口機制
比如發(fā)送端能發(fā)送5個數(shù)據(jù)售淡,接收端也能收到5個數(shù)據(jù)斤葱,給個確認(rèn)(ack)給發(fā)送端,確認(rèn)我收到5個數(shù)據(jù)揖闸。如果網(wǎng)絡(luò)通信出現(xiàn)繁忙或者擁塞的時候揍堕,接收端只能收3個數(shù)據(jù),接受端給個確認(rèn)我只能收3個數(shù)據(jù)汤纸,那么發(fā)送端就自動調(diào)整發(fā)送的窗口為3衩茸,當(dāng)線路又恢復(fù)通暢的時候,接受端又可以受到5個數(shù)據(jù)贮泞,那它會給確認(rèn)給發(fā)送端楞慈,告訴它我的窗口為5,那發(fā)送端就把窗口又調(diào)整會5隙畜,這樣進行流量控制的
2抖部、比如說發(fā)送端窗口為3说贝,發(fā)送到接收端议惰,接收端的接收窗口為5的話,接受數(shù)據(jù)乡恕,并且會給發(fā)送端一個ack(確認(rèn))告訴發(fā)送端我的窗口為5言询,發(fā)送端收到確認(rèn)后會把自己的發(fā)送端窗口調(diào)整為5~~這樣就可以加速數(shù)據(jù)傳輸了
數(shù)組和鏈表的區(qū)別
從邏輯結(jié)構(gòu)來看
1. 數(shù)組必須事先定義固定的長度(元素個數(shù)),不能適應(yīng)數(shù)據(jù)動態(tài)地增減的情況傲宜。當(dāng)數(shù)據(jù)增加時运杭,可能超出原先定義的元素個數(shù);當(dāng)數(shù)據(jù)減少時函卒,造成內(nèi)存浪費辆憔;數(shù)組可以根據(jù)下標(biāo)直接存取。
2. 鏈表動態(tài)地進行存儲分配虱咧,可以適應(yīng)數(shù)據(jù)動態(tài)地增減的情況熊榛,且可以方便地插入、刪除數(shù)據(jù)項腕巡。(數(shù)組中插入玄坦、刪除數(shù)據(jù)項時,需要移動其它數(shù)據(jù)項绘沉,非常繁瑣)鏈表必須根據(jù)next指針找到下一個元素
從內(nèi)存存儲來看
1. (靜態(tài))數(shù)組從棧中分配空間, 對于程序員方便快速,但是自由度小
2. 鏈表從堆中分配空間, 自由度大但是申請管理比較麻煩
從上面的比較可以看出煎楣,如果需要快速訪問數(shù)據(jù),很少或不插入和刪除元素车伞,就應(yīng)該用數(shù)組择懂;相反, 如果需要經(jīng)常插入和刪除元素就需要用鏈表數(shù)據(jù)結(jié)構(gòu)了另玖。
鏈表是動態(tài)進行存儲分配,不連續(xù)休蟹。數(shù)組是固定好數(shù)組長度,存儲空間是靜態(tài)連續(xù)的日矫。
UIView 生命周期
一赂弓、 大體流程:
(loadView/nib)文件來加載view到內(nèi)存-->viewDidLoad函數(shù)進一步初始化這些view-->內(nèi)存不足時, 調(diào)用viewDidUnload函數(shù)釋放views-->當(dāng)需要使用view時又回到第一步
loadView:
永遠(yuǎn)不要主導(dǎo)調(diào)用這個函數(shù)哪轿。
viewController 會在view的property被請求并且當(dāng)前view值為nil時調(diào)用這個函數(shù)盈魁。如果你手動創(chuàng)建view, 你應(yīng)該重載這個函數(shù)窃诉,切不要在重載的時候調(diào)用[super loadView]杨耙。
viewDidload:
這個函數(shù)的作用主要是讓你可以進一步的初始化你的views。
viewDidLoad通常負(fù)責(zé)的是view及其子view被加載進內(nèi)存之后的數(shù)據(jù)初始化的工作飘痛,即視圖的數(shù)據(jù)部分的初始化
viewDidUnLoad:
這個函數(shù)時viewDidLoad的對立函數(shù)珊膜。在程序內(nèi)存欠缺時,這個函數(shù)被controller帶哦用宣脉,來釋放他的view以及view相關(guān)的對象车柠。由于controller通常保存著view以及相關(guān)的object的引用,所以你必須使用這個函數(shù)來放棄這些對象的所有權(quán)以便內(nèi)存回收塑猖,但不要釋放那些難以重建的數(shù)據(jù)
viewWillAppear:
視圖即將可見時調(diào)用竹祷,默認(rèn)情況下不執(zhí)行任何操作。
viewDidAppear:
視圖已完全過渡到屏幕上時調(diào)用
viewWillDisappear:
視圖被駁回時調(diào)用羊苟,覆蓋或以其他方式隱藏塑陵,默認(rèn)情況下不執(zhí)行任何操作
viewDidDisappear:
視圖被駁回后調(diào)用,覆蓋或以其他方式隱藏蜡励。默認(rèn)情況下不執(zhí)行任何操作
didReceiveMemoryWarning:
當(dāng)程序內(nèi)存過度時令花,系統(tǒng)會調(diào)用該方法
二阻桅、Controller和View的生命周期
這里指的View是指Controller的View。它作為Controler的屬性兼都,生命周期在Controller的生命周期內(nèi)鳍刷。就是說你的Controller不能在view釋放前就釋放了。
當(dāng)你alloc并init了一個ViewController時俯抖,這個ViewController應(yīng)該是還沒有創(chuàng)建view的输瓜。ViewController的view是使用了lazyInit方式創(chuàng)建,就是說你調(diào)用的view屬性的getter:[self view]芬萍。在getter里會先判斷view是否創(chuàng)建尤揣,如果沒有創(chuàng)建,那么會調(diào)用loadView來創(chuàng)建view柬祠。loadView完成時會繼續(xù)調(diào)用viewDidLoad北戏。loadView和viewDidLoad的一個區(qū)別就是:loadView時還沒有view。而viewDidLoad時view以及創(chuàng)建好了漫蛔。
當(dāng)view被添加其他view中之前時嗜愈,會調(diào)用viewWillAppear,而之后會調(diào)用viewDidAppear莽龟。
當(dāng)view從其他view中移出之前時蠕嫁,會調(diào)用viewWillDisAppear,而之后會調(diào)用viewDidDisappear毯盈。
當(dāng)view不在使用剃毒,而且是disappeared,受到內(nèi)存警告時搂赋,那么viewController會將view釋放并將其指向nil赘阀。
三、代碼組織(如何設(shè)計良好的viewcontroller)
ViewController生命周期中有那么多函數(shù)脑奠,一個重要問題就是什么代碼該寫在什么地方基公。
1、init里不要出現(xiàn)創(chuàng)建view的代碼宋欺。良好的設(shè)計轰豆,在init里應(yīng)該只有相關(guān)數(shù)據(jù)的初始化,而且這些數(shù)據(jù)都是比較關(guān)鍵的數(shù)據(jù)迄靠。init里不要掉self.view秒咨,否則會導(dǎo)致viewcontroller創(chuàng)建view喇辽。(因為view是lazyinit的)掌挚。
2、loadView中只初始化view菩咨,一般用于創(chuàng)建比較關(guān)鍵的view如tableViewController的tabView吠式,UINavigationController的navgationBar陡厘,不可掉用view的getter(在掉super loadView前),最好也不要初始化一些非關(guān)鍵的view特占。如果你是從nib文件中創(chuàng)建的viewController在這里一定要首先調(diào)用super的loadView方法糙置,但建議不要重載這個方法。
3是目、viewDidLoad 這時候view已經(jīng)有了谤饭,最適合創(chuàng)建一些附加的view和控件了。
4懊纳、viewWillAppear 這個一般在view被添加到superview之前揉抵,切換動畫之前調(diào)用。在這里可以進行一些顯示前的處理嗤疯。比如鍵盤彈出冤今,一些特殊的過程動畫(比如狀態(tài)條和navigationbar顏色)。
5茂缚、viewDidAppear 一般用于顯示后戏罢,在切換動畫后,如果有需要的操作脚囊,可以在這里加入相關(guān)代碼龟糕。
6、viewDidUnload 這時候viewController的view已經(jīng)是nil了悔耘。由于這一般發(fā)生在內(nèi)存警告時翩蘸,所以在這里你應(yīng)該將那些不在顯示的view釋放了。比如你在viewcontroller的view上加了一個label淮逊,而且這個label是viewcontroller的屬性催首,那么你要把這個屬性設(shè)置成nil,以免占用不必要的內(nèi)存泄鹏,而這個label在viewDidLoad時會重新創(chuàng)建郎任。
7、接下來看看ViewController中的view是如何被卸載的:
當(dāng)系統(tǒng)發(fā)出內(nèi)存警告時备籽,會調(diào)用didReceiveMemoeryWarning方法舶治,如果當(dāng)前有能被釋放的view,系統(tǒng)會調(diào)用viewWillUnload方法來釋放view车猬,完成后調(diào)用viewDidUnload方法霉猛,至此,view就被卸載了珠闰。此時原本指向view的變量要被置為nil惜浅,具體操作是在viewDidUnload方法中調(diào)用self.myButton = nil;
小結(jié)一下:loadView和viewDidLoad的區(qū)別就是,loadView時view還沒有生成伏嗜,viewDidLoad時坛悉,view已經(jīng)生成了伐厌,loadView只會被調(diào)用一次,而viewDidLoad可能會被調(diào)用多次(View可能會被多次加載)裸影,當(dāng)view被添加到其他view中之前挣轨,會調(diào)用viewWillAppear,之后會調(diào)用viewDidAppear轩猩。當(dāng)view從其他view中移除之前卷扮,調(diào)用viewWillDisAppear,移除之后會調(diào)用viewDidDisappear均践。當(dāng)view不再使用時画饥,受到內(nèi)存警告時,ViewController會將view釋放并將其指向為nil浊猾。
ViewController的生命周期中各方法執(zhí)行流程如下:init—>loadView—>viewDidLoad—>viewWillApper—>viewDidApper—>viewWillDisapper—>viewDidDisapper—>viewWillUnload->viewDidUnload—>dealloc
如果頁面 A 跳轉(zhuǎn)到 頁面 B抖甘,A 的 viewDidDisappear 方法和 B 的 viewDidAppear 方法哪個先調(diào)用?
1.A -->viewWillDisappear
2.B-->viewWillAppear
3.A-->viewDidDisappear
4.B-->viewDidAppear
ARC 的本質(zhì)
ARC是編譯器(時)特性葫慎,而不是運行時特性衔彻,更不是垃圾回收器(GC)。
Automatic Reference Counting (ARC) is a compiler-level feature that simplifies the process of managing object lifetimes (memory management) in Cocoa applications.
ARC只是相對于MRC(Manual Reference Counting或稱為非ARC偷办,下文中我們會一直使用MRC來指代非ARC的管理方式)的一次改進艰额,但它和之前的技術(shù)本質(zhì)上沒有區(qū)別。具體信息可以參考ARC編譯器官方文檔椒涯。
iOS開發(fā)ARC內(nèi)存管理技術(shù)要點
如何找到字符串中第一個不重復(fù)的字符
如何在字符串里查找第一個不重復(fù)的字母,即只出現(xiàn)一次的最靠前的字母
哈希表如何處理沖突
介紹 block柄沮。
ARC 會對代碼做什么優(yōu)化?
——比如 NSString *s2 = s1; s2 = nil 這樣的語句废岂,可能就不會有 retain 和 release 方法了祖搓。
介紹一下 MVVM 和 RAC。
ViewModel層湖苞,就是View和Model層的粘合劑拯欧,他是一個放置用戶輸入驗證邏輯,視圖顯示邏輯财骨,發(fā)起網(wǎng)絡(luò)請求和其他各種各樣的代碼的極好的地方镐作。說白了,就是把原來ViewController層的業(yè)務(wù)邏輯和頁面邏輯等剝離出來放到ViewModel層隆箩。
View層该贾,就是ViewController層,他的任務(wù)就是從ViewModel層獲取數(shù)據(jù)捌臊,然后顯示杨蛋。
介紹自己用過哪些開源庫。
——Masonry 和 SnapKit,AFNetWorking六荒,MKNetworkKit护姆,Alamofire矾端,Mantle掏击,SDWebImage
讀過某個庫的源碼么?
——扯了一點 SDWebImage秩铆,后來被告知這個庫用了 runloop 來保證滑動是加載數(shù)據(jù)的流暢性砚亭,自己看了源碼后表示沒有發(fā)現(xiàn),唯一用到 runloop 地方是保證后臺線程一直跑殴玛,也有可能是我理解錯了捅膘,如果錯誤歡迎指正。
SDWebImage 下載了圖片后為什么要解碼滚粟?
——當(dāng)時蒙住了寻仗,面試官很 nice 的解釋了一下,說是要把 png 文件建立一個什么內(nèi)存映射凡壤,目前還不太懂署尤,有空研究一下。
不用臨時變量怎么實現(xiàn) swap(a, b)
——用加法或者異或都可以
二維有序數(shù)組查找數(shù)字
——劍指 offer 第 3題
億級日志中亚侠,查找登陸次數(shù)最多的十個用戶
——(不確定對不對曹体,我的思路是)先用哈希表保存登陸次數(shù)和ID,然后用紅黑樹保存最大的十個數(shù)硝烂。劍指 offer 第 30題
簡述排序算法
——快排箕别,partion 函數(shù)的原理,堆排(不穩(wěn)定)滞谢,歸并排序串稀,基數(shù)排序。
說說你對 OC 中 load 方法和 initialize 方法的異同狮杨。
——主要說一下執(zhí)行時間厨诸,各自用途,沒實現(xiàn)子類的方法會不會調(diào)用父類的禾酱?
說說你對 block 的理解微酬。
—— 三種 block,棧上的自動復(fù)制到堆上颤陶,block 的屬性修飾符是 copy颗管,循環(huán)引用的原理和解決方案。
說說你對 runtime 的理解滓走。
——主要是方法調(diào)用時如何查找緩存垦江,如何找到方法,找不到方法時怎么轉(zhuǎn)發(fā)搅方,對象的內(nèi)存布局比吭。
說說你對 MVC 和 MVVM 的理解绽族。
—— MVC 的 C 太臃腫,可以和 V 合并衩藤,變成 MVVM 中的 V吧慢,而 VM 用來將 M 轉(zhuǎn)化成 V 能用的數(shù)據(jù)。
野指針是什么赏表,iOS 開發(fā)中什么情況下會有野指針检诗?
——野指針是不為 nil,但是指向已經(jīng)被釋放的內(nèi)存的指針瓢剿,不知道什么時候會有逢慌,如果有知道的讀者還望提醒。
很長一道題间狂,讀了很久才讀懂攻泼,目測是 DFS,但是最后沒時間了鉴象,寫了個思路忙菠。
把 "www.zhidao.baidu.com" 這樣的字符串改成 "com/baidu/zhidao/www"
——老題目了,劍指 offer 的炼列,兩次逆序排列即可只搁。
求數(shù)組中和為某個值的所有子數(shù)組,比如數(shù)組是 [5,5,10,2,3] 一共有四個子數(shù)組的和是 15俭尖,比如 [5,10]氢惋,[5,10],[10,2,3]稽犁,[5,5,2,3]焰望。
這個就是簡單的遞歸了,分兩種情況已亥,當(dāng)前位置的數(shù)字在子數(shù)組中熊赖,以及不在子數(shù)組中。