Estoy navegando por el maravilloso blog mantenido por Scott Stevenson, y estoy tratando de entender un concepto fundamental del Objetivo-C de asignar a los delegados la propiedad 'asignar' frente a 'retener'. Tenga en cuenta que ambos son iguales en un entorno de recolección de basura. Me preocupa principalmente un entorno no basado en GC (por ejemplo: iPhone).
Directamente desde el blog de Scott:
"La palabra clave de asignación generará un setter que asigna el valor a la variable de instancia directamente, en lugar de copiarlo o retenerlo. Esto es mejor para tipos primitivos como NSInteger y CGFloat, u objetos que no son directamente suyos, como los delegados".
¿Qué significa que no posee directamente el objeto delegado? Normalmente retengo a mis delegados, porque si no quiero que se vayan al abismo, retener se encargará de eso por mí. Por lo general, abstraigo UITableViewController lejos de su respectiva fuente de datos y delego también. También conservo ese objeto en particular. Quiero asegurarme de que nunca desaparezca para que mi UITableView siempre tenga su delegado.
¿Alguien más puede explicar dónde / por qué estoy equivocado, para poder entender este paradigma común en la programación de Objective-C 2.0 de usar la propiedad de asignación en los delegados en lugar de retener?
¡Gracias!
fuente
Respuestas:
La razón por la que evita retener delegados es que debe evitar un ciclo de retención:
A crea B A se establece como delegado de B ... A es liberado por su propietario
Si B hubiera retenido a A, A no se liberaría, ya que B es dueño de A, por lo tanto, el dealloc de A nunca se llamaría, lo que haría que A y B fugas.
No debe preocuparse de que A desaparezca porque posee B y, por lo tanto, se deshace de él en dealloc.
fuente
weak
hace? La pregunta es ¿por qué usar enassign
lugar deweak
?assign
lugar deretain
. La pregunta es más antigua que ARC;weak
ystrong
(este último es sinónimo deretain
) no existió hasta que se introdujo ARC. Debe hacer su pregunta sobreweak
vs. porassign
separado.Porque el objeto que envía los mensajes del delegado no es el propietario del delegado.
Muchas veces, es al revés, como cuando un controlador se establece a sí mismo como el delegado de una vista o ventana: el controlador posee la vista / ventana, por lo que si la vista / ventana fuera su delegado, ambos objetos se poseerían entre sí. Esto, por supuesto, es un ciclo de retención, similar a una fuga con la misma consecuencia (los objetos que deberían estar muertos permanecen vivos).
Otras veces, los objetos son iguales: ninguno de los dos posee el otro, probablemente porque ambos son propiedad del mismo tercer objeto.
De cualquier manera, el objeto con el delegado no debe retener a su delegado.
(Hay al menos una excepción, por cierto. No recuerdo qué fue, y no creo que haya una buena razón para ello).
Anexo (agregado 2012-05-19): bajo ARC, debe usar en
weak
lugar deassign
. Las referencias débiles se configurannil
automáticamente cuando el objeto muere, eliminando la posibilidad de que el objeto delegante termine enviando mensajes al delegado muerto.Si se mantiene alejado de ARC por alguna razón, al menos cambie las
assign
propiedades que apuntan a objetosunsafe_unretained
, lo que hace explícito que se trata de una referencia no retenida pero no cero a un objeto.assign
sigue siendo apropiado para valores que no sean de objeto tanto en ARC como en MRC.fuente
NSURLConnection
retiene a su delegado.weak
, pero eso no responde a la pregunta original: ¿Por qué Apple usa enassign
lugar deweak
?assign
lugar de retenerlas ?weak
no existía cuando se le preguntó. Su pregunta es diferente, que debe hacer por separado. Estaré encantado de responderlo.Tenga en cuenta que cuando tiene un delegado asignado, hace que sea muy importante establecer ese valor de delegado en nulo siempre que el objeto se desasigne, por lo que un objeto siempre debe tener cuidado de anular las referencias de delegado en dealloc si no lo ha hecho. hecho así en otra parte.
fuente
Una de las razones detrás de eso es para evitar retener ciclos. Solo para evitar el escenario en el que ambos objetos A y B se refieren entre sí y ninguno de ellos se libera de la memoria.
Asignar de forma aguda es mejor para tipos primitivos como NSInteger y CGFloat, u objetos que no son de su propiedad, como los delegados.
fuente