Swift evitando ciclos de retención con child viewControllers y uso de singletons
He estado utilizando singletons en exceso y esto ha resultado en fugas de memoria y algunos problemas para gestionar estados. Estoy tratando de entender las alternativas adecuadas al uso de singletons y la inyección de dependencias en general, es decir, los protocolos.
El ejemplo con el que estoy tratando es que MainViewController tiene un paginador que muestra respectivamente ViewControllerA y ViewControllerB. MainViewController tiene un selector que determina el tipo de contenido de ViewControllerA/ViewControllerB. Básicamente, cuando se selecciona un tipo de contenido diferente, necesito recargar los datos del ViewController hijo mostrado. Estoy tratando de averiguar cómo llamar correctamente a reloadData con el ContentType seleccionado en el ViewController hijo. Si creo instancias de los ViewController hijos a nivel de clase y hago algo como esto:
class MainVC: UIViewController {
...
@objc func contentSelectorTapped() {
...
reloadDisplayedChild(prodTypeForIndex(i))
}
func reloadDisplayedChild(_ prodType: ProductType) {
switch currentPage {
case .pageA
pageA.reloadData(prodType)
case .pageB
pageB.reloadData(prodType)
}
}
}
...
class PageAViewController: UIViewController {
...
func reloadData(_ prodType: ProductType) {
...
//Normalmente llamaría a un singleton de capa de datos que creé, pero estoy tratando de alejarme de este enfoque
}
}
Me preocupa que esté creando un ciclo de retención y siento que habrá una gran cantidad de sobrecarga. Y si esto está bien, ¿cómo debo declarar mis instancias de los ViewController hijos para que no creen un ciclo de retención?
lazy var pageAVC: UIPageAViewController = {
let page = UIPageAVC()
page.delegate = self
...
return page
}()
Siento que conceptualmente entiendo cómo evitar los ciclos de retención, pero estoy teniendo dificultades para implementarlo realmente y mantener alguna estructura arquitectónica (en mi caso, MVP).
davy.ai
Para evitar el uso de singletons y mejorar la inyección de dependencias, puedes utilizar protocolos en su lugar. En tu ejemplo, puedes crear un protocolo al cual los controladores de vista secundarios deben conformarse e implementar el método
reloadData
.Luego, puedes hacer que las clases
ViewControllerA
yViewControllerB
se adhieran a este protocolo.En tu
MainViewController
, declara los controladores de vista secundarios como instancias del tipo del protocolo.Al declarar los controladores de vista secundarios como instancias del tipo del protocolo, no estás creando un ciclo de retención. El protocolo actúa como un contrato y las instancias de los controladores de vista secundarios solo necesitan conformarse al protocolo para poder ser utilizadas en
MainViewController
. Esto también permite una prueba y modularidad más fácil en tu código.