日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS下KVO使用过程中的陷阱

發布時間:2025/3/21 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS下KVO使用过程中的陷阱 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

KVO,全稱為Key-Value Observing,是iOS中的一種設計模式,用于檢測對象的某些屬性的實時變化情況并作出響應。網上廣為流傳普及的一個例子是利用KVO檢測股票價格的變動,例如這里。這個例子作為掃盲入門還是可以的,但是當應用場景比較復雜時,里面的一些細節還是需要改進的,里面有多個地方存在crash的危險。本文旨在逐步遞進深入地探討出一種目前比較健壯穩定的KVO實現方案,彌補網上大部分教程的不足!

首先,假設我們的目標是在一個UITableViewController內對tableview的contentOffset進行實時監測,很容易地使用KVO來實現為。

在初始化方法中加入:

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

在dealloc中移除KVO監聽:

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

添加默認的響應回調方法:

1 2 3 4 5 - (void)observeValueForKeyPath:(NSString?*)keyPath ofObject:(id)object ????????????????????????change:(NSDictionary?*)change context:(void?*)context { ???????[self?doSomethingWhenContentOffsetChanges]; }

好了,KVO實現就到此完美結束了,拜拜。。。開個玩笑,肯定沒這么簡單的,這樣的代碼太粗糙了,當你在controller中添加多個KVO時,所有的回調都是走同上述函數,那就必須對觸發回調函數的來源進行判斷。判斷如下:

1 2 3 4 - (void)observeValueForKeyPath:(NSString?*)keyPath ofObject:(id)object ????????????????????????change:(NSDictionary?*)change context:(void?*)context { ????if?(object == _tableView && [keyPath isEqualToString:@"contentOffset"]) {
1 [self?doSomethingWhenContentOffsetChanges];
1 } }

你以為這樣就結束了嗎?答案是否定的!我們假設當前類(在例子中為UITableViewController)還有父類,并且父類也有自己綁定了一些其他KVO呢?我們看到,上述回調函數體中只有一個判斷,如果這個if不成立,這次KVO事件的觸發就會到此中斷了。但事實上,若當前類無法捕捉到這個KVO,那很有可能是在他的superClass,或者super-superClass...中,上述處理砍斷了這個鏈。合理的處理方式應該是這樣的:

1 2 3 4 5 6 7 8 9 - (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]; } }

?

這樣就結束了嗎?答案仍舊是否定的。潛在的問題有可能出現在dealloc中對KVO的注銷上。KVO的一種缺陷(其實不能稱為缺陷,應該稱為特性)是,當對同一個keypath進行兩次removeObserver時會導致程序crash,這種情況常常出現在父類有一個kvo,父類在dealloc中remove了一次,子類又remove了一次的情況下。不要以為這種情況很少出現!當你封裝framework開源給別人用或者多人協作開發時是有可能出現的,而且這種crash很難發現。不知道你發現沒,目前的代碼中context字段都是nil,那能否利用該字段來標識出到底kvo是superClass注冊的,還是self注冊的?

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

?

=======================================================

by 編程小翁@博客園

from:?http://www.cnblogs.com/wengzilin/p/4346775.html

總結

以上是生活随笔為你收集整理的iOS下KVO使用过程中的陷阱的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。