Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何调查ios中的内存泄漏?_Ios_Swift_Memory Leaks_Instruments_Retain Cycle - Fatal编程技术网

如何调查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() } @

我已经创建了一个简单的流程来测试ios应用程序中的内存。我在导航堆栈中有两个视图控制器。我在第一个视图控制器中显示一个警报,允许用户移动到下一个视图控制器。下面是我正在使用的代码

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获得不同。而且,我还可以生成这样一个案例:仪器显示没有泄漏,但对象分配正在增加(),我想在我以前的代码中,由于我的初始视图控制器没有被取消初始化,所以我无法看到效果。