在 iOS 開發中 記憶體流失是常見的問題, 這裡整理下常用的記憶體檢測方法. 一 靜態檢測方法
使用XCode分析功能,Product->Analyze
使用靜態檢測可以檢查出一些明顯的沒有釋放的記憶體,包括NSObject和CF開頭的記憶體流失.
缺點: 不能檢測block導致的記憶體流失問題
二 動態檢測方法
使用 instruments
三 dealloc 重新檢測
重寫dealloc 方法, 在介面返回或者對象銷毀的時候, 判斷是否調用
四 第三方檢測方法
MLLeaksFinder
主要檢查UI方面的泄漏,整合簡單,優點如下:
1.不同於instrument的分析功能,需要人工觀察,這個工具自動檢測,發現有泄漏後可以即時進行提示,雖然主要是針對UI,但對於一般的工程來說,記憶體流失的情境中還是以UI居多,因此可以解決很大部分的問題。
2.在新功能的開發過程和解決bug的過程中,出現記憶體流失都可以很輕鬆的檢測出來。
其原理如下: (1) 檢測viewController在pop後 是否已經釋放
(2) 在viewWillAppear中將標誌位設定NO
(3) 在Navgation pop後將標誌位設定為YES
(4) 在viewDidDisappear 中判斷標誌位
我們根據這個原理, 簡單實現一個自己簡易的記憶體偵查工具:
(1) 用runtime的技術交換 viewController 的 viewWillAppear 和 viewDidDisappear;
(2) 在viewWillAppear 中將標誌位設為 NO, 代碼如下:
- (void)sw_viewWillAppear:(BOOL)animated{ [self sw_viewWillAppear:animated]; objc_setAssociatedObject(self, &kLeakMemory, @(NO), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}
(3) 交換 navigationController 的 popViewControllerAnimated, 並在其中將標誌位設為YES
- (nullable UIViewController *)sw_popViewControllerAnimated:(BOOL)animated{ UIViewController *vc = [self sw_popViewControllerAnimated:animated]; extern const char *kLeakMemory; objc_setAssociatedObject(self, &kLeakMemory, @(YES), OBJC_ASSOCIATION_RETAIN_NONATOMIC); return vc;}
(4) 在viewController的viewDidDisappear中判斷標誌位, 並延時檢測dealloc是否調用
- (void)sw_viewDidDisappear:(BOOL)animated{ [self sw_viewDidDisappear:animated]; if (objc_getAssociatedObject(self, &kLeakMemory)) { [self willDealloc]; }}- (BOOL)willDealloc { if (![super willDealloc]) { return NO; } return YES;}
/**super willDealloc*/- (BOOL)willDealloc{ // 這裡注意, 使用weakSelf 防止引起循環參考 __weak typeof(self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ __strong typeof(weakSelf) strongSelf = weakSelf; [strongSelf showMsg:NSStringFromClass([strongSelf class])]; }); return YES;}- (void)showMsg:(NSString *)msg{ UIAlertView *alertViewTemp = [[UIAlertView alloc] initWithTitle:@"Leak" message:msg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; [alertViewTemp show];}
Demo
如有疑問, 歡迎指出.