2017-09-08 3 views
0

Implémentation de UIDocumentBrowserViewController dans une application existante. Ce vc, dans iOS 11 est le contrôleur de vue racine, et en tapant un fichier crée mon document, instancie mon contrôleur de vue, et le présente dans un UINavigationController. Tout fonctionne, en ce que les fichiers s'affichent, le document approprié s'ouvre, le vc affiche et fonctionne comme prévu. J'ai dû ajouter un bouton gauche à la barre de navigation pour fournir un moyen de fermer le doc/vc.Pourquoi est-ce que le fait de rejeter uinavigationcontroller ne libère pas la mémoire du contrôleur de vue?

Lorsque j'appuie sur le bouton "Terminé", le contrôleur de vue se ferme et retourne au navigateur de documents. Tout cela est bien.

Le problème est que la mémoire du contrôleur de vue ne se libère pas (et l'effet domino de la mémoire de document, etc. ne se libère pas). Dans le côté iOS 10 des choses, avec un UICollectionViewController intégré dans un UINavigationController comme le vc initial, mais le doc et l'affichage vc code identique pour iOS 10 & 11, toutes les versions de mémoire. J'ai étudié How to correctly dismiss a UINavigationController that's presented as a modal? et les postes connexes, essayé des dizaines d'alternatives, et je ne vois pas ce qui me manque. Instruments ne montre aucune fuite de mémoire, bien que je vois des objets de document dans la mémoire après avoir rejeté le contrôleur de vue. Le journal montre que le viewWillDisappear du vc est appelé au bon moment.

J'apprécie toute idée de la raison pour laquelle la mémoire vc n'est pas libérée (deinit() n'étant pas appelée).

Merci.

@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") 
     } 
    }) 
} 
} 
+0

peut-être que vous avez un cycle de rétention dans votre implémentation de fermeture, essayez d'utiliser '[weak self]' avant '(succès) in et utilisez self.present avec optionnel? comme ceci 'self? .present (navigationController, animé: true, complétion: nil)' faites moi signe –

+0

Merci pour la suggestion. Cela n'a pas changé le comportement. J'ai aussi essayé [être soi-même] être/je ne peux jamais rester droit quand on en a besoin ou pas ... c'est un blocage mental. Aucun effet de l'un ou l'autre. – JKaz

+0

où est la déclaration 'delegate'? est faible? –

Répondre

0

La pile de navigation semble être au cœur de tout cela. Dans la version iOS 10, un contrôleur de vue de collection est le contrôleur de vue racine et est intégré dans un contrôleur de navigation via le storyboard.

Dans la version iOS 11, le contrôleur de vue de navigateur de document est le contrôleur de vue racine et ne peut pas être intégré dans un contrôleur de navigation. Lorsque j'ai présenté dans le code d'origine, mon contrôleur de vue de document est devenu le contrôleur de vue racine de la pile de navigation, et cela ne peut pas être déclenché, par exemple. J'ai donc pensé que peut-être le contrôleur de navigation avait besoin d'un contrôleur de vue racine différent pour imiter le comportement antérieur autant que possible et exiger le moins de changements de code.

Je changé

  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) 

Cette configuration du contrôleur de navigation a ajouté un bouton de retour, ce qui signifie que je ne devais pas ajouter un bouton de retour, et ceux qui manient sauter le contrôleur de vue automatiquement. En conséquence, j'ai seulement besoin de rejeter le contrôleur de nav, car ce n'était pas la racine de l'application vc. Enfin, pour le commentaire que le délégué devrait être déclaré faible, c'est ce que fait Apple, et je l'utilise comme prévu. Je ne suis pas sûr de l'effet que cela a sur les choses.