如何调查 ios 中的内存泄漏?

How to investigate into memory leaks in ios?

我创建了一个简单的流程来测试 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)

    } 

}

在浏览了提到不应该有强引用循环的资源后,我在代码中使用了 unowned self。检查 Instruments 中的泄漏,我得到了下图。

图表显示没有泄漏,如绿色刻度线所示。然而,当我在两个视图控制器之间来回移动时,内存使用图正在增加。是什么导致内存使用量增加(第一个问题)?

接下来,我还检查了将unowned self替换为self[=35的效果=]。我得到的结果和以前一样。这表明没有强参考。参考这个例子(第二个问题),我们如何判断是否存在strong retain cycle?

转到Edit Scheme -> Run -> Diagnostics 现在像截图一样勾选Malloc stack After doing that, rebuild and run . Now open Debug memory graph, you will see purple icon on the list of your class where memory leak has occurred. see this screenshot Example Repo with memory leak is Swift Memory Leak Demo Here is the view for memory leak with real example with the attached repo 您可以对您的项目执行相同的过程来识别内存泄漏

从你的第二个问题开始。

撇开工具不谈,您的代码正在对一个 UIViewController 进行排序,如果这么简单就将其忽略,让我们暂时不要考虑保留周期。

Strong vs Weak vs Unowned

1- 通常,在创建 属性 时,引用是强引用,除非它们被声明为弱引用或无主引用。

2- 将 属性 标记为弱,它不会增加引用计数

3- 无主引用介于两者之间,它们既不是强引用也不是可选类型 编译器将假定对象未被释放,因为引用本身仍处于分配状态。

What是保留周期:

Unless there is some other reference to the parent or child, they both become orphaned. But the retain cycle between the parent and child prevent either from being released and they become wasted memory.

A child should never retain a parent. If anything, use a weak reference in the child to maintain a reference to the parent.

现在让我们看看你有什么,你正在使用 UINavigationController & segue,好吧 UINavigationController 是一个后进先出堆栈,同样根据 apple

A navigation controller is a container view controller that manages one or more child view controllers in a navigation interface. In this type of interface, only one child view controller is visible at a time.

所以检查你的 UIViewController deinit 函数,我认为你可以毫无疑问地告诉你引用被释放了。

现在让我们试着看看 UIAlertAction 中的其他东西,你有这个 [unowned self]

When to use unowned self or weak self

The only time where you really want to use [unowned self] or [weak self] is when you would create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around.

In the specific case of a closure, you just need to realize that any variable that is referenced inside of it, gets "owned" by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to do the [unowned self] or [weak self]. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure.

正如你所说,同时切换 [unowned self][self] 什么也没做。

现在第一个问题,

仪器泄漏检查很简单,只需比较一段时间内显着增加的内存,并根据发生的情况将所有内容相互比较,这不是 100% 的描述,但很接近,所以每当那个绿色勾号弹出时,就意味着你通过了测试。并不意味着 100% 你是安全的,你可以直观地看到仪器底部的分配,观察值变化 (增加/减少) .. 如果有东西在增加而没有不断减少,我想你发现了你的问题。

调查你的情况我认为你不会找到