Estoy un poco confundido sobre el uso de bloques en Objective-C. Actualmente uso ARC y tengo bastantes bloques en mi aplicación, actualmente siempre me refiero en selflugar de su referencia débil. ¿Puede ser esa la causa de que estos bloques selfretengan y eviten que sean desalojados? La pregunta es, ¿debería usar siempre una weakreferencia de selfen un bloque?
-(void)handleNewerData:(NSArray *)arr
{
ProcessOperation *operation =
[[ProcessOperation alloc] initWithDataToProcess:arr
completion:^(NSMutableArray *rows) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateFeed:arr rows:rows];
});
}];
[dataProcessQueue addOperation:operation];
}
ProcessOperation.h
@interface ProcessOperation : NSOperation
{
NSMutableArray *dataArr;
NSMutableArray *rowHeightsArr;
void (^callback)(NSMutableArray *rows);
}
ProcessOperation.m
-(id)initWithDataToProcess:(NSArray *)data completion:(void (^)(NSMutableArray *rows))cb{
if(self =[super init]){
dataArr = [NSMutableArray arrayWithArray:data];
rowHeightsArr = [NSMutableArray new];
callback = cb;
}
return self;
}
- (void)main {
@autoreleasepool {
...
callback(rowHeightsArr);
}
}
ios
iphone
objective-c
automatic-ref-counting
weak-references
el crítico
fuente
fuente

Respuestas:
Ayuda a no centrarse en parte
strongoweaken la discusión. En cambio, concéntrate en la parte del ciclo .Un ciclo de retención es un ciclo que ocurre cuando el Objeto A retiene el Objeto B, y el Objeto B retiene el Objeto A. En esa situación, si cualquiera de los objetos se libera:
Por lo tanto, esos dos objetos permanecerán en la memoria durante toda la vida del programa, aunque deberían, si todo funcionara correctamente, ser desasignado.
Entonces, lo que nos preocupa es retener ciclos , y no hay nada sobre los bloques en sí mismos que crean estos ciclos. Esto no es un problema, por ejemplo:
El bloque retiene
self, peroselfno retiene el bloque. Si se libera uno u otro, no se crea ningún ciclo y todo se desasigna como debería.Donde te metes en problemas es algo como:
Ahora, su objeto (
self) tiene unastrongreferencia explícita al bloque. Y el bloque tiene una fuerte referencia implícita aself. Eso es un ciclo, y ahora ninguno de los objetos se desasignará correctamente.Porque, en una situación como esta,
selfpor definición ya tiene unastrongreferencia al bloque, generalmente es más fácil de resolver haciendo una referencia explícitamente débilselfpara que el bloque use:¡Pero este no debería ser el patrón predeterminado que sigues cuando trates con bloques que llaman
self! Esto solo debe usarse para romper lo que de otro modo sería un ciclo de retención entre uno mismo y el bloque. Si adoptara este patrón en todas partes, correría el riesgo de pasar un bloque a algo que se ejecutó después de queselffue desasignado.fuente
-setCompleteionBlockWithSuccess:failure:método. Pero sipaginatores propiedad de ellosViewController, y estos bloques no se llaman despuésViewController, se liberaría, usar una__weakreferencia sería el movimiento seguro (porqueselfposee lo que posee los bloques, por lo que es probable que siga existiendo cuando los bloques lo llamen a pesar de que no lo retienen). Pero eso es un montón de "si". Realmente depende de lo que se supone que debe hacer.MyObjectySomeOtherObjectambos son dueños del bloque. Pero debido a que la referencia del bloque vuelve aMyObjectserweak, el bloque no es el propietarioMyObject. Así, mientras que el bloque se garantiza que existirá mientras seaMyObjectoSomeOtherObjectexiste, no hay garantía de queMyObjectexistirá siempre y cuando el bloque hace.MyObjectpuede ser completamente desasignado y, mientrasSomeOtherObjectexista, el bloque seguirá allí.No tiene que usar siempre una referencia débil. Si su bloqueo no se retiene, sino que se ejecuta y luego se descarta, puede capturarse con fuerza, ya que no creará un ciclo de retención. En algunos casos, incluso desea que el bloque se retenga hasta que se complete el bloque para que no se desasigne prematuramente. Sin embargo, si captura el bloque con fuerza, y dentro de sí mismo, creará un ciclo de retención.
fuente
Estoy totalmente de acuerdo con @jemmons:
Para superar este problema, se puede definir una referencia fuerte sobre el
weakSelfinterior del bloque:fuente
->), donde desea garantizar que realmente obtuvo una referencia válida y mantenerla continuamente en todo el conjunto de operaciones, por ejemploif ( strongSelf ) { /* several operations */ }Como Leo señala, el código que agregó a su pregunta no sugeriría un ciclo de referencia fuerte (también conocido como ciclo de retención). Un problema relacionado con la operación que podría causar un fuerte ciclo de referencia sería si la operación no se libera. Si bien su fragmento de código sugiere que no ha definido su operación como concurrente, pero si lo ha hecho, no se publicará si nunca publicó
isFinished, o si tuvo dependencias circulares, o algo así. Y si la operación no se lanza, el controlador de vista tampoco se lanzaría. Sugeriría agregar un punto de interrupción oNSLogen eldeallocmétodo de su operación y confirmar que se llama.Tu dijiste:
Los problemas del ciclo de retención (ciclo de referencia fuerte) que ocurren con los bloques son como los problemas del ciclo de retención con los que está familiarizado. Un bloque mantendrá referencias fuertes a cualquier objeto que aparezca dentro del bloque, y no liberará esas referencias fuertes hasta que se libere el bloque mismo. Por lo tanto, si las referencias de bloque
self, o incluso solo hace referencia a una variable de instancia deself, que mantendrá una fuerte referencia a sí mismo, eso no se resolverá hasta que se libere el bloque (o en este caso, hasta queNSOperationse libere la subclase.Para obtener más información, consulte la sección Evitar ciclos de referencia fuertes al capturar uno mismo del documento Programación con Objective-C: Trabajar con bloques .
Si su controlador de vista aún no se está lanzando, simplemente tiene que identificar dónde reside la referencia fuerte no resuelta (suponiendo que confirmó que
NSOperationse está desasignando). Un ejemplo común es el uso de una repeticiónNSTimer. O algúndelegateobjeto personalizado u otro que mantiene erróneamente unastrongreferencia. A menudo puede usar instrumentos para rastrear dónde los objetos obtienen sus referencias fuertes, por ejemplo:O en Xcode 5:
fuente
Algunas explicaciones ignoran una condición sobre el ciclo de retención [Si un grupo de objetos está conectado por un círculo de relaciones fuertes, se mantienen vivos incluso si no hay referencias fuertes desde fuera del grupo.] Para obtener más información, lea el documento
fuente
Así es como puedes usar el self dentro del bloque:
// llamada del bloque
fuente