我如何停止内存泄漏并回收150MB的内存— Swift

在iOS开发人员中,内存管理可能不是一个有趣的话题,但是如果您想将应用程序提升到一个新的水平,它需要引起注意。 内存泄漏的应用确实更有可能被iOS强制杀死。 为用户提供低于标准的体验。

好消息是,多年来,检测内存泄漏变得越来越容易。 XCode提供了一些非常好的工具,因此您可以修复并避免泄漏。

如果您在应用程序中遇到内存相关问题,或者只是想了解有关iOS中内存管理的更多信息,请在下面列出我的前3个资源。 实际上,我最近实际上已使用这些资源来修复应用程序中的主要内存泄漏。

  1. Kaira Diagne撰写的Swift的Memory Management in Swift文章:该文章对该主题做了很好的介绍,并提供了一个内存泄漏修复程序的示例。
  2. 这个出色的Stackoverflow答案描述了如何使用XCode的Allocations Instrument,以及更新的“ Debug Memory Graph”选项。 后者绝对是救命稻草
  3. 这个惊人的Tweet基本上很有趣,可以捕获应用程序中的内存问题。 它解释说,您可以在XCode中放置一个断点,让您立即(仅通过播放声音)就知道UIViewController是从内存中释放的。 从第1天起将此断点添加到您的应用程序中,您肯定会在发生内存泄漏时及时发现它们。

在我的武器库中拥有这些工具后,我针对了应用程序中存在一段时间的内存泄漏。 该应用程序称为Buluttan,它是一款气象应用程序,具有自己的天气预报和警报。 在显示嵌入了Map的视图控制器时发生泄漏。 这是泄漏的发生方式:

看起来很恐怖,不是吗? 由于内存泄漏,在第二步中加载的MapKit永远不会从内存中删除。 该应用程序每次轻按都会变重,最终会从内存中消除力量。

这里发生的是第二个ViewController以某种方式创建了一个强大的参考周期。 导致无法将其从内存中删除 。 即使用户在上面的第3步中取消了地图,该地图仍在我们的记忆中。 强大的参考周期导致它不会被释放。

找出周期发生的地方实际上并不难。 通常认为强周期的原因是:

  1. 强委托:如果您在代码中使用委托模式,则很可能忘记了使用引用定义委托。 将委托工作的实体应具有如下定义的委托:

私有弱变量myDelegate:ImportantDelegate? =。无

如果没有weak关键字,则会立即引入一个强循环。 这也是我的问题! 我已经使用强大的委托初始化了LoaderView。 那造成了强大的循环!

2.封闭性强:大多数网络完成处理程序都作为封闭性从UI传递。 网络调用完成后,将调用这些处理程序,并且UI会自行更新。 如果您的网络处理程序实体对您的ViewController有很强的引用,则VC永远不会从内存中删除。 网络处理程序仍在指向它。 通过使用捕获列表使self成为弱引用,可以防止此情况:

myNetworkHandler.fetchSomething {[弱自我](fetchedEntities)在

守卫让strongSelf =自我else {return}

strongSelf.updateUI()

}


希望这可以澄清内存泄漏的形成方式以及如何防止泄漏。 本文开头列出的前3个资源应该真正有助于解决任何内存问题。 特别是,第三资源真是太棒了!

处理内存错误时的最后一个提示:XCode中的内存图确实是一个出色的工具。 它告诉您谁仍然对您的ViewController拥有强大的引用,并为您指出正确的方向。 就我而言,这使我摆脱了许多强周期,但是删除最后一个强周期有点麻烦。 这是图的样子:

Graph告诉我,UIApplication在其_statusBarTintColorLockingControllers中持有对我的VC的引用 。 我不知道这个指针是什么,因为我没有定义这样的变量。 问题最终出在我的代表中,并且与UIApplication并没有真正的关系。 因此,如果您看到此图,请尝试在代码中寻找强循环。 CocoaTouch并不是造成问题的真正原因。 这有点误导。

干杯,

古文