Estoy escribiendo una API que implica el manejo de eventos, y me gustaría poder usar bloques para los manejadores. Las devoluciones de llamada a menudo querrán acceder o modificarse. En el modo ARC, Clang advierte que los bloques que hacen referencia a uno mismo probablemente creen un ciclo de retención, lo que parece una advertencia útil que quiero mantener en general.Desactivar de manera compacta la advertencia de arc-retain-cycles para bloques que se auto referencian
Sin embargo, para esta parte de mi API, el ciclo de vida de la devolución de llamada y el objeto que contiene se mantienen de forma externa. Sé que puedo romper el ciclo cuando el objeto debe ser desasignado.
Puedo desactivar la advertencia de retener ciclo por archivo con #pragma clang diagnostic ignored "-Warc-retain-cycles"
, pero eso desactiva la advertencia para todo el archivo. Puedo rodear los bloques con #pragma clang diagnostic push
y pop
alrededor de esa advertencia, pero eso hace que los bloques sean feos.
También puedo obtener la advertencia de que se va al hacer referencia a una variable __weak que apunta a self en lugar de hacer referencia directamente a self, pero eso hace que los bloques sean menos agradables de usar.
La mejor solución que he llegado con esta macro es que hace el diagnóstico de discapacidad en todo el bloque:
#define OBSERVE(OBJ, OBSERVEE, PATH, CODE) \
[(OBJ) observeObject:(OBSERVEE) forKeyPath:(PATH) withBlock:^(id obj, NSDictionary *change) { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-retain-cycles\"") \
do { CODE; } while(0); \
_Pragma("clang diagnostic pop") \
}];
que funciona, pero no es muy visible para los usuarios de la API, que no permite anidada observadores, e interactúa mal con el editor de XCode. ¿Hay una mejor manera de desactivar o evitar la advertencia?
Crear una referencia '__weak' a' self' toma literalmente una línea de código. Creo que solucionar el problema en este caso es mejor que tratar de aliviar los síntomas. ¿Cómo se hace referencia a 'weakSelf' en lugar de' self' haciendo que el bloque sea menos agradable de usar? –
Es menos agradable de dos maneras. Los oyentes a menudo son bastante cortos, a veces una sola declaración. La declaración __weak dobla el tamaño del oyente. También significa que necesita calificar los accesos a la propiedad en lugar de usar un yo inferido. Estoy de acuerdo en que mi solución actual es probablemente peor que solo usar __weak, pero esperaba obtener una mejor a través de esta pregunta. –
¿Puedes cambiar el prototipo de tu bloque de finalización para aceptar un argumento "propio"? Ahora el código donde pasa sus bloques se verá igual (excepto para aceptar un argumento adicional) y puede eliminar las advertencias. (es decir, hacer que su API pase el objeto en cuestión a su bloque) – nielsbot