Como no puedo crear una propiedad sintetizada en una Categoría en Objective-C, no sé cómo optimizar el siguiente código:
@interface MyClass (Variant)
@property (nonatomic, strong) NSString *test;
@end
@implementation MyClass (Variant)
@dynamic test;
- (NSString *)test {
NSString *res;
//do a lot of stuff
return res;
}
@end
El método de prueba se llama varias veces en tiempo de ejecución y estoy haciendo muchas cosas para calcular el resultado. Normalmente, usando una propiedad sintetizada, almaceno el valor en un IVar _test la primera vez que se llama al método, y solo devuelvo este IVar la próxima vez. ¿Cómo puedo optimizar el código anterior?
objective-c
categories
dhrm
fuente
fuente
Respuestas:
El método de @lorean funcionará (nota: la respuesta ahora se elimina) , pero solo tendría una ranura de almacenamiento. Entonces, si quisiera usar esto en varias instancias y hacer que cada instancia calcule un valor distinto, no funcionaría.
Afortunadamente, el tiempo de ejecución de Objective-C tiene una cosa llamada objetos asociados que puede hacer exactamente lo que quieres:
fuente
@selector(test)
como clave, como se explica aquí: stackoverflow.com/questions/16020918/…archivo .h
archivo .m
Al igual que una propiedad normal, accesible con notación de puntos
Sintaxis más fácil
Alternativamente, podría usar en
@selector(nameOfGetter)
lugar de crear una tecla de puntero estática como esta:Para obtener más detalles, consulte https://stackoverflow.com/a/16020927/202451
fuente
@dynamic objectTag;
.@dynamic
significa que el setter y getter se generarán en otro lugar, pero en este caso se implementan aquí.La respuesta dada funciona muy bien y mi propuesta es solo una extensión que evita escribir demasiado código repetitivo.
Para evitar escribir repetidamente métodos getter y setter para propiedades de categoría, esta respuesta introduce macros. Además, estas macros facilitan el uso de propiedades de tipo primitivas como
int
oBOOL
.Enfoque tradicional sin macros
Tradicionalmente, define una propiedad de categoría como
Luego debe implementar un método getter y setter utilizando un objeto asociado y el selector get como clave ( consulte la respuesta original ):
Mi enfoque sugerido
Ahora, usando una macro, escribirás en su lugar:
Las macros se definen de la siguiente manera:
La macro
CATEGORY_PROPERTY_GET_SET
agrega un getter y setter para la propiedad dada. Las propiedades de solo lectura o de solo escritura usarán la macroCATEGORY_PROPERTY_GET
yCATEGORY_PROPERTY_SET
respectivamente.Los tipos primitivos necesitan un poco más de atención.
Como los tipos primitivos no son objetos, las macros anteriores contienen un ejemplo para usar
unsigned int
como tipo de propiedad. Lo hace envolviendo el valor entero en unNSNumber
objeto. Entonces su uso es análogo al ejemplo anterior:Siguiendo este patrón, simplemente puede añadir más macros para apoyar también
signed int
,BOOL
, etc ...Limitaciones
Todas las macros están usando
OBJC_ASSOCIATION_RETAIN_NONATOMIC
por defecto.Los IDEs como App Code actualmente no reconocen el nombre del configurador cuando refactorizan el nombre de la propiedad. Tendría que cambiarle el nombre usted mismo.
fuente
#import <objc/runtime.h>
en la categoría .m archivo de lo contrario. error de tiempo de compilación: la declaración implícita de la función 'objc_getAssociatedObject' no es válida en C99 aparece. stackoverflow.com/questions/9408934/…Simplemente use la biblioteca libextobjc :
archivo h:
archivo-m:
Más acerca de @synthesizeAssociation
fuente
Probado solo con iOS 9 Ejemplo: Agregar una propiedad UIView a UINavigationBar (Categoría)
UINavigationBar + Helper.h
UINavigationBar + Helper.m
fuente
Otra posible solución, quizás más fácil, que no se utiliza
Associated Objects
es declarar una variable en el archivo de implementación de categoría de la siguiente manera:La desventaja de este tipo de implementación es que el objeto no funciona como una variable de instancia, sino como una variable de clase. Además, no se pueden asignar atributos de propiedad (como los utilizados en Objetos asociados como OBJC_ASSOCIATION_RETAIN_NONATOMIC)
fuente