若是一個類在釋放事後,dealloc方法沒有執行,那麼就表明着這個類還被其餘對象所引用,引用計數不爲0,這樣就形成了內存泄露json
昨天其餘業務線開發告知他所依賴的我這邊的父類VC的-dealloc 方法不執行,叫我跟一下函數
因而我很快的想到-dealloc沒執行,確定是循環引用內存泄露之類的問題,因而打開instrument,復現着觸發步驟,一個紅點,兩個紅點;嘿,就是你了,結果查找call trees事後就矇蔽了,報錯是jsonmodel的實例方法有問題,難道是某個子類化的JsonModel對象引用了這個VC? 可是這個類有接近兩千行,我怎麼看?指針
因而小組大神出場,其在使用了一番instrument事後,發現確實這個VC在釋放事後引用計數不爲0,可是從各個內存的使用狀況啊,調用堆棧啊並看不出錯誤是出如今哪裏(他說instrument改版後不太會用了),在得知個人業務需求事後,因而叫我去用最笨的辦法去解決-- 把全部改動屏蔽掉,而後逐個取消屏蔽,看內存泄露在哪個方法裏面code
因而嘗試,定位,嘗試,定位對象
最終找到循環引用的地方:blog
在block外面是把self指針置爲weak了的,可是進入block事後,倒是仍然使用的是強self指針去調用的本類方法,這樣一來,便形成了經典的循環引用的問題:內存
self ---> block block ---> self
因而VC裏面就沒辦法釋放掉,這就是形成VC的dealloc方法未能執行的緣由開發
#define weakify(...) \\ autoreleasepool {} \\ metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__) #define strongify(...) \\ try {} @finally {} \\ _Pragma("clang diagnostic push") \\ _Pragma("clang diagnostic ignored \\"-Wshadow\\"") \\ metamacro_foreach(rac_strongify_,, __VA_ARGS__) \\ _Pragma("clang diagnostic pop")
他們的做用主要是在block內部管理對self的引用:input
@weakify(self); // 定義了一個__weak的self_weak_變量 [RACObserve(self, name) subscribeNext:^(NSString *name) { @strongify(self); // 局域定義了一個__strong的self指針指向self_weak self.outputLabel.text = name; }];
這兩個宏必定成對出現,先weak再strong.能夠很好的管理Block內部對self的引用。 固然你若是是一個不愛用黃色宏的盆友的話,你能夠用原生代碼寫出來it
__weak typeof(self) weakSelf = self; self.Button.rac_command = [[RACCommand alloc] initWithEnabled:textSig signalBlock:^RACSignal *(NSString * input) { __strong typeof(weakSelf) strongSelf = weakSelf; return nil; }];
在使用instrument的過程當中可能由於某些緣由,檢測不到具體的某個函數的內存泄露,這個時候就不能依賴instrument了(也多是本渣不太懂怎麼調,歡迎指正),這個時候就只能使用最笨的辦法 --- 還原二分法來trick了