以前我們經(jīng)常會(huì)重寫控制器的dealloc方法混狠,并且在dealloc方法中加上[[NSNotificationCenter defaultCenter] removeObserver:self];這行代碼摘投。好消息是現(xiàn)在的版本,xcode7以上不用重寫dealloc方法集币,在里面加上這行代碼了晴竞。那么,為什么這么說呢崔慧?為了佐證我的猜測,我嘗試弄清楚UIViewController的dealloc方法是怎么實(shí)現(xiàn)的穴墅。
依稀記得xcode5以前(具體版本記不清楚了惶室,反正就是比較早的版本)温自,那時(shí)候系統(tǒng)的控制器dealloc方法中還不會(huì)自動(dòng)調(diào)用移除觀察者的方法,需要我們手動(dòng)移除皇钞,否則等控制器銷毀后悼泌,通知沒有移除,就可能發(fā)生崩潰夹界。
下面寫個(gè)demo來證明UIViewController的dealloc方法中確實(shí)調(diào)用了[[NSNotificationCenter defaultCenter] removeObserver:self]方法馆里。首先我們要先建一個(gè)NSNotificationCenter的分類,代碼如下
熟悉runtime的同學(xué)應(yīng)該很清楚可柿,這是runtime的交換方法鸠踪,目的是為了跟蹤系統(tǒng)調(diào)用removeObserver:,當(dāng)調(diào)用此方法時(shí)會(huì)打印--my_removeObserver-复斥。
然后我們要寫一個(gè)控制器的跳轉(zhuǎn)营密,在DXViewController控制器銷毀時(shí),系統(tǒng)會(huì)調(diào)用控制器的dealloc方法目锭。
新建一個(gè)DXViewController類评汰,繼承UIViewController,DXViewController.m如下
上面這2步其實(shí)就是從ViewController跳轉(zhuǎn)到DXViewController痢虹,然后從DXViewController跳回ViewController時(shí)被去,DXViewController控制器會(huì)銷毀,系統(tǒng)會(huì)自動(dòng)調(diào)用[DXViewController dealloc]方法奖唯,熟悉mrc的同學(xué)應(yīng)該知道编振,其實(shí)31行代碼還有一行隱藏的[super dealloc]方法,也就是我們的UIViewController的dealloc方法臭埋,下面我們來看看為什么說在UIViewController的dealloc方法中確實(shí)調(diào)用了[[NSNotificationCenter defaultCenter] removeObserver:self]方法踪央。
我們故技重施,給UIViewController添加一個(gè)分類瓢阴,目的是交換它的dealloc方法畅蹂,跟蹤它的調(diào)用,代碼如下(這個(gè)類要打開mrc荣恐, -fno-objc-arc)
運(yùn)行項(xiàng)目液斜,我們可以看到打印如下
證明在UIViewController的分類的第29行代碼[self my_dealloc]里面確實(shí)調(diào)用了移除通知的方法,這里的[self my_dealloc]其實(shí)就是UIViewController的dealloc方法(不懂的同學(xué)可以去弄清楚runtime交換方法是怎么用的)叠穆。
問題到這里其實(shí)還沒完少漆,我們只能證明【UIViewController dealloc】方法里面確實(shí)調(diào)用了[[NSNotificationCenter defaultCenter] removeObserver:self]方法,但是不能證明一定是UIViewController dealloc】調(diào)用了移除通知中心的方法硼被,因?yàn)閐ealloc方法中其實(shí)是[super dealloc]示损。。為了證明移除觀察者方法不是在UIViewController的父類UIResponder的dealloc中調(diào)用嚷硫,我們必須還要再做一件事检访。
給UIResponder添加一個(gè)分類始鱼,重寫dealloc方法,代碼如下脆贵。原理:(在分類中覆寫原有類的方法医清,系統(tǒng)只會(huì)調(diào)用分類的方法)
再次運(yùn)行項(xiàng)目,發(fā)現(xiàn)打印跟上面一樣卖氨。至此会烙,我們排除了UIViewController的父類UIResponder以及其父類的父類等的影響,確定了系統(tǒng)在UIViewController的dealloc方法中調(diào)用了[[NSNotificationCenter defaultCenter] removeObserver:self]方法筒捺。
結(jié)論:只要控制器能正常釋放(不出現(xiàn)循環(huán)引用控制器持搜,會(huì)走dealloc)的前提下,我們不用重寫控制器的dealloc方法焙矛,在里面加[[NSNotificationCenter defaultCenter] removeObserver:self]代碼了葫盼。
啟發(fā):隨著iOS版本的升級,蘋果其實(shí)會(huì)優(yōu)化UIKit或者其他框架的實(shí)現(xiàn),比如[[NSNotificationCenter defaultCenter] removeObserver:self]系統(tǒng)就幫我們寫了村斟。即使強(qiáng)大如蘋果贫导,也在一直優(yōu)化它的框架和代碼的實(shí)現(xiàn),我們也應(yīng)該不斷跟蘋果學(xué)習(xí)優(yōu)化自己的代碼蟆盹。
2018.7更新 ------------------------------------------------------
這篇文章的初衷其實(shí)是本人與同事打賭說控制器的dealloc方法不用寫移除觀察者了孩灯,因?yàn)閁IViewController的dealloc方法已經(jīng)做了這件事(蘋果文檔寫的)。但是同事由于沒看過相關(guān)文檔不信逾滥,故我想了個(gè)辦法證明UIViewController的dealloc方法確實(shí)寫了[[NSNotificationCenter defaultCenter] removeObserver:self]峰档。
由于近來開源了UIKit和Foundation (iOS開源),這篇文章其實(shí)沒有太大的意義了寨昙,但是思路還是值得借鑒讥巡。下面給出證據(jù)
可以得出代碼實(shí)現(xiàn)如下圖
文章的demo地址在 jianshuExample下面的removeObserverDemo里