ios - libros - tesis sobre youtube pdf
Capturar fuertemente el "yo" en este bloque puede llevar a un ciclo de retenciĆ³n (2)
Esta pregunta ya tiene una respuesta aquí:
He solicitado con el bloque. Pero el compilador emite una advertencia.
"Capturar fuertemente" a sí mismo "en este bloque puede conducir a un ciclo de retención"
__weak typeof(self) weakSelf = self;
[generalInstaImage setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:data[@"images"][@"low_resolution"][@"url"]]] placeholderImage:[UIImage imageNamed:@"Default"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
NSLog(@"success");
[generalInstaImage setImage: image];
[weakSelf saveImage:generalInstaImage.image withName:data[@"id"]];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(@"fail");
}];
Intento con el ejemplo escribir como weakSelf.generalInstaImage
, pero luego el compilador genera un error y no compila.
Considere esta advertencia:
Capturarse fuertemente en este bloque es probable que conduzca a un ciclo de retención
Cuando reciba la advertencia anterior, debe revisar su bloqueo para:
- cualquier referencia explícita a
self
; o - cualquier referencia implícita a
self
causada por hacer referencia a cualquier variable de instancia.
Imaginemos que tenemos una propiedad de clase simple que era un bloque (esto experimentará las mismas advertencias de "ciclo de retención" que su pregunta, pero mantendré mis ejemplos un poco más simples):
@property (nonatomic, copy) void (^block)(void);
Y asumamos que teníamos alguna otra propiedad de clase que queríamos usar dentro de nuestro bloque:
@property (nonatomic, strong) NSString *someString;
Si te refieres a ti self
dentro del bloque (en mi ejemplo a continuación, en proceso de acceder a esta propiedad), obviamente recibirás esa advertencia sobre el riesgo de retención de ciclo:
self.block = ^{
NSLog(@"%@", self.someString);
};
Esto se soluciona mediante el patrón que sugirió, a saber:
__weak typeof(self) weakSelf = self;
self.block = ^{
NSLog(@"%@", weakSelf.someString);
};
Menos obvio, también recibirá la advertencia de "ciclo de retención" si hace referencia a una variable de instancia de la clase dentro del bloque, por ejemplo:
self.block = ^{
NSLog(@"%@", _someString);
};
Esto se debe a que la variable de instancia _someString
lleva una referencia implícita a self
, y en realidad es equivalente a:
self.block = ^{
NSLog(@"%@", self->_someString);
};
También podrías estar inclinado a tratar de adoptar un patrón de autoestima débil, pero no puedes. Si intentas el patrón de sintaxis weakSelf->_someString
, el compilador te advertirá sobre esto:
No se
__weak
desreferenciación de un puntero__weak
debido a un posible valor nulo causado por la condición de carrera, asignarlo primero a la variablestrong
Por lo tanto, resuelve esto utilizando el patrón weakSelf
, pero también crea una variable strong
local dentro del bloque y la usa para eliminar la referencia a la variable de instancia:
__weak typeof(self) weakSelf = self;
self.block = ^{
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"%@", strongSelf->_someString);
// or better, just use the property
//
// NSLog(@"%@", strongSelf.someString);
}
};
Además, esta creación de una referencia strong
local, strongSelf
, dentro del bloque también tiene otras ventajas, a saber, que si el bloque de finalización se ejecuta de forma asíncrona en un subproceso diferente, no tiene que preocuparse por self
autoasignación mientras que El bloque se está ejecutando, lo que resulta en consecuencias no deseadas.
Este patrón weakSelf
/ strongSelf
es muy útil cuando se trata de propiedades de bloque y desea evitar los ciclos de retención (también conocidos como ciclos de referencia fuertes), pero al mismo tiempo garantizar que no se pueda desasignar el self
en medio de la ejecución del bloque de finalización.
Para su información, Apple analiza este patrón en la discusión de "ciclos no triviales" más adelante en la sección Use los Calificadores de vida útil para evitar ciclos de referencia fuertes de Transición a las Notas de la versión ARC.
weakSelf.generalInstaImage
que recibió algún "error" cuando hizo referencia a weakSelf.generalInstaImage
en su ejemplo. Esta es la forma correcta de resolver esta advertencia de "retención del ciclo", por lo que si recibió alguna advertencia, debe compartirla con nosotros, así como mostrarnos cómo declaró la propiedad.
Use __unsafe_unretained typeof(self) weakSelf = self