Идиомы Objective C — свойства, переменные и потребности.

Вот ситуация, с которой я часто сталкиваюсь, достаточно, чтобы шаблонный код был расточительным, и достаточно, чтобы я был уверен, что не могу быть единственным. Является ли это однообразным, есть ли лучший способ, или мне просто нужно делать это каждый раз?

@interface SomeUIElement : UIView
@property CGFloat insetMargin; // <-- just an example of a UI parameter
@end

@implementation SomeElement
- (void)setInsetMargin:(CGFloat)insetMargin {
    _insetMargin = insetMargin;
    [self setNeedsDisplay]; // <-- the only thing that stops it being synthesized
}
@end

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

- (CGFloat)insetMargin {
    return _insetMargin;
}

но теперь он жалуется, что у меня нет ivar (поскольку определенный геттер и сеттер означает, что он не создан для меня), поэтому мне нужно добавить

@interface SomeUIElement () {
    CGFloat _insetMargin;
}

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

Есть ли (а) какой-то способ сообщить ObjC, что я действительно намеревался создать для меня геттер и ивар, поэтому мне нужно только написать сеттер, или (б) лучший способ запросить обновление отображения, когда свойство, связанное с внешний вид меняется?

Как Apple SDK это делает (я предполагаю, что не пропустил какой-то способ просмотра, скажем, источник UILabel)?


person Ian    schedule 03.08.2013    source источник
comment
Вам нужно, чтобы свойство было атомарным? Это то, что вызывает сбой синтеза и, следовательно, жалобы компилятора.   -  person jscs    schedule 03.08.2013
comment
Ах, мне на самом деле не нужна атомарность (или, в редких случаях, я не возражаю против прыжков с обручей), поэтому, если я вставлю неатомарность везде, даже для типов данных, состоящих из одного слова, это создаст для меня ivar? Я этого не знал, спасибо. Вы должны поместить это в ответ!   -  person Ian    schedule 03.08.2013
comment
Если вы объявляете свойство как @property (nonatomic, assign) CGFloat insetMargin, вам не нужен геттер или ивар.   -  person rmaddy    schedule 03.08.2013
comment
rmaddy - конечно, назначение не имеет значения, так как я пишу свой собственный сеттер и явно «назначаю» его. Или я тоже что-то пропустил?   -  person Ian    schedule 03.08.2013
comment
Вы не поставили @ перед моим именем пользователя, поэтому я не получил ваш комментарий раньше. Использование assign в объявлении собственности означает контракт. Вы позволяете клиентам кода узнать семантику свойства. Конечно, вы хотите, чтобы ваша реализация соблюдала этот контракт.   -  person rmaddy    schedule 03.08.2013
comment
@rmaddy - отличное замечание   -  person Ian    schedule 03.08.2013


Ответы (1)


Вы можете получить «частичный синтез», если свойство объявлено неатомарным:

@property (nonatomic) CGFloat insetMargin;

По умолчанию (по неизвестным причинам) используется atomic. Чтобы реализовать эту атомарность, оба метода доступа должны использовать один и тот же механизм блокировки. Однако этот механизм не раскрывается при синтезе методов. Поэтому вам нужно либо реализовать оба средства доступа и создать свою собственную блокировку, либо позволить компилятору сделать и то, и другое и использовать свою блокировку.

Однако если свойство не является атомарным, вы можете явно реализовать любую комбинацию трех элементов: ivar, setter или getter, а компилятор позаботится обо всем остальном. Если вы хотите изменить имя ивара по умолчанию (в настоящее время имя свойства с предшествующим символом подчеркивания), вам также потребуется явный @synthesize.

person jscs    schedule 03.08.2013