[iOS]KVOController踩坑記
KVO 作為 iOS 中一種強大並且有效的機制,為我們檢測物件屬性的變化提供了幫助;
但系統提供的KVO介面實在太麻煩,所以開發過程中,我們使用了facebook 開源的KVOController。
今天和大家分享一下在專案開發過程中KVOController的填坑經歷。
第一個坑:
這樣使用會導致self和KVOController形成迴圈引用。
1. KVOController為所有的NSObject物件都提供 -KVOController 屬性,所以這裡self是強引用了KVOController
2. FBKVOController 例項方法-observer:keyPath:options:block: 呼叫後會強引用 self
[_objectInfosMap setObject:infos forKey:object];
這裡的 object 就是 -[KVOController observer:keyPath:options:block:] 傳進來的第一個引數,也就是"self"
也就是把 “self” 作為 key,儲存在FBKVOController的私有變數_objectInfosMap裡面
就會形成 “self ----》 KVOController ----》 self” 這樣的迴圈引用
第二個坑:
為了解決上面的迴圈引用問題,我把程式碼改成了下面醬紫,iOS10必崩
KVOControllerNonRetaining 與 KVOController 的區別就是初始化的時候,retainObserved 為 NO
上面“坑一”說到,“self” 是被 _objectInfosMap 強引用了,retainObserved 傳 NO,就可以解決這個問題
但是事情並沒有這樣結束。接下來的測試,ios10的系統必崩
這是 "self" 釋放了,但是沒有呼叫到 removeObserver 的崩潰棧
在 -[FBKVOController _unobserveAll] 裡面除錯,發現 _objectInfosMap 中已經沒有了 “self”
呼叫順序是這樣的:
1. [self dealloc]
2. [FBKVOController dealloc]
3. [FBKVOController dealloc] 裡面找存起來的"self",並呼叫 [self removeObserver]
因為第3步中,“self”已經被釋放,FBKVOController 中對“self” 的 weak 指標已經置 nil
所以最終並沒有呼叫到 “self” 的 removeObserver
總結:
一、物件監聽自己的屬性變化,應該在setter中監聽;而不應該使用 -[self.KVOController observe:self]
二、物件dealloc時,指向物件的weak指標已經置為nil
相關文章
- Realm ios踩坑筆記iOS筆記
- iOS自動化打包部署踩坑記iOS
- iOS私有Pod, 指南+踩坑iOS
- removeChild踩坑記REM
- vue 踩坑記Vue
- mpVue 踩坑記Vue
- vuepress踩坑記Vue
- ReactNative 踩坑之 iOS 原生元件ReactiOS元件
- DietPi踩坑記錄
- sealos踩坑記錄
- strtotime 踩坑記錄
- Dubbo 2.7.1 踩坑記
- 踩坑日記(1)
- DelayedWorkQueue踩坑筆記筆記
- laravel踩坑記錄Laravel
- PHP 8 踩坑記PHP
- Sentry 部署踩坑記
- RN 踩坑:雜記
- appium IOS 真機踩坑分享 NoSuchElementErrorAPPiOSError
- iOS開發之UIRefreshControl使用踩坑iOSUI
- MySQL_踩坑記錄MySql
- Electron踩坑日記-2
- Opengl ES之踩坑記
- Android Studio踩坑記錄Android
- gorm踩坑記錄(一)GoORM
- Go踩坑筆記(十九)Go筆記
- Kubernetes探針踩坑記
- Go json 踩坑記錄GoJSON
- 筆記:Mysql踩坑之路筆記MySql
- node link 踩坑記錄
- ABP框架踩坑記錄框架
- Electron工程踩坑記錄
- Nginx的踩坑日記Nginx
- MUI的踩坑筆記UI筆記
- PWA - ios 新增到桌面功能(踩坑之路)iOS
- Xcode10和iOS12踩坑XCodeiOS
- 工作踩坑問題記錄
- list複製踩坑記錄
- Cypress 踩坑記 - DOM 遮擋