問(wèn)題:我們知道,從 Storyboard 往編譯器拖出來(lái)的 UI 控件的屬性是 weak 的,如下所示
@property (weak, nonatomic) IBOutlet UIButton *myButton;
那么,如果有一些 UI 控件我們要用代碼的方式來(lái)創(chuàng)建,那么它應(yīng)該用 weak 還是 strong 呢?為什么?
答案:這是一道有意思的問(wèn)題,這個(gè)問(wèn)題是我當(dāng)時(shí)和 Lancy 一起寫(xiě)猿題庫(kù) App 時(shí)產(chǎn)生的一次小爭(zhēng)論。簡(jiǎn)單來(lái)說(shuō),這道題并沒(méi)有標(biāo)準(zhǔn)答案,但是答案背后的解釋卻非常有價(jià)值,能夠看出一個(gè)人對(duì)于引用計(jì)數(shù),對(duì)于 view 的生命周期的理解是否到位。
從昨天的評(píng)論上,我們就能看到一些理解非常不到位的解釋?zhuān)纾?/p>
@spume 說(shuō):Storyboard 拖線使用 weak 是為了規(guī)避出現(xiàn)循環(huán)引用的問(wèn)題。
這個(gè)理解是錯(cuò)誤的,Storyboard 拖出來(lái)的控件即使是 strong 的,也不會(huì)有循環(huán)引用問(wèn)題。
我認(rèn)為 UI 控件用默認(rèn)用 weak,根源還是蘋(píng)果希望只有這些 UI 控件的父 View 來(lái)強(qiáng)引用它們,而 ViewController 只需要強(qiáng)引用 ViewController.view 成員,則可以間接持有所有的 UI 控件。這樣有一個(gè)好處是:在以前,當(dāng)系統(tǒng)收到 Memory Warning 時(shí),會(huì)觸發(fā) ViewController 的 viewDidUnload 方法,這樣的弱引用方式,可以讓整個(gè) view 整體都得到釋放,也更方便重建時(shí)整體重新構(gòu)造。
但是首先 viewDidUnload 方法在 iOS 6 開(kāi)始就被廢棄掉了,蘋(píng)果用了更簡(jiǎn)單有效地方式來(lái)解決內(nèi)存警告時(shí)的視圖資源釋放,具體如何做的呢?嗯,這個(gè)可以當(dāng)作某一期的面試題展開(kāi)介紹??傊褪?,除非你特殊地操作 view 成員,ViewController.view 的生命期和 ViewController 是一樣的了。
所以在這種情況下,其實(shí) UI 控件是不是 weak 其實(shí)關(guān)系并不大。當(dāng) UI 控件是 weak 時(shí),它的引用計(jì)數(shù)是 1,持有它的是它的 superview,當(dāng) UI 控件是 strong 時(shí),它的引用計(jì)數(shù)是 2,持有它的有兩個(gè)地方,一個(gè)是它的 superview,另一個(gè)是這個(gè) strong 的指針。UI 控件并不會(huì)持有別的對(duì)象,所以,不管是手寫(xiě)代碼還是 Storyboard,UI 控件是 strong 都不會(huì)有循環(huán)引用的。
那么回到我們的最初的問(wèn)題,自己寫(xiě)的 view 成員,應(yīng)該用 weak 還是 strong?我個(gè)人覺(jué)得應(yīng)該用 strong,因?yàn)橛?weak 并沒(méi)有什么特別的優(yōu)勢(shì),加上上一篇面試題文章中,我們還看到,其實(shí) weak 變量會(huì)有額外的系統(tǒng)維護(hù)開(kāi)銷(xiāo)的,如果你沒(méi)有使用它的特別的理由,那么用 strong 的話應(yīng)該更好。
另外有讀者也提到,如果你要做 Lazy 加載,那么你也只能選擇用 strong。
當(dāng)然,如果你非要用 weak,其實(shí)也沒(méi)什么問(wèn)題,只需要注意在賦值前,先把這個(gè)對(duì)象用 addSubView 加到父 view 上,否則可能剛剛創(chuàng)建完,它就被釋放了。
在我心目中,這才是我喜歡的面試題,沒(méi)有標(biāo)準(zhǔn)答案,每種方案各有各的特點(diǎn),面試者能夠足夠分清楚每種方案的優(yōu)缺點(diǎn),結(jié)合具體的場(chǎng)景做選擇,這才是優(yōu)秀的面試者。
1.懶加載的對(duì)象必須用strong的原因在于,如果使用weak,對(duì)象沒(méi)有被沒(méi)有被強(qiáng)引用,過(guò)了懶加載對(duì)象就會(huì)被釋放掉。