轉(zhuǎn) iOS下KVO使用過程中的陷阱

KVO躏碳,全稱為Key-Value Observing谒主,是iOS中的一種設(shè)計模式,用于檢測對象的某些屬性的實時變化情況并作出響應(yīng)丐膝。網(wǎng)上廣為流傳普及的一個例子是利用KVO檢測股票價格的變動捐友,例如這里淫半。這個例子作為掃盲入門還是可以的,但是當(dāng)應(yīng)用場景比較復(fù)雜時匣砖,里面的一些細節(jié)還是需要改進的科吭,里面有多個地方存在crash的危險。本文旨在逐步遞進深入地探討出一種目前比較健壯穩(wěn)定的KVO實現(xiàn)方案猴鲫,彌補網(wǎng)上大部分教程的不足对人!

首先,假設(shè)我們的目標(biāo)是在一個UITableViewController內(nèi)對tableview的contentOffset進行實時監(jiān)測拂共,很容易地使用KVO來實現(xiàn)為牺弄。

在初始化方法中加入:

[_tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];

在dealloc中移除KVO監(jiān)聽:

[_tableView removeObserver:self forKeyPath:@"contentOffset" context:nil];

添加默認的響應(yīng)回調(diào)方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object

change:(NSDictionary *)change context:(void *)context

{

[self doSomethingWhenContentOffsetChanges];

}

好了,KVO實現(xiàn)就到此完美結(jié)束了宜狐,拜拜势告。。抚恒。開個玩笑咱台,肯定沒這么簡單的,這樣的代碼太粗糙了俭驮,當(dāng)你在controller中添加多個KVO時回溺,所有的回調(diào)都是走同上述函數(shù),那就必須對觸發(fā)回調(diào)函數(shù)的來源進行判斷。判斷如下:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object

change:(NSDictionary *)change context:(void *)context

{

if (object == _tableView && [keyPath isEqualToString:@"contentOffset"]) {

[self doSomethingWhenContentOffsetChanges];

} }

你以為這樣就結(jié)束了嗎遗遵?答案是否定的萍恕!我們假設(shè)當(dāng)前類(在例子中為UITableViewController)還有父類,并且父類也有自己綁定了一些其他KVO呢瓮恭?我們看到雄坪,上述回調(diào)函數(shù)體中只有一個判斷,如果這個if不成立屯蹦,這次KVO事件的觸發(fā)就會到此中斷了。但事實上绳姨,若當(dāng)前類無法捕捉到這個KVO登澜,那很有可能是在他的superClass,或者super-superClass...中飘庄,上述處理砍斷了這個鏈脑蠕。合理的處理方式應(yīng)該是這樣的:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object

change:(NSDictionary *)change context:(void *)context

{

if (object == _tableView && [keyPath isEqualToString:@"contentOffset"]) {

[self doSomethingWhenContentOffsetChanges];

} else {

[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

}

}

這樣就結(jié)束了嗎?答案仍舊是否定的跪削。潛在的問題有可能出現(xiàn)在dealloc中對KVO的注銷上谴仙。KVO的一種缺陷(其實不能稱為缺陷,應(yīng)該稱為特性)是碾盐,當(dāng)對同一個keypath進行兩次removeObserver時會導(dǎo)致程序crash晃跺,這種情況常常出現(xiàn)在父類有一個kvo,父類在dealloc中remove了一次毫玖,子類又remove了一次的情況下掀虎。不要以為這種情況很少出現(xiàn)!當(dāng)你封裝framework開源給別人用或者多人協(xié)作開發(fā)時是有可能出現(xiàn)的付枫,而且這種crash很難發(fā)現(xiàn)烹玉。不知道你發(fā)現(xiàn)沒,目前的代碼中context字段都是nil阐滩,那能否利用該字段來標(biāo)識出到底kvo是superClass注冊的二打,還是self注冊的?

回答是可以的掂榔。我們可以分別在父類以及本類中定義各自的context字符串继效,比如在本類中定義context為@"ThisIsMyKVOContextNotSuper";然后在dealloc中remove observer時指定移除的自身添加的observer。這樣iOS就能知道移除的是自己的kvo衅疙,而不是父類中的kvo莲趣,避免二次remove造成crash。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饱溢,一起剝皮案震驚了整個濱河市喧伞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖潘鲫,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翁逞,死亡現(xiàn)場離奇詭異,居然都是意外死亡溉仑,警方通過查閱死者的電腦和手機挖函,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浊竟,“玉大人怨喘,你說我怎么就攤上這事≌穸ǎ” “怎么了必怜?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長后频。 經(jīng)常有香客問我梳庆,道長,這世上最難降的妖魔是什么卑惜? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任膏执,我火速辦了婚禮,結(jié)果婚禮上露久,老公的妹妹穿的比我還像新娘更米。我一直安慰自己,他們只是感情好抱环,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布壳快。 她就那樣靜靜地躺著,像睡著了一般镇草。 火紅的嫁衣襯著肌膚如雪眶痰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天梯啤,我揣著相機與錄音竖伯,去河邊找鬼。 笑死因宇,一個胖子當(dāng)著我的面吹牛七婴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播察滑,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼打厘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了贺辰?” 一聲冷哼從身側(cè)響起户盯,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嵌施,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后莽鸭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吗伤,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年硫眨,在試婚紗的時候發(fā)現(xiàn)自己被綠了足淆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡礁阁,死狀恐怖巧号,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情氮兵,我是刑警寧澤裂逐,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站泣栈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏弥姻。R本人自食惡果不足惜南片,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望庭敦。 院中可真熱鬧疼进,春花似錦、人聲如沸秧廉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疼电。三九已至嚼锄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蔽豺,已是汗流浹背区丑。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留修陡,地道東北人沧侥。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像魄鸦,于是被迫代替她去往敵國和親宴杀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

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