为什么解雇uinavigationcontroller而不释放视图控制器内存?

时间:2017-09-08 04:27:32

标签: uiviewcontroller uinavigationcontroller uidocument

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

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

问题是视图控制器的内存没有释放(文件内存的多米诺骨牌效应等因此没有释放)。在iOS 10方面,UICollectionViewController嵌入UINavigationController作为初始vc,但doc和display vc相同的代码适用于iOS 10& 11,所有内存释放。我研究了How to correctly dismiss a UINavigationController that's presented as a modal?和相关的帖子,尝试了几十种替代品,我只是没有看到我所缺少的东西。仪器没有显示任何内存泄漏,但我在解除视图控制器后看到内存中的文档对象。日志显示正在调用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")
        }
    })
}
}

1 个答案:

答案 0 :(得分:0)

导航堆栈似乎是其中的核心。在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)

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

最后,对于代表应该被宣布为弱的评论,这是Apple正在做的,我只是按照提供的方式使用它。我不确定这会对事情产生什么影响。