Поначалу запись через точку может немного ввести в заблуждение.
Сеттер
В строке, которую вы разместили здесь
self.scale = scale;
вы не назначаете локальную переменную. На самом деле вы отправляете сообщение -setScale:
пользователю self
. Эта строка эквивалентна
[self setScale:scale];
Поскольку вы вызываете -setScale:
из -setScale:
, вы получаете эту бесконечную рекурсию.
Что вам нужно сделать, так это установить переменную экземпляра в вашем сеттере (вместо того, чтобы вызывать ваш сеттер изнутри). Обычно, просто написав
@property (nonatomic) CGFloat scale;
вы создали переменную экземпляра _scale
. Однако, поскольку вы также переопределили и -scale
, и -setScale:
, эта переменная экземпляра не будет создана. Поэтому вам нужно будет добавить переменную экземпляра самостоятельно. В объявлении вашего класса @interface
(или, альтернативно, в расширение класса @interface
)
//If adding the instance variable to the class declaration:
@interface MyClass : Superclass
{
//....
CGFloat _scale;
}
//....
@end
После этого достаточно изменить строку на
_scale = scale;
Добытчик
Есть еще две проблемные строки, которые вы опубликовали, в геттере. Первый
return self.scale;
внутри - (CGFloat)scale
. Как и раньше, это обозначение через точку не означает того, что вы можете подумать. На самом деле это означает
return [self scale];
Как и прежде, это вызывает бесконечную рекурсию. Второй
if (!self.scale) {
Это проблема по той же причине: выражение self.scale
при оценке равно [самомасштаб]. Опять же, это вызывает бесконечную рекурсию. Исправление для обоих из них состоит в том, чтобы заменить self.scale
на _scale
, оставив вам этот геттер:
- (CGFloat)scale
{
if (!_scale) {//Since CGFloat is not an object, this means <<if (_scale == 0) {>>
return DEFAULT_SCALE;
} else {
return _scale
}
}
Лучший способ
Ты делаешь здесь гораздо больше работы, чем должен. Было бы намного лучше воспользоваться вашим инициализатором:
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
{
self.scale = DEFAULT_SCALE;
}
}
Это гарантирует, что если scale
не установлено, будет возвращено DEFAULT_SCALE
. Это позволяет полностью исключить геттер (и, следовательно, @synthesize
). Поскольку вы вызываете -setNeedsDisplay
в сеттере, он вам все равно понадобится.
- (void)setScale:(CGFloat)scale
{
if (_scale != scale) {
_scale = scale;
[self setNeedsDisplay];
}
}
person
Nate Chandler
schedule
31.10.2012