objective c - ¿Cuándo debo usar @synthesize explícitamente?
objective-c properties (7)
Gracias por aclarar eso. Tuve un problema similar.
@synthesize firstAsset, secondAsset, audioAsset;
@synthesize activityView;
Así que ahora, después de comentarlos, revisé y reemplazé cada ocurrencia con, por ejemplo,
self.firstAsset Parece que también podría usar firstAsset, pero encuentro que extraño ver el " " demasiado a menudo.
Por lo que sé, desde XCode 4.4, @synthesize
generará automáticamente los @synthesize
propiedades. Pero justo ahora he leído una muestra de código sobre NSUndoManager
, y en el código notó que @synthesize
se agregó 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 confundido ahora ... ¿Cuándo debería agregar @synthesize
explícitamente a mi código?
Hay muchas respuestas, pero también una gran confusión. Intentaré poner algo de orden (o aumentar el desorden, ya veremos ...)
Dejemos de hablar de Xcode. Xcode es un IDE . clang es un compilador . Esta característica que estamos discutiendo se denomina autosíntesis de propiedades y es una extensión de lenguaje Objective-C compatible con clang , que es el compilador predeterminado utilizado por Xcode.
Solo para dejarlo en claro, si cambia a gcc en Xcode, no se beneficiará de esta característica (independientemente de la versión de Xcode). De la misma manera si usa un editor de texto y compila usando el clang desde la línea de comandos, será.Gracias a la autosíntesis, no necesita 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 una implementación personalizada tanto getter como setter, la propiedad no se sintetizará automáticamente
propiedad de solo lectura con captador personalizado
cuando se proporciona una implementación getter personalizada para una propiedad de solo lectura, esto no se sintetizará automáticamente
@dinámica
cuando se utiliza
@dynamic propertyName
, la propiedad no se sintetizará automáticamente (es bastante obvio, ya que@dynamic
y@synthesize
se excluyen mutuamente)Propiedades declaradas en un @protocol
al ajustarse 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 el
@synthesize
no inserta automáticamente la directiva@synthesize
, pero tampoco se pueden sintetizar manualmente estas propiedades. Si bien las categorías pueden declarar propiedades, no se pueden sintetizar en absoluto, ya que las categorías no pueden crear ivars. Para completar, 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 reemplaza 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, el ivar también faltará, a menos que se declare explícitamente.
Excepto en los últimos tres casos, la filosofía general es que cada vez que especifique manualmente toda la información sobre una propiedad (al implementar todos los métodos de acceso o mediante @dynamic
), el compilador asumirá que desea un control total sobre la propiedad y deshabilitará la La autosíntesis en ello.
Aparte de los casos que se enumeran anteriormente, el único otro uso de un @synthesize
explícito sería especificar un nombre ivar diferente. Sin embargo, las convenciones son importantes, por lo que mi consejo es utilizar siempre la denominación predeterminada.
La síntesis de propiedades se requiere cuando una propiedad se declara en un protocolo. No se sintetizará automáticamente en una interfaz de implementación.
OK, cuando creas una propiedad ...
@property NSString *name;
Xcode sintetizará automáticamente una iVar como si hubieras 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
realidad usa los métodos de acceso.
Solo hay una vez que la síntesis automática no funciona.
Si sobrescribe pero el setter Y el método getter, tendrá que sintetizar el iVar.
Usted está bien si simplemente anula el setter o si simplemente anula el getter. Pero si hace ambas cosas, el compilador no lo entenderá y tendrá que sintetizarlo manualmente.
Sin embargo, como regla general.
No hagas iVars. Sólo tiene que utilizar la propiedad. No lo sintetices.
Si no usa 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
Esta 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 usar @synthesize
es vincular una iVar
a una @property
. Si quieres generar getter y setter específicos para ello. Pero en el código dado no hay iVar
, creo que este @synthesize
es inútil. Pero ahora creo que la nueva pregunta es "¿Cuándo usar iVar
?", ¡Y no tengo otra respuesta que "nunca" para esta!
Xcode no requiere una declaración explícita @synthesize
.
Si no escribes @synthesize
es lo mismo que hacer:
@synthesize manager = _manager;
El código de muestra podría haber sido viejo. Lo actualizarán pronto.
Puede acceder a sus propiedades como:
[self.manager function];
Esta es la convención recomendada de Apple. Lo sigo, y te recomiendo que lo hagas también!
¿Cuándo debería agregar @synthesize
explícitamente a mi código?
Generalmente, si es necesario: probablemente nunca llegue a un caso donde sea necesario.
Sin embargo, hay un caso que podría resultarte útil.
Digamos que estás escribiendo tanto un getter como un setter personalizados, pero quieres una variable de instancia para respaldarla. (Para una propiedad atómica, esto es tan simple como desear un configurador personalizado: el compilador escribirá un captador si especifica un definidor 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 un getter o setter, por lo que Xcode (correctamente) no crea una variable de instancia de respaldo para él.
Tienes dos opciones para hacerlo existir. Puede cambiar la @implementation
a esto:
@implementation MyObject {
NSString *_title;
}
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
O cambiarlo 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 usar para definir variables de instancia de respaldo de propiedades cuando se proporciona un captador / definidor. Puede decidir qué formulario desea utilizar aquí.
En el pasado, he preferido la especificación de la variable de instancia en @implementation {}
, pero ahora creo que la ruta @synthesize
es una mejor opción, ya que elimina el tipo redundante y vincula explícitamente la variable de respaldo a la propiedad:
- Cambie el tipo de propiedad, y el tipo de variable de la instancia cambia.
- Cambie su calificador de almacenamiento (por ejemplo, hágalo débil en lugar de fuerte o fuerte en lugar de débil) y el calificador de almacenamiento cambia.
- Elimine o cambie el nombre de la propiedad, y
@synthesize
generará un error de compilación. No terminarás con variables de instancia extraviadas.
* -Conozco un caso donde fue necesario, relacionado con la división de la funcionalidad en varias categorías en varios archivos. Y no me sorprendería si Apple arregla esto, o si ya lo ha hecho.