Могу ли я переопределить, как @synthesize работает в Objective C?


Я создаю базовый класс, который имеет флаг isDirty. Он устанавливается каждый раз, когда изменяется одно из его свойств, но поскольку это базовый класс, он не знает, каковы его свойства. Так что в принципе, на каждом подклассе я должен переопределить каждый метод - set: на что-то вроде этого:

- (id) setName:(NSString *)value {
  if ([name isEqualToString:value]) {
    return;
  }
  [name autorelease];
  name = [value retain];
  isDirty = YES;  //Here's the important bit
}

Почти каждая строка этого-то, что автоматически синтезированный сеттер сделал бы. Есть ли способ, которым я могу переопределить то, что @synthesize На самом деле создает?

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

Есть идеи? Если это имеет значение, то это для приложения iPhone.

4 5

4 ответа:

Я не знаю способа, который позволит вам переопределить то, что делает @synthesize.

В конце концов, он используется для создания основных методов доступа-ie. те, которые не имеют определенного поведения.

Может быть, вам следует изучить кодирование значений ключей и наблюдение за значениями ключей?

Здесь несколько вопросов:

(1) Если вы беспокоитесь о производительности сеттера, вы не должны использовать-isEqualToString: в вашем сеттере. Вместо этого сделайте сравнение указателя, потому что это все, что имеет значение в данном контексте.

(2) Если у вас есть атрибут NSString, вы должны копировать на set. Копирование является бесплатным для неизменяемых строк и сохранит ваш бекон для изменяемых строк (предотвращая вызов от мутации строки из-под вас).

(3) снова с производительностью; вы проверяете равенство, но затем используете авторелиз. Это влечет за собой ненужные накладные расходы.

(4) * все они кажутся намного медленнее во время выполнения* указывает на то, что вы на самом деле не пробовали его, не выявили проблемы с производительностью и преждевременно оптимизируете свой код. Учитывая (1) и (3), вероятно, гораздо легче решить проблемы производительности.

Мои предложения:

(1) Используйте @synthesize. Он будет генерировать правильный и быстрый код, адресуя (1) и (3).

(2) Используйте кво или один из других механизмов. Пока вы не определите проблему производительности с помощью инструментария и количественной оценки, у вас не будет проблемы производительности.

(3) рассмотрите возможность использования CoreData (если, конечно, вы не нацелены на OS 2.икс). Пример кода взят из чего-то, что, очевидно, является объектом модели. Если ваш код хорошо интегрирован в модель / представление / контроллер, использование CoreData на уровне модели может упростить ваше приложение, и CoreData делает замечательная работа по отслеживанию изменений.

Нет.

То, чего вы хотите достичь, возможно только глубоко копаясь в Objective-C runtime или используя прокси-объекты.

Почему бы тебе еще раз не взглянуть на кво?

Если вы пишете свой собственный метод доступа(ы) @synthesize уважает это. @синтезировать отдает предпочтение аксессоры вы пишите по своему усмотрению. Просто укажите нужный вам способ доступа, и @synthesize будет проигнорирован. Например, можно реализовать метод доступа, который создает свойство только в том случае, если его еще нет.

Пример:

@synthesize standardUserDefaults;

- (NSUserDefaults *)standardUserDefaults {
    NSLog(@"standardUserDefaults");
    if (!standardUserDefaults) {
        NSLog(@"standardUserDefaults new");
        self.standardUserDefaults = [NSUserDefaults standardUserDefaults];
    }
    return standardUserDefaults;
}
Здесь" сеттер "синтезируется, а" геттер " - нет.