Как обеспечить дополнительную пользовательскую реализацию методов доступа при использовании @synthesize? - PullRequest
6 голосов
/ 20 августа 2009

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

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

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

-(void)setFoo {
    // custom stuff
}

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

Ответы [ 4 ]

5 голосов
/ 20 августа 2009

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

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

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

    //custom code here
}

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

1 голос
/ 20 августа 2009

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

0 голосов
/ 06 сентября 2013

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

Пример:

@interface ALTOClassA : NSObject


@property NSString *catName;

@end

В этом тесте больше ничего не нужно .m кроме файла-заглушки для этого теста.

Создайте подкласс, специально для интерфейса @ ничего не нужно

#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);

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

0 голосов
/ 20 августа 2009

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

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

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

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

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

...