Hasta donde yo sé, desde XCode 4.4, se @synthesize
generarán automáticamente los descriptores de acceso de propiedad. Pero acabo de leer una muestra de código sobre NSUndoManager
, y en el código noté que @synthesize
se agrega explícitamente. Me gusta:
@interface RootViewController ()
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSUndoManager *undoManager;
@end
@implementation RootViewController
//Must explicitly synthesize this
@synthesize undoManager;
Me siento desconcertado ahora ... ¿Cuándo debo agregar @synthesize
explícitamente a mi código?
@sythesize
. Si el código aún funciona, entonces no es necesario.Respuestas:
Hay muchas respuestas, pero también una gran confusión. Intentaré poner algo de orden (o aumentar el lío, ya veremos ...)
Dejemos de hablar de Xcode. Xcode es un IDE . clang es un compilador . Esta característica que estamos discutiendo se llama autosíntesis de propiedades y es una extensión del lenguaje Objective-C compatible con clang , que es el compilador predeterminado utilizado por Xcode.
Solo para que quede claro, si cambia a gcc en Xcode, no se beneficiará de esta función (independientemente de la versión de Xcode). De la misma manera, si usa un editor de texto y compila usando clang desde la línea de comando, será.
Gracias a la autosíntesis, no es necesario sintetizar explícitamente la propiedad, ya que el compilador la sintetizará automáticamente como
@synthesize propertyName = _propertyName
Sin embargo, existen algunas excepciones:
propiedad readwrite con getter y setter personalizados
al proporcionar tanto una implementación personalizada get y set, la propiedad no se puede sintetizar de forma automática
propiedad de solo lectura con getter personalizado
al proporcionar una implementación de captador personalizado para una propiedad de solo lectura, esto no se sintetizará automáticamente
@dinámica
cuando se usa
@dynamic propertyName
, la propiedad no se sintetizará automáticamente (bastante obvio, ya que@dynamic
y@synthesize
son mutuamente excluyentes)propiedades declaradas en un @protocolo
cuando se ajusta a un protocolo, cualquier propiedad que defina el protocolo no se sintetizará automáticamente
propiedades declaradas en una categoría
este es un caso en el que la
@synthesize
directiva no es insertada automáticamente por el compilador, pero estas propiedades tampoco se pueden sintetizar manualmente. Si bien las categorías pueden declarar propiedades, no se pueden sintetizar en absoluto, ya que las categorías no pueden crear ivars. En aras de la integridad, agregaré que todavía es posible falsificar la síntesis de propiedades utilizando el tiempo de ejecución de Objective-C .propiedades anuladas (nuevo desde clang-600.0.51, envío con Xcode 6, gracias Marc Schlüpmann)
cuando anula una propiedad de una superclase, debe sintetizarla explícitamente
Vale la pena señalar que sintetizar una propiedad sintetiza automáticamente el ivar de respaldo, por lo que si falta la síntesis de la propiedad, también faltará el ivar, a menos que se declare explícitamente.
Excepto en los últimos tres casos, la filosofía general es que siempre que especifique manualmente toda la información sobre una propiedad (implementando todos los métodos de acceso o usando
@dynamic
) el compilador asumirá que desea un control total sobre la propiedad y deshabilitará la autosíntesis en eso.Aparte de los casos que se enumeran anteriormente, el único otro uso de un explícito
@synthesize
sería especificar un nombre de ivar diferente. Sin embargo, las convenciones son importantes, por lo que mi consejo es usar siempre la denominación predeterminada.fuente
@synthesize
en una categoría está prohibido (no ivar en las categorías, como ya ha señalado). Agregaré una nota.Si no utiliza explícitamente,
@synthesize
el compilador entenderá su propiedad de la misma manera si hubiera escrito@synthesize undoManager=_undoManager;
entonces podrás escribir en tu código cosas como:
[_undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter
Ésta es la convención común.
Si tú escribes
@synthesize undoManager;
usted tendrá :
[undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter
Personalmente dejo de usar
@synthesize
, ya que ya no es obligatorio. Para mí, la única razón para usarlo@synthesize
es vincular uniVar
a un@property
. Si desea generar getter y setter específicos para ello. Pero en el código dado no hayiVar
, creo que esto@synthesize
es inútil. Pero ahora creo que la nueva pregunta es "¿Cuándo usariVar
?", ¡Y no tengo otra respuesta que "nunca" para esta!fuente
@synthesize
porque ya no hay razón para hacerlo. Además, el subrayado inicial sirve como una bonita bandera visual para hacerle saber que está trabajando en torno a la gestión de memoria y la red de seguridad de subprocesos que proporcionan las propiedades (que debería omitirinit
ydealloc
métodos).¿Cuándo debo agregar
@synthesize
explícitamente a mi código?Generalmente, si es necesario: Probablemente nunca encontrará un caso donde sea necesario.
Sin embargo, hay un caso que puede resultarle útil.
Supongamos que está escribiendo tanto un getter como un setter personalizados, pero desea que una variable de instancia lo respalde. (Para una propiedad atómica, esto es tan simple como querer un setter personalizado: el compilador escribirá un getter si especificas un setter para una propiedad monoatómica, pero no una propiedad atómica).
Considera esto:
@interface MyObject:NSObject @property (copy) NSString *title; @end @implementation MyObject - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
Esto no funcionará porque
_title
no existe. Ha especificado tanto un getter como un setter, por lo que Xcode (correctamente) no crea una variable de instancia de respaldo para él.Tienes dos opciones para hacerlo existir. Puede cambiar el
@implementation
a esto:@implementation MyObject { NSString *_title; } - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
O cámbielo a esto:
@implementation MyObject @synthesize title = _title; - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
En otras palabras, aunque sintetizar nunca es necesario para fines prácticos *, se puede utilizar para definir variables de instancia de respaldo de propiedad cuando se proporciona un captador / definidor. Aquí puede decidir qué formulario desea utilizar.
En el pasado, prefería especificar la variable de instancia en el
@implementation {}
, pero ahora creo que@synthesize
ruta es una mejor opción, ya que elimina el tipo redundante y vincula explícitamente la variable de respaldo a la propiedad:@synthesize
generará un error del compilador. No acabará con variables de instancia extraviadas.* -Conozco un caso en el que fue necesario, relacionado con la división de funciones en categorías en varios archivos. Y no me sorprendería si Apple soluciona esto, o incluso si ya lo ha hecho.
fuente
atomic
no se agregó como especificador de propiedad hasta más tarde. Ahora que está allí, puede que la bandera de advertencia le resulteCLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES
interesante.OK, cuando creas una propiedad ...
@property NSString *name;
Xcode sintetizará automáticamente una iVar como si hubiera escrito ...
@synthesize name = _name;
Esto significa que puede acceder a la propiedad con ...
self.name; // or _name;
Cualquiera de los dos funcionará, pero solo
self.name
realmente usa los métodos de acceso.Solo hay una vez que la síntesis automática no funciona: si sobrescribe pero el método setter Y getter, necesitará sintetizar el iVar.
Está bien si simplemente anula el setter o si simplemente anula el getter. Pero si hace ambas cosas, el compilador no lo entenderá y necesitará sintetizarlo manualmente.
Sin embargo, como regla general.
No hagas iVars. Solo usa la propiedad. No lo sintetices.
fuente
La síntesis de propiedad es necesaria cuando una propiedad se declara en un protocolo. No se sintetizará automáticamente en una interfaz de implementación.
fuente
Gracias por aclarar eso. Tuve un problema similar.
@synthesize firstAsset, secondAsset, audioAsset; @synthesize activityView;
Así que ahora, habiéndolos comentado, revisé y reemplacé cada ocurrencia con, por ejemplo
self.firstAsset Parece que también podría usar firstAsset, pero encuentro que extraño ver el " " con demasiada frecuencia.
fuente
Xcode no requiere una
@synthesize
declaración explícita .Si no escribe,
@synthesize
es lo mismo que hacer:@synthesize manager = _manager;
Es posible que el código de muestra sea antiguo. Lo actualizarán pronto.
Puede acceder a sus propiedades como:
[self.manager function];
Esta es la convención recomendada por Apple. Lo sigo y te recomiendo que lo hagas tú también.
fuente
[_manager function]
NO accederá a la propiedad, sino que accederá directamente al ivar subyacente .[_manager function]
no utiliza accesos de la propiedad.