objective c - rio - ¿Qué significa esta advertencia de síntesis de propiedades objetivo-c?
rio ganges india (2)
Desde la actualización a Xcode 5.1, estoy empezando a ver la siguiente advertencia en algún código que usa mi proyecto. Estoy tratando de averiguar lo que significa.
Advertencia: la Auto property synthesis will not synthesize property ''responseHeader'' because it is ''readwrite'' but it will be synthesized ''readonly'' via another property
El código donde está ocurriendo, en el archivo .m:
@interface S3Response ()
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
@end
La declaración previa de la propiedad, en el archivo .h:
@property (nonatomic, readonly) NSDictionary *responseHeader;
No hay @synthesize
instrucción @synthesize
para esa propiedad, ni responseHeader
o setResponseHeader
definidos como métodos. Sin embargo, existe una definición explícita de un ivar llamado responseHeader
.
Me parece bastante sencillo: la propiedad está declarada como de solo lectura para los usuarios de la clase, pero de lectura y escritura localmente para que la clase la pueda configurar.
¿Qué significa esta advertencia y qué debo hacer al respecto?
El problema aquí es el siguiente.
De forma predeterminada, si no se escribe la propiedad (débil / retener / fuerte / asignar) explícitamente, xCode verificará el tipo automáticamente. Así que en el caso de NSDictionary será fuerte . Así, en la interfaz tendrás
@property (nonatomic, readonly, strong) NSDictionary *responseHeader;
Entonces se te contradecirá la definición de tu implementación privada.
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
El compilador no coincide fuerte y retiene bajo la síntesis de propiedades, aunque formalmente es la misma cosa.
Para solucionar el problema, puede escribir retener en ambos casos, o más correcto, no debe escribir retener en absoluto. Será fuerte por defecto en ambas definiciones.
Ese código parece ser del AWS SDK para iOS , y S3Response
es una subclase de AmazonServiceResponse
.
La interfaz pública de AmazonServiceResponse
define una propiedad de solo lectura
@interface AmazonServiceResponse:NSObject
// ...
@property (nonatomic, readonly) NSDictionary *responseHeader;
@end
que se redefine como lectura-escritura en una extensión de clase en el archivo de implementación:
@interface AmazonServiceResponse ()
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
@end
Ahora, la subclase S3Response
también quiere acceso de lectura y escritura a esta propiedad y, por lo tanto, también define en la extensión de clase de su archivo de implementación:
@interface S3Response ()
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
@end
El compilador se queja porque, al compilar "S3Response.m", no sabe que existe un configurador para la propiedad en la superclase (no lee el archivo de implementación de la superclase en ese momento). Además, el compilador no puede simplemente sintetizar un definidor en la subclase, porque no puede saber que la propiedad está respaldada por una variable de instancia en la superclase.
Pero sabe que se generará un definidor, por lo que puede eliminar la advertencia agregando una declaración @dynamic
a la implementación de la subclase:
@implementation S3Response
@dynamic responseHeader;
...
@dynamic
es una "promesa" para el compilador de que todos los métodos de acceso necesarios estarán disponibles en tiempo de ejecución.