Pregunta ¿Qué significa esta advertencia de síntesis de propiedad objetivo-c?


Desde que actualicé a Xcode 5.1, estoy comenzando a ver la siguiente advertencia en algún código que usa mi proyecto. Estoy tratando de descubrir lo que significa.

Advertencia: 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 anterior de la propiedad, en el archivo .h:

@property (nonatomic, readonly) NSDictionary *responseHeader;

No hay @synthesize declaración de esa propiedad, ni responseHeader o setResponseHeader definido como métodos. Sin embargo, hay una definición explícita de un ivar llamado responseHeader.

Me parece muy sencillo: la propiedad se declara como de solo lectura para los usuarios de la clase, pero de lectura y escritura localmente para que la clase pueda configurarla.

¿Qué significa esta advertencia y qué debo hacer al respecto?


16
2018-03-16 21:56


origen


Respuestas:


Ese código parece ser del AWS SDK para iOS, y S3Response es una subclase de AmazonServiceResponse.

El público AmazonServiceResponse interfaz 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 el subclase  S3Response también quiere acceso de lectura-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 una setter porque la propiedad existe en la superclase (no lee el archivo de implementación de la superclase en ese punto). Además, el compilador no puede simplemente sintetizar un colocador en la subclase, porque no puede ignorar que la propiedad está respaldada por una variable de instancia en la superclase.

Pero ya sabes que se generará un setter, por lo que puede eliminar la advertencia agregando un @dynamic declaración 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 disponible en tiempo de ejecución.


23
2018-03-16 22:46



El problema aquí es el siguiente.

De forma predeterminada, si no escribe la propiedad (débil / retener / fuerte / asignar) explícitamente, xCode verificará el tipo automáticamente. Entonces en caso de NSDictionary será fuerte. Por lo tanto, en la interfaz tendrá

@property (nonatomic, readonly, strong) NSDictionary *responseHeader;

Entonces se contradirá con la definición de implementación privada

@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;

El compilador no combina fuerte y se mantiene bajo la propiedad sintetizada, aunque formalmente es lo mismo.

Para curar la situación puedes escribir conservar en ambos casos, o más correcto, no debe escribir retener en absoluto. Será fuerte por defecto en ambas definiciones.


-1
2018-03-16 22:18