objective-c memory-management objective-c-blocks weak-references ownership

objective c - ¿Cuál es la diferencia entre una referencia__weak y__block?



objective-c memory-management (3)

En el modo de conteo de referencia manual, __block id x; tiene el efecto de no retener x. En el modo ARC, __block id x; se predetermina a retener x (al igual que todos los demás valores). Para obtener el comportamiento del modo de conteo manual de referencia bajo ARC, puede usar __unsafe_unretained __block id x ;. Como el nombre __unsafe_unretained implica, sin embargo, tener una variable no retenida es peligroso (porque puede colgar) y, por lo tanto, se desalienta. Dos mejores opciones son usar __weak (si no necesita soportar iOS 4 u OS X v10.6), o establecer el valor de __block en nil para romper el ciclo de retención.

Apple Docs

Estoy leyendo la documentación de Xcode, y aquí hay algo que me desconcierta:

__block typeof(self) tmpSelf = self; [self methodThatTakesABlock:^ { [tmpSelf doSomething]; }];

Lo siguiente se copia de la documentación:

Un bloque forma una fuerte referencia a las variables que captura. Si usas self en un bloque, el bloque forma una fuerte referencia a self , por lo que si self también tiene una referencia fuerte al bloque (que normalmente lo hace), se obtiene un fuerte ciclo de referencia. Para evitar el ciclo, necesita crear una referencia débil (o __block ) al self fuera del bloque, como en el ejemplo anterior.

No entiendo qué significa "débil" (o " __block ").

Es

__block typeof(self) tmpSelf = self;

y

__weak typeof(self) tmpSelf = self;

exactamente lo mismo aquí?

Encontré otra pieza en el documento:

Nota: En un entorno recolectado de basura, si aplica los modificadores __weak y __block a una variable, entonces el bloque no garantizará que se mantenga activo.

Entonces, estoy totalmente desconcertado.


Además de otras respuestas en __block vs __weak, hay otra manera de evitar retener el ciclo en su escenario.

@weakify(self); [self methodThatTakesABlock:^ { @strongify(self); [self doSomething]; }];

Más información sobre @Weakify @Strongify Marco


De los documentos sobre __block

__ las variables de bloqueo viven en el almacenamiento que se comparte entre el alcance léxico de la variable y todos los bloques y copias de bloques declarados o creados dentro del alcance léxico de la variable. Por lo tanto, el almacenamiento sobrevivirá a la destrucción del marco de pila si cualquier copia de los bloques declarados dentro del marco sobrevive más allá del final del marco (por ejemplo, al ser enrutado en algún lugar para su posterior ejecución). Múltiples bloques en un alcance léxico dado pueden usar simultáneamente una variable compartida.

De los documentos sobre __weak

__weak especifica una referencia que no mantiene vivo el objeto al que se hace referencia. Una referencia débil se establece en cero cuando no hay referencias fuertes al objeto.

Entonces son cosas técnicamente diferentes. __block es para detener la copia de su variable desde su alcance externo en su alcance de bloque. __weak es un puntero débil auto delimitador.

Nota que dije técnicamente, porque para su caso harán (casi) lo mismo. La única diferencia es si está usando ARC o no. Si su proyecto usa ARC y es solo para iOS4.3 y superior, use __weak. Asegura que la referencia se establece en nil si la referencia de alcance global se libera de alguna manera. Si su proyecto no usa ARC o es para versiones anteriores del sistema operativo, use __block.

Aquí hay una sutil diferencia, asegúrese de entenderlo.

EDITAR: Otra pieza del rompecabezas es __unsafe_unretained. Este modificador es casi el mismo que __weak pero para entornos de tiempo de ejecución pre 4.3. SIN EMBARGO, no está configurado en cero y puede dejarlo con punteros colgantes.