如何调查ios中的内存泄漏?
我已经创建了一个简单的流程来测试ios应用程序中的内存。我在导航堆栈中有两个视图控制器。我在第一个视图控制器中显示一个警报,允许用户移动到下一个视图控制器。下面是我正在使用的代码如何调查ios中的内存泄漏?,ios,swift,memory-leaks,instruments,retain-cycle,Ios,Swift,Memory Leaks,Instruments,Retain Cycle,我已经创建了一个简单的流程来测试ios应用程序中的内存。我在导航堆栈中有两个视图控制器。我在第一个视图控制器中显示一个警报,允许用户移动到下一个视图控制器。下面是我正在使用的代码 class ViewController: UIViewController { @IBOutlet weak var labelInfo: UILabel! override func viewDidLoad() { super.viewDidLoad() } @
class ViewController: UIViewController {
@IBOutlet weak var labelInfo: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func showNextScreen(_ sender: Any) {
let alert = UIAlertController(title: "Alert", message: "Go to next screen?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { [unowned self] (action) in
self.performSegue(withIdentifier: "showNextScreen", sender: nil)
}))
alert.addAction(UIAlertAction(title: "No", style: .default, handler: { [unowned self] (action) in
self.labelInfo.text = "You did not move to next screen"
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
}
在阅读了提到不应该有强引用循环的参考资料之后,我在代码中使用了无主self。检查仪器的泄漏情况,我得到了下面的图表
如绿色记号所示,图表显示无泄漏。然而,当我向后移动并在两个视图控制器之间来回移动时,内存使用图正在增加。是什么导致了内存使用量的增加(第一个问题)
接下来,我还检查了用self替换unowned self的效果。我得到的结果和以前一样。这表明没有强有力的参考。我们如何参照本例确定强保留周期的存在(第二个问题)
进入
编辑方案->运行->诊断
现在,像屏幕截图一样勾选Malloc stack。完成后,重建并运行。现在打开Debug memory graph
,您将在发生内存泄漏的类列表上看到紫色图标。请参阅此屏幕截图示例带内存泄漏的Repo。此处是带附加Repo的真实示例的内存泄漏视图
从第二个问题开始,您可以在项目中按照相同的步骤识别内存泄漏 撇开仪器不谈,您的代码正在对一个
UIViewController
进行分段,如果这么简单,请不要考虑保留循环
–
1-通常,在创建属性时,引用是强的,除非它们被声明为弱或无主
2-当属性标记为弱时,它不会增加引用计数
3-无主引用介于两者之间,它们既不是强引用,也不是可选类型
编译器将假定对象未解除分配,因为引用本身仍保持分配状态
是保留周期:
除非对父母或孩子有其他的提及,否则他们都会成为孤儿。但父子之间的保留周期阻止了
被释放,它们就变成了浪费的内存
孩子永远不应该留住父母。如果有任何问题,请使用弱电
子对象中的引用,以维护对父对象的引用
现在让我们看看您拥有什么,您使用的是UINavigationController&segue
,那么UINavigationController
也是一个后进先出堆栈,也是根据
导航控制器是一个容器视图控制器,用于管理导航界面中的一个或多个子视图控制器。在这种类型的界面中,一次只能看到一个子视图控制器
因此,检查您的UIViewController
deinit
函数,我认为您可以毫无问题地判断引用是否已解除分配
现在,让我们尝试查看UIAlertAction
中的其他内容。您有这个[无主自我]
唯一一次你真的想使用[无主的自我]或[软弱的自我]
self]是您创建强引用循环的时间。强壮的
引用循环是指对象结束的所有权循环
相互拥有(可能通过第三方),因此
永远不会被解除分配,因为他们都在确保
其他人留下来
在闭包的特定情况下,您只需要意识到
在其内部引用的变量将被闭包“拥有”。
只要闭包还在,这些对象就一定会被关闭
围绕阻止这种所有权的唯一方法是做[无主]
自我]或[软弱的自我]。如果一个类拥有一个闭包,那么这个闭包
捕获对该类的强引用,则具有强引用
闭包和类之间的引用循环。这还包括
如果类拥有某个拥有闭包的对象
正如你所说,切换[无主的自我]
和[自我]
没有任何作用
现在第一个问题,
仪器泄漏检查很简单,它只是比较一段时间内内存的显著增加,并根据发生的情况相互比较,这不是100%的描述,而是非常接近,所以每当出现绿色勾号时,就意味着你通过了测试。这并不意味着你100%安全,你可以在仪器底部看到分配情况,观察数值变化(增加/减少)。。如果有什么东西在不断增加而没有减少,我想你发现了你的问题
看看你的案子,我想你找不到一个VC@MohmmadS我使用导航的后退按钮controller@Sujal使用导航控制器?对我来说,查看视图控制器是否解除分配的最简单、最直接的方法是在
deinit
中放置一条打印行。在我的项目中,我有一个BaseViewController
类,它在deinit
方法中调用Utils.debugPrint(\(self)deinitialized”)
。我所有的VC都是子类。在第二个viewcontroller中添加类似的alertcontroller代码,我可以使用self和unowned self获得不同。而且,我还可以生成这样一个案例:仪器显示没有泄漏,但对象分配正在增加(),我想在我以前的代码中,由于我的初始视图控制器没有被取消初始化,所以我无法看到效果。