¿Las llamadas de método multiple presentViewController a través de los controlleres de vista conducen a la pérdida de memory en iOS?

Sé que ha habido muchas discusiones relacionadas con este tema. Pero en todas las discusiones, todos se han discutido con 2 controlleres de vista (A y B). Mi escenario es similar pero diferente.

Lo que sucederá cuando haya múltiples controlleres de vista como A, B, C, D. Entonces, el flujo de presentación se mueve como,

El controller de vista A (Inicio) presenta el controller de vista B (Lista). Luego, desde el controller de vista B se muestra el controller de vista C (Detalles). Luego, desde el controller de vista C se muestra el controller de vista D (Detalles avanzados). Luego, desde View Controller D, se muestra View Controller A, para navegar directamente a Home !!!

¿Cuál es la mejor práctica para eso?

Al no conocer la estructura de su proyecto y los detalles de cómo mostrará A, B, C, D, E, F y luego de F a A, tomaría una conjetura salvaje y diría que puede conducir a una pérdida de memory dependiendo de patrones de layout que empleas a tus UIViewControllers. Como lo comentó @CaptJak en sus preguntas, es difícil saber si, cómo y cuándo provocará una pérdida de memory, especialmente si usa un patrón de delegación para pasar datos alnetworkingedor de los controlleres de vista.

Personalmente, cuando realizo flujos complicados como presentar múltiples UIViewControllers y me encuentro con la necesidad de retroceder unas pocas pantallas, no popearé las vistas en la stack hasta que la que yo quiera esté en la parte superior de la stack (si estás usando la navigation controller), desestime el controller de vista si se presenta de manera modal, o desenrolle segues si los uso. El riesgo aquí puede ser la memory del controller de vista puede haber desasignado.

Habría comentado pero no tengo suficiente reputación. Tome mi respuesta con un poco de sal, ya que soy bastante nuevo en el desarrollo de iOS.

EDIT: Gracias por los detalles proporcionados en el flujo de su aplicación. Como podría usar presentViewController, estoy asumiendo que se está ejecutando en un NavigationController. Si ese es el caso, utilizaría popToViewController o popToRootViewController (si A es su controller de vista raíz) para este caso en lugar de presentar A de D nuevamente. Si A se presenta de D otra vez, supongo que tendrá 2 instancias de A en su stack de VC, lo que puede provocar una pérdida de memory.

Método PopToViewController

 NSArray arrayOfVCs = self.navigationController.viewControllers; for(UIViewController *currentVC in arrayOfVCs) { if([currentVC isKindOfClass:[ViewControllerA class]) { [self.navigation.controller popToViewController:currentVC animated:YES] } } 

Método PopToRootViewController (suponiendo que A es su vista raíz en el controller de navigation)

 [self.navigationController popToRootViewControllerAnimated:YES] 

EDITAR 12 de abril de 2016

Acabo de estar pensando en esta cuestión tanto que realmente hice un breve informe sobre ella y solo quiero compartir mis hallazgos aquí. Hice una simple y sucia function para get una stack de todos los controlleres de vista modal presentados en mi aplicación muy simple.

Probé desde A -> B -> C-> B -> C -> B aproximadamente 20 – 30 veces. Cada vez que paso el time B -> C, la memory aumentó en 0.5MB (porque mis pantallas son simples pero las suyas pueden ser diferentes) y terminé aumentando de 20+ MB a 50+ MB.

En esta function, grabé el número de controlleres de vista presentados en la stack y también sus nombres en una matriz. Hasta ahora, funcionó para mí, pero puedes probarlo y ver si te funciona.

 //global variables var vccount = 0 var vcnamelist = [String]() func getPresentingViewStackCount(currentVC : UIViewController!){ if(currentVC.presentingViewController != nil){ vccount = vccount + 1 let vc = currentVC.presentingViewController vcnamelist.append(NSStringFromClass((vc?.classForCoder)!)) getPresentingViewStackCount(vc) } } // to use func someRandomMethod(){ getPresentingViewStackCount(self) } 

Aún así, creo que es mejor usar controlleres de navigation. Es para lo que están diseñados. 🙂

1. Si presenta así, A-> B-> C-> D-> A, uno por uno, uno encima del otro, obtendrá una exception:

La aplicación intentó presentar modalmente un controller activo

No puede presentar un ViewController que ya se haya presentado, al igual que no puede presionar un ViewController que ya está en la stack UINavigationController.

2. Si usó Storyboard para build su aplicación, puede usar unwind-segue para volver a A desde D.

3.Si usó el código para build su aplicación, puede mantener una reference débil de A en D y llamar

 [A dismissViewControllerAnimated:YES completion:nil]; 

en ViewController D como dismissViewControllerAnimated permite volver a A.

– (void) dismissViewControllerAnimated: finalización del indicador (BOOL): (vacío (^ __nulable) (vacío)) finalización;
Si presenta varios controlleres de vista en sucesión, creando así una stack de controlleres de vista presentados, llamar a este método en un controller de vista más bajo en la stack descarta su controller de vista secundario inmediato y todos los controlleres de vista por encima de ese elemento secundario en la stack. Cuando esto sucede, solo la vista superior se descarta de manera animada; cualquier controller de vista intermedia simplemente se elimina de la stack. La vista superior se descarta utilizando su estilo de transición modal, que puede diferir de los styles utilizados por otros controlleres de vista más bajos en la stack.

Creo que es posible mandar + arrastrar desde un button UIB (o cualquier otra cosa que esté utilizando para controlar su flujo) al controller de vista que quiera presentar a continuación, para navegar correctamente. Luego, suelte y select el método de presentación que desee, y cuando lo pruebe, debería funcionar. Estoy asumiendo que usa XCode para esto, y no estoy seguro de otras aplicaciones de desarrollo.

Esto está diseñado para evitar que se produzca una pérdida de memory, pero tenga en count que tendrá que crear files separados para cada controller de vista por separado. Otras forms manuales de cambio pueden provocar pérdidas de memory, según el contenido de su situación.

Nada malo si va a mostrar el controller de vista A recién creado .