Come fornire un'implementazione personalizzata aggiuntiva di metodi di accesso quando si utilizza @synthesize?
-
19-09-2019 - |
Domanda
Voglio sparare po 'di codice quando una proprietà si accede e cambiò. Io uso @property
e @synthesize
nel mio codice per i miei Ivars. Le proprietà vengono mantenute, quindi mi piacerebbe mantenere quella roba la gestione della memoria generato automaticamente dal @synthesize
.
Tuttavia, presumo che @synthesize
dice al compilatore di generare il codice di metodi di accesso a destra dove @synthesize is
, quindi la maggior parte dei casi nella parte superiore del codice, giusto?
E quando ho un foo
proprietà, ottengo -setFoo
e -foo
metodi. Potrei poi basta fare un metodo come questo, per eseguire un po 'di codice personalizzato quando una proprietà è cambiato?
-(void)setFoo {
// custom stuff
}
Ora che è un problema. Come eseguire il primo? Io non piacerebbe avere un nome diverso qui. C'è forse un modo per lasciare che la direttiva @synthesize
creare altri nomi per metodi getter e setter, che ho poi chiamo facilmente? E vorrei ancora in grado di utilizzare la sintassi del punto quindi per accedervi?
Soluzione
È possibile utilizzare @property
e @synthesize
proprio come si farebbe normalmente, ma fornire un setter personalizzato o getter (o entrambi) e quelli sarà usato al posto. In genere io farò qualcosa di simile:
// Override the setter
- (void)setName:(NSString *)aName
{
if (name == aName)
return;
[name release];
name = [aName retain];
//custom code here
}
Quando uso la proprietà insieme, si invocherà il mio metodo personalizzato. Tuttavia, sarà ancora essere sintetizzato il get.
Altri suggerimenti
Se si fornisce un implemnetation per i setter o getter Userà che invece della realizzazione generato. La sua non è difficile da attuare l'aspetto "di contenimento" dei getter e setter che sono generati per voi dal compilatore quando u sintetizzare, quindi si può solo scrivere i propri getter e setter, direi che e andare con quella.
Una soluzione stravagante è quello di creare un super-classe astratta che non dà la sintesi di proprietà normale. Quindi creare una sottoclasse concreta che verrà effettivamente utilizzare, e che implementa in modo semplice e metodo di sostituzione (stessa firma) e chiama super per fare l'impostazione attuale. Questo ti permette di fare quello che vuoi fare prima o dopo la chiamata alla realizzazione dei Super.
Esempio:
@interface ALTOClassA : NSObject
@property NSString *catName;
@end
Niente altro necessario nel .m al di là del file spense per questo test.
Crea la sottoclasse, nulla necessaria specialmente in @interface
#import "ALTOClassA.h"
@interface ALTOClassAJunior : ALTOClassA
@end
Nel @implementation facciamo la nostra esclusione.
#import "ALTOClassAJunior.h"
@implementation ALTOClassAJunior
- (void)setCatName:(NSString*)aCatName {
NSLog(@"%@",NSStringFromSelector(_cmd));
[super setCatName:aCatName];
NSLog(@"after super: self.catName %@", self.catName);
}
@end
In uso:
ALTOClassAJunior *aCAJ = [ALTOClassAJunior new];
NSLog(@"aCAS.catName %@", aCAJ.catName);
NSLog(@"set it to George.");
[aCAJ setCatName:@"George"];
NSLog(@"aCAS.catName %@", aCAJ.catName);
Questo consente di sfruttare il codice generato automaticamente, ed ancora fare cose che vuoi fare con la classe. Riepilogo Super Class è spesso una soluzione utile per molte cose.
Sì, nella dichiarazione @property, è possibile specificare i metodi getter e setter.
@property (readwrite,getter=privateGetFoo,setter=privateSetFoo:) NSObject * foo;
Nel vostro foo
e setFoo:
metodi, chiamare [self privateGetFoo]
o [self privateSetFoo:f]
allora il codice personalizzato.
L'oggetto può anche impostare un osservatore su se stessa con addObserver:forKeyPath:options:context:
.
Detto questo, non credo che uno di questi sono modi molto pulito di fare le cose. Meglio scrivere il proprio getter / setter come altri hanno suggerito.