Вопрос по objective-c – Разница между доступом к методам свойств и полям классов (Objective-C)

11

Предположим, что у меня есть этот кусок кода:

@interface Foo : NSObject {
    Bar *bar;
}

@property (retain, nonatomic) Bar *bar;

@end

При использовании этого поля / свойства, есть ли разница между строками:

[self.bar doStuff];

а также

[bar doStuff];

?

При выполнении присваивания метод свойства будет выполнять правильное сохранение, но как насчет доступа для чтения к свойству, как описано выше? Есть ли разница?

Ваш Ответ

4   ответа
0

класса Bar, ваше поле Bar станет Зомби раньше, чем ваш параметр Bar Property with Retain, поскольку счетчик ссылок не увеличивается при назначении полей, и иногда вы сталкиваетесь с & quot; доступ к освобожденным объектам & quot; ошибка.

2

[self bar]. Синтаксис периода только для внешности. Прямой доступ к переменной-члену не требует дополнительного вызова функции и, следовательно, немного быстрее. Это действительно имеет значение, только если вы обращаетесь к нему в цикле или в каком-то процессе, где эта разница будет складываться. (На iPhone) Сеттеры, созданные для свойств, также имеют некоторые дополнительные издержки для выполнения кодирования значения ключа. Уведомление KVO отправляется, когда вы вызываете «setBar:» или произнесите & quot; self.bar = & quot; , поэтому повторный вызов приведет к потоку уведомлений.

Джим прав, хотя - нет никакой функциональной разницы между неатомным @property и прямым использованием переменной в вашем коде. Если вы действительно не заинтересованы в скорости, использование собственности, вероятно, является лучшим выбором.

Хороший вопрос Николай - поскольку переопределенная строка - (Bar *) может добавить дополнительную бизнес-логику или вернуть что-то, кроме bar, использование свойства может быть не эквивалентно прямой ссылке на переменную. Спасибо что подметил это!
Нет. Рассмотрим производный класс, который переопределяет - (Bar *) bar;
Просто чтобы прояснить: издержки, о которых вы говорите, не зависят от метода установки, создаваемого с помощью оператора @synthesize. Даже если вы реализуете их самостоятельно, уведомления будут отправлены, если наблюдатель зарегистрирован. Это достигается с помощью Isa Swizzling.
0

тупа будет функционально эквивалентен

- (Bar *)bar
{
    return bar;
}

так что между вашими двумя примерами нет функциональной разницы.

Тем не менее, вне -dealloc или ваших инициализаторов, постоянный доступ к свойству через его метод доступа является хорошей идеей.

13

[self.bar doStuff] эквивалентно[[self bar] doStuff]

[bar doStuff] эквивалентно[self->bar doStuff]

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

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

- (void)setBar:(Bar*)b;
- (Bar*)bar;

Также обратите внимание, что сгенерированный компилятором метод setter сохраняет вашBar экземпляр, как вы сказали в@property декларация.

Разница определенно есть. Производный класс может переопределить - (Bar *) bar и вернуть другой объект.
Однако, несмотря на различие между механизмами получения и выбора полей, функциональных различий между упомянутыми линиями по-прежнему нет. То есть один и тот же объект получит то же сообщение, верно? Sergey Mikhanov
ну, может быть. Так как вы можете свободно реализовывать панель методов любым удобным для вас способом. Например, вы можете вернуть прокси-объект или что-либо еще. Даже если вы синтезируете методы доступа, они могут вести себя по-разному, например, синхронизировать доступ, если вы устанавливаете свойство как атомарное.
Но в случае, когда я синтезирую свойство, даже если бы была синхронизация, или сохранение, или что-то еще, между упомянутыми строками по-прежнему не было функциональной разницы в том смысле, чтоsame object получаетsame message, право? Sergey Mikhanov

Похожие вопросы