Когда получить доступ к собственности с собой, а когда нет? - PullRequest
5 голосов
/ 03 февраля 2011

Может кто-нибудь объяснить разницу между настройкой someObject = someOtherObject; и self.someObject = someOtherObject;, если someObject является свойством класса, созданным с помощью @property (nonatomic, retain) SomeType someObject;

Чтобы уточнить, у меня есть что-то вроде:

@interface SomeClass : NSObject {
   SomeType* someObject;
}

@property (nonatomic, retain) SomeType* someObject;

@end

Я заметил, что иногда получаю EXC_BAD ACCESS, когда использую свойство без self, и оно кажется довольно случайным. Когда я использую себя, моя программа работает так, как должно быть. Я не получаю никаких ошибок или предупреждений компилятора, когда я пропускаю себя, так что я думаю, что это какой-то правильный синтаксис?

Ответы [ 4 ]

5 голосов
/ 03 февраля 2011

self.someObject = someOtherObject использует собственность.Свойства генерируют сеттеры и геттеры для вас.В вашем случае вы передали свойству атрибут retain, что означает, что объект, установленный через это свойство, автоматически получит сообщение retain, которое увеличит его счетчик хранения на 1. Кроме того, старое значение переменной-члена равноотправил сообщение release, которое уменьшает количество сохраненных сообщений.

Объекты освобождаются, когда их количество хранения достигает 0. Вы получаете EXC_BAD_ACCESS, если вы пытаетесь получить доступ к освобожденному объекту (например, если вы пытаетесь освободить его слишком часто).ваш случай:

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
self.someObject = soo; //soo's retain count is now 2
[soo release]; //soo's retain count is 1 again, as self still uses it.
[self doSomethingWithSoo];

Однако, если вы не используете сеттер, вы не должны выпускать soo.

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
someObject = soo; //soo's retain count is still  1
[soo release]; //soo's retain count is 0, it will be deallocated
[self doSomethingWithSoo]; //will fail with an EXC_BAD_ACCESS exception, as soo does not exist anymore.
2 голосов
/ 03 февраля 2011

Свойства - это просто удобный способ доступа к данным.Поэтому, когда вы объявляете свойство @property (nonatomic, retain) SomeType * someObject;это означает, что во время доступа будет синтезировано 2 метода:

getter:

-(SomeType*) someObject {
   return someObject;
}

setter

-(void) setSomeObject:(SomeType*) obj {
   [someObject release];
   someObject = [obj retain];
}

Таким образом, основное различие между свойствами и ivars заключается в том, что свойствадинамическое создание методов установки / получения (и вы можете переопределить их).Но когда вы пишете someObject = new_val, вы просто копируете ссылку на ячейку памяти.Никакой дополнительной работы там не сделано, кроме одной инструкции по сборке.

Следует упомянуть еще одну вещь: атомарную и неатомную.С атомарным, синтезированный установщик / получатель будет гарантировать, что целое значение всегда возвращается из получателя или устанавливается установщиком, независимо от активности установщика в любом другом потоке.То есть, если поток A находится в середине метода получения, а поток B вызывает метод установки, фактическое жизнеспособное значение - объект с автоматически освобожденным кодом, скорее всего, - будет возвращено вызывающей стороне в A.

Inнеатомные, такие гарантии не предоставляются.Таким образом, nonatomic значительно быстрее, чем atomic.

Редактировать: поэтому, если у вас есть некоторая переменная, доступ к которой осуществляется из разных потоков или / и необходимо выполнить некоторую дополнительную работу (например, сохранить, поднять некоторые флаги ...), то ваш выбор - собственность.Но иногда у вас есть переменная, к которой очень часто обращаются, и доступ через свойство может привести к большим накладным расходам, потому что процессору приходится выполнять гораздо больше операций для синтеза и вызова метода.

1 голос
/ 03 февраля 2011

Все дело в управлении памятью.

Ваше свойство класса someObject создало методы доступа с аннотацией @property / @synthsize в ваших файлах .h / .m.

Когда вы получаете доступ к своей собственности с помощью someObject, вы получаете прямой доступ к собственности. Когда вы обращаетесь к self.someObject, вы звоните своему аксессору [self someObject], который позаботится об управлении памятью.

Так что, когда вам нужно присвоить свойство класса, это делает чище self.someObject = someOtherObject;, потому что вы используете установщик и не должны заботиться о выпуске и сохранении. Когда ваш сеттер генерируется с @property (nonatomic, retain), он позаботится о сохранении для вас.

0 голосов
/ 03 февраля 2011

Разница между ними такова:

1) когда вы не используете "себя".Вы присваиваете результат непосредственно переменной-члену.

2), когда вы используете "self".Вы вызываете метод установки для этого свойства.Он такой же, как [self setMyObject: ...];

, поэтому в случае self.myobject он сохраняет свое сохранение, а в другом случае (без self), если вы не используете alloc,тогда он будет обрабатываться как объект автоматического освобождения.

В большинстве случаев вы обнаружите, что хотите использовать «self», за исключением случаев инициализации объекта.

Кстати, вы можететакже используйте self.someObject = [someOtherObject retain] для увеличения счетчика удержания

...