Переопределить установщик @property и бесконечный цикл - PullRequest
37 голосов
/ 20 июня 2011

Существует класс A с:

@interface ClassA : NSObject {
}
@property (nonatomic, assign) id prop1;
@end

@implementation
@synthesize prop1;
@end

, тогда у меня есть подкласс

@interface ClassB : ClassA {
}
@end

@implementation

- (id)init {
    self = [super init];
    if (self) {
    }
    return self;
}

//This is infinite loop
- (void) setProp1:(id)aProp
{
    self.prop1 = aProp;
}
@end

, и это бесконечный цикл, потому что setProp1 из ClassB вызывает [ClassB setProp1: val] из ClassB,

Я уже пробовал вызывать [super setProp1], но это

Как перезаписать @property и присвоить значение внутри перезаписанного сеттера?И давайте предположим, что я не могу изменить ClassA.

Ответы [ 5 ]

56 голосов
/ 20 июня 2011

Просто присвойте переменной экземпляра напрямую, без использования точечного синтаксиса для вызова метода установки:

- (void) setProp1:(id)aProp
{
    self->prop1 = aProp;
}

Такой вопрос напрашивается, хотя. Все, что делает этот метод доступа, это именно то, что сделал бы родитель - так какой смысл вообще переопределять родитель?

23 голосов
/ 12 декабря 2012

С XCode 4.5+ и LLVM 4.1 нет необходимости @synthesize, вы получите _prop1 для ссылки.

- (void) setProp1:(id)aProp
{
    _prop1 = aProp;
}

Будет отлично работать.

9 голосов
/ 11 мая 2012

Вы не должны использовать «self» внутри установщика, так как это создает рекурсивный вызов.

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

И вам следует переопределить имя установщика, как предложено выше:

@synthesize prop1 = prop1_; 

...

- (void) setProp1:(id)aProp
{
    if (prop1_ != aProp) {
        [aProp retain]; 
        [prop1_ release]; 
        prop1_ = aProp;
    }
}
5 голосов
/ 16 июля 2011

Другая альтернатива - установить для синтезированной переменной другое имя, например, так:

@synthesize selectedQuestion = _selectedQuestion;

, а затем именовать ее _selectedQuestionЭто предотвращает случайную запись selectedQuestion, когда вы имели в виду self.selectedQuestion.

Однако Apple рекомендует не использовать подчеркивание.Вы можете использовать другое имя, но метод @ Sherm - лучший, imho.

4 голосов
/ 17 сентября 2012

Просто @synthesize желаемое свойство в вашем подклассе, затем вы можете использовать его как имя для прямого доступа к свойству:

Интерфейс основного класса:

@interface AClass : NSObject

@property (nonatomic, assign) id<someProtocol> delegate;

@end

Интерфейс подкласса:

@interface BCLass : AClass
@end

Реализация подкласса:

@implementation BCLass

@synthesize delegate = _delegate;

- (void)setDelegate:(id<someProtocol>)d{
    _delegate = d;
}

@end
...