在 iOS 开发中,使用 UIKit 的视图和视图控制器构建保留循环非常容易。您经常在不同的视图和控制器以及相应的代理之间有依赖性。这些内存泄漏往往无法被发现,特别是当它们不消耗大量内存或者在不太完善的生产边缘情况下发生时。Leak Finder 是一个小工具,您可以轻松将其集成到您的应用程序中。它自动发现视图控制器中可能存在的内存泄漏,并打印警告。因此,您无需添加调试消息即可查看视图控制器或视图是否被释放。
Leak Finder 可在 CocoaPods 上使用,并具有一行集成。首先,您需要将 pod 添加到您的项目中。请在 Podfile 中添加以下内容并运行 pod install
pod 'LeakFinder'
如果您从未使用过 CocoaPods,您可以在 NSHipster 的指南 或 官方指南 中了解更多有关 CocoaPods 的信息。
在添加了 pod 之后,您可以使用 header,或者如果您使用 Swift,创建一个 Objective-C 桥接头
#import <LeakFinder/ViewControllerObserver.h>
之后,您只需实例化视图控制器观察者的单例即可。在应用程序委托的 application:didFinishLaunchingWithOptions:
方法中执行此操作是一个好地方。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/// Instantiate the view controller observer which detects memory leaks.
[ViewControllerObserver sharedInstance];
return YES;
}
那么就这样!如果您现在运行应用程序并且您的应用程序中确实存在内存泄漏,您将在控制台(或者更准确地说,是系统记录)中看到类似于以下的消息:
2015-09-19 23:16:28.838 LeakFinder[8262:79575] Possible memory leak: ViewController <MyViewController: 0x7fa941765f90> (MyViewController)
这意味着您在 MyViewController
视图控制器类中有一个可能的内存泄漏。如果您想要获取更多或更好的关于泄漏对象的信息,您可以为它编写自己的报告器,从而完全控制报告。
如果您想看看如何在没有将其集成到您的应用程序中的情况下使用它的示例,您可以运行以下命令:
pod try LeakFinder
以打开一个使用 LeakFinder 查找内存泄漏的示例应用程序。
所有检测到的内存泄漏都通过视图控制器观察者的报告器来报告。您可以交换报告器,通过设置视图控制器观察者上的 reporter
属性来实现。
MyCustomReporter myReporter = [MyCustomReporter new];
[ViewControllerObserver sharedInstance].reporter = myReporter;
例如,您可以实现一个报告器,每当检测到内存泄漏时,它会抛出一个错误。报告器还将传递一个泄漏对象的实例,因此您可以在报告器中设置断点,进一步检查泄漏对象。
任何实现ViewControllerObserverReporter
协议的对象都可以作为报告器。
默认情况下,使用ViewControllerObserverSystemOutReporter
来报告内存泄漏。它将所有泄漏报告到系统日志。
基本思路是,视图控制器及其视图(包括所有子视图)在视图控制器被解除后不久就会被释放。这个小工具会钩住视图控制器的解除。在被解除后,它等待一个可配置的时间间隔。时间间隔过后,它会检查视图控制器及其所有视图是否已释放。如果没有,控制台会显示警告。
您可以通过查看本存储库中的示例应用程序来查看一些示例。
从技术上讲,它通过hook到UIViewController
和UINavigationController
的方法,以检测视图控制器何时被解除。
Leak finder遵循MIT/Expat许可。有关详细信息,请参阅[LICENSE](https://github.com/Lukas-Stuehrk/LeakFinder/blob/master/LICENSE)
。
我欢迎有关使用、改进以及当然还有错误的任何反馈。请通过GitHub的问题跟踪器报告所有错误和反馈。
至少有两个类似的项目采用了相关方法。不幸的是,在我完成了漏检的实现后,我才发现了这些项目。然而,这两个项目都没有在视图中实现漏检(而这个项目则实现了)。
viewDidDisappear:
)。这种方法会在漏检中导致大量的误报。它也缺乏对视图中的漏检。