2009-08-20 5 views
6

Я хочу, чтобы загорелся какой-то код, когда свойство было доступно и изменено. Я использую @property и @synthesize в своем коде для моих иваров. Свойства сохранены, поэтому я хотел бы сохранить этот материал управления памятью автоматически генерируемый @synthesize.Как обеспечить дополнительную пользовательскую реализацию методов доступа при использовании @synthesize?

Однако я предполагаю, что @synthesize сообщает компилятору, что он генерирует код методов доступа, где @synthesize is, поэтому большинство случаев в верхней части кода, правильно?

И когда у меня есть имущество foo, я получаю -setFoo и -foo методов. Могу ли я затем сделать такой способ, чтобы выполнить еще один пользовательский код при изменении свойства?

-(void)setFoo { 
    // custom stuff 
} 

Теперь это проблема. Как выполнить первый? Я не хотел бы иметь другое имя здесь. Возможно ли, чтобы директива @synthesize создала другие имена для методов getter и setter, которые я тогда называю легко? И я все равно смогу использовать синтаксис точек, чтобы получить к ним доступ?

ответ

5

Вы можете использовать @property и @synthesize так же, как вы, как правило, должны были бы, но предоставить пользовательский сеттер или геттер (или оба), и они будут использоваться вместо этого. Обычно я буду делать примерно так:

// Override the setter 
- (void)setName:(NSString *)aName 
{ 
    if (name == aName) 
     return; 

    [name release]; 
    name = [aName retain]; 

    //custom code here 
} 

Когда я использую свойство set, он будет вызывать мой собственный метод. Однако получение все равно будет синтезировано.

+1

FYI, ваш пример setter имеет ошибку, поскольку вызов его дважды с тем же объектом может привести к тому, что этот объект будет отменен до его сохранения. Не очень-то большое дело, но это иллюстрирует, как трудно добиться того, чтобы все было правильно. –

+0

Я не уверен, что я последую за вами, не могли бы вы объяснить, как это должно быть написано (не то, чтобы я не верю вам, я хотел бы знать, как это сделать правильно). Спасибо :) – jbrennan

+1

О, nvm Я вижу проблему, я обновлю ее, чтобы отразить изменения. – jbrennan

1

Если вы предоставляете имплементацию для сеттеров или геттеров, он будет использовать это вместо сгенерированной реализации. Его не сложно реализовать «сохраняющий» аспект геттеров и сеттеров, которые генерируются для вас компилятором при синтезе u, поэтому вы можете просто написать свои собственные геттеры и сеттеры, которые я бы сказал и пошел с этим.

-2

Да, в вашем объявлении @property вы можете указать методы получения и настройки.

@property (readwrite,getter=privateGetFoo,setter=privateSetFoo:) NSObject * foo; 

В ваших foo и setFoo: методы, вызовите [self privateGetFoo] или [self privateSetFoo:f] то пользовательский код.

Объект также может установить наблюдателя на себя с addObserver:forKeyPath:options:context:.

Тем не менее, я не думаю, что любой из них является очень чистым способом сделать что-то. Лучше написать свой собственный приемник/сеттер, как предложили другие.

+0

Вы сказали: «В ваших foo и setFoo: methods ...» Пока доступны [obj setFoo: x] и [obj foo], важно отметить, что из-за измененного свойства obj.foo не будет быть доступным для записи, и вам придется использовать obj.setFoo = x. Это не так, как обычно это делает @property, где obj.foo используется как для чтения, так и для записи. – mahboudz

+0

Тогда object.foo эквивалентен [object privateFoo], который побеждает цели использования свойств. –

0

Одним из дурацких решений является создание абстрактного суперкласса, который дает вам нормальный синтез свойств. Затем создайте конкретный подкласс, который вы фактически будете использовать, и который просто реализует и переопределяет метод (та же подпись) и вызывает супер, чтобы выполнить фактическую настройку. Это позволяет делать то, что вы хотите сделать до или после вызова супер-реализации.

Пример:

@interface ALTOClassA : NSObject 


@property NSString *catName; 

@end 

Ничего еще нужно в ой за пределами погасили файл для этого теста.

Создать подкласс, ничего не нужно специально в @interface

#import "ALTOClassA.h" 

@interface ALTOClassAJunior : ALTOClassA 

@end 

В @implementation мы делаем наше переопределение.

#import "ALTOClassAJunior.h" 

@implementation ALTOClassAJunior 


- (void)setCatName:(NSString*)aCatName { 
    NSLog(@"%@",NSStringFromSelector(_cmd)); 
    [super setCatName:aCatName]; 
    NSLog(@"after super: self.catName %@", self.catName); 
} 
@end 

При использовании:

ALTOClassAJunior *aCAJ = [ALTOClassAJunior new]; 
NSLog(@"aCAS.catName %@", aCAJ.catName); 

NSLog(@"set it to George."); 

[aCAJ setCatName:@"George"]; 

NSLog(@"aCAS.catName %@", aCAJ.catName); 

Это позволяет использовать автоматически сгенерированный код, и все еще делать вещи вы хотите сделать с вашим классом. Аннотация Суперкласс часто является полезным решением для многих вещей.

Смежные вопросы