【问题标题】:Why is dismissing uinavigationcontroller not releasing view controller memory?为什么解散 uinavigationcontroller 不释放视图控制器内存?
【发布时间】:2017-09-08 04:27:31
【问题描述】:

在现有应用中实现UIDocumentBrowserViewController。这个 vc,在 iOS 11 中是根视图控制器,点击文件会创建我的文档,实例化我的视图控制器,并将其呈现在 UINavigationController 中。一切正常,文件显示,正确的文档打开,vc 显示并按预期工作。我必须在导航栏上添加一个左按钮以提供关闭 doc/vc 的方法。

当我点击“完成”按钮时,视图控制器关闭并返回到文档浏览器。这一切都很好。

问题是视图控制器的内存没有释放(以及文档内存的多米诺骨牌效应等然后没有释放)。在 iOS 10 方面,UICollectionViewController 嵌入在 UINavigationController 作为初始 vc,但 doc 和显示 vc 的代码与 iOS 10 和 11 相同,所有内存释放。我研究了How to correctly dismiss a UINavigationController that's presented as a modal? 和相关帖子,尝试了几十种替代方法,只是没有看到我缺少的东西。 Instruments 没有显示任何内存泄漏,尽管我在关闭视图控制器后看到内存中的文档对象。日志显示 vc 的 viewWillDisappear 在适当的时间被调用。

感谢任何关于为什么 vc 内存没有被释放(deinit() 未被调用)的见解。

谢谢。

@available(iOS 11.0, *)
class DocumentBrowserViewController: UIDocumentBrowserViewController, UIDocumentBrowserViewControllerDelegate {

override func viewDidLoad() {
    super.viewDidLoad()

    delegate = self

    allowsDocumentCreation = true
    allowsPickingMultipleItems = false
}

// MARK: Document Presentation

func returnToDocumentBrowser(sender: UIBarButtonItem) {
    print("returnToDocumentBrowser")
    if let controller = self.presentedViewController as? UINavigationController {
        controller.dismiss(animated: true, completion: nil)
    }
}

func presentDocument(at documentURL: URL) {
    print("present document")

    let doc = MyDocument(fileURL: documentURL)
    doc.open(completionHandler: { (success) in
        if (success) {
            print("open succeeded")
            DispatchQueue.main.async {
                let myController = self.storyboard!.instantiateViewController(withIdentifier: "my controller") as! MyViewController
                myController.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.returnToDocumentBrowser(sender:))), animated: false)
                myController.doc = doc

                let navigationController = UINavigationController(rootViewController: myController)
                self.present(navigationController, animated: true, completion: nil)
            }
        } else {
            print("open failed")
        }
    })
}
}

【问题讨论】:

  • 也许你的闭包实现中有一个保留周期,尝试在 (success) in 之前使用 [weak self] 并将 self.present 与 optional 一起使用?像这样self?.present(navigationController, animated: true, completion: nil)让我知道
  • 感谢您的建议。它没有改变行为。我也尝试过 [unowned self] be/c 当他们需要与否时,我永远无法保持直截了当……这是一个心理障碍。两者都没有影响。
  • delegate 声明在哪里?弱吗?
  • 当您在 XCode 9 中创建一个基于文档的项目时,您会得到它。该行是为您提供的内容的一部分。我确实从这篇文章中删除了一些委托方法,因为我没有修改它们的默认值。
  • 你能发布这个delegate属性声明吗?

标签: uiviewcontroller uinavigationcontroller uidocument


【解决方案1】:

导航堆栈似乎是其中的核心。在 iOS 10 版本中,集合视图控制器是根视图控制器,并通过故事板嵌入到导航控制器中。

在 iOS 11 版本中,文档浏览器视图控制器是根视图控制器,不能嵌入到导航控制器中。当我在原始代码中展示时,我的文档视图控制器成为导航堆栈的根视图控制器,并且无法弹出。

所以我认为导航控制器可能需要一个不同的根视图控制器来尽可能地模仿先前的行为并且需要最少的代码更改。

所以我改变了

            let navigationController = UINavigationController(rootViewController: myController)
            self.present(navigationController, animated: true, completion: nil)

                    let dummyVC = UIViewController()
                    let navigationController = UINavigationController(rootViewController: dummyVC)
                    from.present(navigationController, animated: true, completion: nil)
                    dummyVC.navigationController?.pushViewController(myController, animated: true)

此导航控制器设置添加了一个后退按钮,这意味着我不必添加后退按钮,它会自动处理弹出视图控制器。结果,我只需要关闭导航控制器,因为它不是应用程序的根 vc。

最后,对于应将委托声明为弱的评论,这是 Apple 所做的,我只是按照提供的方式使用它。我不确定这对事物有什么影响。

【讨论】:

  • 什么是“来自”?我在您的代码中的其他任何地方都没有看到它?
  • 我会告诉你它是从哪里来的,但是我已经有几个月没有看过那个代码了,所以如果不深入研究它就无法解释它或者重新创建思维过程。我用这个方法向我的 UIDocument 子类添加了一个扩展:@available(iOS 11.0, *) func present(from: DocumentBrowserViewController) { 并且该属性是该方法的参数。
  • 没关系,我最终使用了self.present(navigationController, animated: true, completion: nil),这似乎有效。你是如何解散 pushViewController 的?您是否检测到何时按下后退按钮或 viewWillDisappear 然后调用 dummyVC.navigationController?.dismiss(animated: true, completion: nil) 我猜??
  • 与文档关联的视图控制器自动调用其viewWillDisappear 方法,并在其中检查其navigationController 属性和.dismiss。最大的复杂性在于支持 iOS 10.x 和 iOS 11.x+,需要不同文档浏览器机制的并行机制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多