Evitar la retención circular usando ARC (fuerte / débil), aprender algunos conceptos básicos

Todavía no me he encontrado con un problema, pero estoy tratando de asegurarme de que estoy usando algunas buenas prácticas.

Supongamos que tengo un UITableViewController con una fuente de datos de un NSArray de objects MyObject. Entonces, en mi UITableViewController declaro mi fuente de datos como:

@property (strong, nonatomic) NSArray *dataSource; 

Luego, después de tocar una celda, quiero presionar una nueva vista que muestre una vista de detalle de algo, utilizando MyObject de esa celda. Entonces en el nuevo UIViewController tengo esto:

 @property (strong, nonatomic) MyObject *myObject; 

Ahora en el UITableViewController cuando se toca una celda:

 MyObject *myObject = [[self dataSource] objectForIndex:[indexPath row]]; NewView *view = [[NewView alloc] initWithMyObject:myObject]; // ... push onto nav controller, etc 

Básicamente, lo que temo es que mi matriz se declara con fuerte , MyObject en la vista detallada se declara con fuerte y quién sabe que quizás haya otra vista con el mismo MyObject declarado con fuerte .

En pocas palabras: ¿es esta la forma correcta de pasar un object entre vistas? Realmente no he usado una reference débil en mis aplicaciones y siento que no está bien. Cualquier ayuda o enlace para ayudar sería increíble.

Creo que lo que necesitas entender es cómo funciona el arco.

Básicamente, lo que sea que tenga un puntero fuerte que lo señale, será retenido.

Esto funciona al agregar un contador de reference en el object para que cuando hagas esto:

 @property (strong, nonatomic) MyObject *myObject; 

usted crea un puntero FUERTE para myObject, (no el object).

pero cuando haces esto

 MyObject *myObject = [[self dataSource] objectForIndex:[indexPath row]]; 

haga que este puntero aumente la reference contando lo que tenga en el índice especificado de esa fuente de datos.

La parte importante es que mientras el puntero siga apuntando a este object, se mantendrá con vida.

Sobre su preocupación con las vistas.

Las vistas creadas en el generador de interfaces tienen sus elementos declarados internamente con pointers fuertes. Esto es cuando quiere usar una reference débil . Cuando agrega su propio IBOutlet a un elemento en la vista, es una buena práctica hacerlo débil. Si piensas lógicamente en el motivo, básicamente significa que no te importa este elemento de creación de interfaz ya que solo quieres que sobreviva hasta que se desasigne el viewcontroller.

Cuando por lo general se encuentra con los ciclos de retención es cuando un object tiene un object secundario y este object secundario tiene una reference FUERTES a su elemento primario.

esto es:

El object A crea el object B con un puntero fuerte

El object B apunta al object A con un puntero fuerte

A mantendrá a B vivo y B mantendrá a A con vida.

Esta página le explicará algunas cosas básicas sobre cómo evitar este tipo de cosas:

http://cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html

También sobre pasar objects entre vistas, es muy simple.

Primero obtenga un puntero desde la Vista 1 hasta la Vista 2 (puede ser fuerte o débil dependiendo de quién debería mantener viva la vista 2, si es del IB Builder, debería ser débil si su progtwig debería ser fuerte)

En segundo lugar, cree una propiedad en la vista 2 (@property (fuerte, no atómica) MyObject * myObject;)

ahora es tan simple como:

 Self.view1Pointer.myObject = self.myOtherObject; 

Entienda aquí cómo ambas vistas apuntan fuertemente a este object para que el object se mantenga con vida, siempre y cuando 1 de las vistas no haya sido desasignado.

No creará un ciclo de retención, simplemente tendrá el recuento de reference de ese object establecido en 2.

Nota: cuando una vista se desasigna, todos sus pointers se configuran como nil, por lo que cualquier object apuntado por ellos disminuirá en su recuento de references. SI alcanza 0, se desasigna. (en el caso anterior miobject será 1 porque otra vista aún está apuntando hacia él).

El único escenario en el que creará un ciclo de retención es si se las arregla para hacer que myObject apunte a View2 también. Entonces ahora se mantienen vivos el uno al otro. (pero, como se explicó antes, puede hacer que myObject apunte a view2 de manera débil, lo que no creará un ciclo de retención).

Puede get más información sobre el arco aquí:

http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1

No es un ciclo de retención. Es una buena manera de hacer las cosas. La instancia de MyObject no hace reference a ninguno de sus propietarios, por lo que cuando finalmente se MyObject el último de esos propietarios, también lo hará el object.