【问题标题】:Navigation Controller not releasing memory, memory leak?导航控制器不释放内存,内存泄漏?
【发布时间】:2019-08-18 14:31:39
【问题描述】:

我创建了一个导航,它推送一个视图控制器,其中包含一个图像视图和一个按钮,每次点击按钮时都会添加相同的视图控制器。每次点击后,内存都会增长,每次返回后,尽管调用了deinit,但内存不会被释放。代码中没有任何内容指向内存泄漏是我遗漏了什么吗?谢谢?

complete project repository

class ViewController: UIViewController {


     lazy var nextButton:UIButton? = {
        let button = UIButton(type: .roundedRect)
        button.setTitle("Next", for: .normal)
        button.addTarget(self, action: #selector(nextButtonTapped), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.backgroundColor = UIColor.red
        return button
    }()

     lazy var imageView:UIImageView? = {
        let image = #imageLiteral(resourceName: "DJI_0014")
        let imageView = UIImageView(image: image)
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        guard let imageView = self.imageView, let nextButton = self.nextButton else{
            print("imageView, nextButton are nil")
            return
        }

        self.view.backgroundColor = UIColor.white

        self.view.addSubview(imageView)
        NSLayoutConstraint.activate([
            imageView.topAnchor.constraint(equalTo:self.view.topAnchor),
            imageView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
            imageView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
            imageView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)])

        view.addSubview(nextButton)
        NSLayoutConstraint.activate([nextButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            nextButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 0),nextButton.heightAnchor.constraint(equalToConstant: 200),nextButton.widthAnchor.constraint(equalToConstant: 200)])
    }

    @objc func nextButtonTapped(){
        print("next button tapped")
        self.navigationController?.pushViewController(ViewController(), animated: true)
    }

    deinit {
        print("view controller is deinitialized")
    }

}

我查看了下面列出的其他问题并尝试采纳他们的建议,但似乎都没有帮助

Navigation arc memory not released

Memory leak issue in navigation controller

【问题讨论】:

  • 使用真机而不是模拟器运行长时间测试,例如100次push和pop,你会发现它有一个cap memory并且稳定在18M以下(这取决于图像的大小。) .
  • @E.Coms 感谢您花时间运行它并浏览它。我一直在 iPhone X 和 iPhone 6s Plus 上进行所有测试。我也怀疑该图像,因此我在测试中删除了该图像。在连续运行大约 20-30 次推送和 20-30 次连续弹出后,内存似乎在内存调试器中像一座山一样增长,尤其是在第一次弹出后出现峰值。探查器中报告了泄漏,但我读过这些可能会产生误导,并且我查看了内存图但没有发现任何有用的信息,这是一个非常奇怪的现象。
  • 我相信你的项目中有更多的代码和资源。这是一种正常情况,因为它将由系统处理,例如缓存和动画优化。这里提供的代码应该没问题。如果没有其他错误和泄漏,它将在 40-50M 左右达到峰值。除非有任何泄漏,否则您可能会忽略。也可以考虑及时popToRoot。不断推送这么多 vcs 是一种罕见的情况。也许10层就足够大了。您可以更改 VC 的内容,而不是 vc 它自己。
  • @E.Coms 我添加了一个指向完整项目存储库的链接,以便您自己查看github.com/TheRedCamaro30/Leaky-Navigation-Controller。我没有理由想到为什么当用户从 ViewController 滑出时,在内存被释放的情况下,视图的行为不应该像预期的那样。从理论上讲,只要负责任地处理解除分配,用户就应该能够向导航控制器添加大量视图。
  • 如我所说,如果隐藏导航栏并关闭所有动画。最大内存22M左右,加起来100层+没问题。如果您打开动画并且导航栏显示带有后退按钮,则最大值应为 35M。峰值的原因是为动画控制器和相关节省了一些空间。有一次这样的跳跃,再也不会发生了。

标签: swift xcode memory-leaks uinavigationcontroller automatic-ref-counting


【解决方案1】:

最后,我发现了问题所在,这个问题来自于导航栏:

navigationController?.setNavigationBarHidden(true, animated: false)

此代码将消除大内存残留的所有问题。代码的其他部分很好。在这种情况下,所有内存将一直保持在 19M 左右。

我尝试使用navigationDelegate进行过渡,发现系统忽略了一个崩溃,并表示如果重复push vc会使NavigationBar布局不好。所以我把它隐藏起来,问题就消失了。但是如果你确实需要导航栏或者它的动画,这里会有很多工作要做。

但是内存问题已经找到了。

【讨论】:

  • 非常感谢您的帮助!我们注意到,当条形图和动画被移除时,内存将减少到它开始的位置。当只是为推送和弹出添加动画时,内存的下降幅度几乎没有上升的幅度那么大。你认为这是一个应该向苹果提交的错误吗?
  • 我不知道。
  • 我也有点难过。我想知道这是否与 collectionview 相关,stackoverflow.com/questions/55349341/…
猜你喜欢
  • 2012-02-29
  • 1970-01-01
  • 2023-03-08
  • 2012-06-08
  • 2011-09-04
  • 2011-01-27
  • 2021-02-25
  • 2014-08-26
  • 1970-01-01
相关资源
最近更新 更多