Como não consigo criar uma propriedade sintetizada em uma categoria no Objective-C, não sei como otimizar o seguinte 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
O método de teste é chamado várias vezes em tempo de execução e estou fazendo muitas coisas para calcular o resultado. Normalmente, usando uma propriedade sintetizada, eu armazeno o valor em um IVar _test na primeira vez que o método é chamado, e apenas retornando esse IVar na próxima vez. Como posso otimizar o código acima?
objective-c
categories
dhrm
fonte
fonte
Respostas:
O método do @ coreano funcionará (nota: a resposta agora foi excluída) , mas você só teria um único slot de armazenamento. Portanto, se você quiser usá-lo em várias instâncias e fazer com que cada instância calcule um valor distinto, não funcionará.
Felizmente, o tempo de execução do Objective-C tem uma coisa chamada Objetos Associados que pode fazer exatamente o que você deseja:
fonte
@selector(test)
como uma chave, como explicado aqui: stackoverflow.com/questions/16020918/...arquivo .h
arquivo .m
Assim como uma propriedade normal - acessível com notação de ponto
Sintaxe mais fácil
Como alternativa, você pode usar em
@selector(nameOfGetter)
vez de criar uma chave de ponteiro estática da seguinte maneira:Para mais detalhes, consulte https://stackoverflow.com/a/16020927/202451
fonte
@dynamic objectTag;
.@dynamic
significa que o setter & getter serão gerados em outro lugar, mas, neste caso, eles serão implementados aqui.A resposta dada funciona muito bem e minha proposta é apenas uma extensão que evita escrever muito código clichê.
Para evitar escrever métodos getter e setter repetidamente para propriedades de categoria, esta resposta apresenta macros. Além disso, essas macros facilitam o uso de propriedades do tipo primitivo, como
int
ouBOOL
.Abordagem tradicional sem macros
Tradicionalmente, você define uma propriedade de categoria como
Em seguida, você precisa implementar um método getter e setter usando um objeto associado e o seletor get como a chave ( consulte a resposta original ):
Minha abordagem sugerida
Agora, usando uma macro, você escreverá:
As macros são definidas da seguinte maneira:
A macro
CATEGORY_PROPERTY_GET_SET
adiciona um getter e setter para a propriedade especificada. As propriedades somente leitura ou somente gravação usarão a macroCATEGORY_PROPERTY_GET
e,CATEGORY_PROPERTY_SET
respectivamente.Tipos primitivos precisam de um pouco mais de atenção
Como os tipos primitivos não são objetos, as macros acima contêm um exemplo para uso
unsigned int
como o tipo da propriedade. Isso é feito envolvendo o valor inteiro em umNSNumber
objeto. Portanto, seu uso é análogo ao exemplo anterior:Seguindo esse padrão, você pode simplesmente adicionar mais macros para também apoiar
signed int
,BOOL
, etc ...Limitações
Todas as macros estão sendo usadas
OBJC_ASSOCIATION_RETAIN_NONATOMIC
por padrão.IDEs como o App Code atualmente não reconhecem o nome do levantador ao refatorar o nome da propriedade. Você precisaria renomeá-lo sozinho.
fonte
#import <objc/runtime.h>
na categoria .m arquivo caso contrário. erro em tempo de compilação: A declaração implícita da função 'objc_getAssociatedObject' é inválida no C99 . stackoverflow.com/questions/9408934/…Basta usar a biblioteca libextobjc :
arquivo h:
arquivo m:
Mais sobre @synthesizeAssociation
fonte
Testado apenas com o iOS 9 Exemplo: Adicionando uma propriedade UIView ao UINavigationBar (Categoria)
UINavigationBar + Helper.h
UINavigationBar + Helper.m
fonte
Outra solução possível, talvez mais fácil, que não usa
Associated Objects
é declarar uma variável no arquivo de implementação da categoria da seguinte maneira:A desvantagem desse tipo de implementação é que o objeto não funciona como uma variável de instância, mas como uma variável de classe. Além disso, não é possível atribuir atributos de propriedade (como usado em objetos associados, como OBJC_ASSOCIATION_RETAIN_NONATOMIC)
fonte