Подтвердить что ты не робот

Alloc + init с синтезированным свойством - увеличивает ли счет удержания на два?

Я немного оценил следующий фрагмент:

В заголовке:

SomeClass *bla;
@property(nonatomic,retain) SomeClass *bla;

В файле реализации:

@synthesize bla;

а затем

self.bla = [[SomeClass alloc] init];

Я думаю, что это задание ставит счетчик "bla" на два; один раз через вызов alloc/init, затем через сохранение, которое мы попросили, чтобы произойти с помощью установщика синтезированных свойств.

В результате я обычно объявляю свои свойства следующим образом:

В заголовке:

SomeClass *_bla; // note the underscore
@property(nonatomic,retain) SomeClass *bla;

В файле реализации:

@synthesize bla = _bla;

а затем

_bla = [[SomeClass alloc] init];

Если мое первоначальное предположение верно - мне было бы интересно узнать, есть ли "правильный" способ сделать это, т.е. объявление, инициализация и управление памятью свойств?

4b9b3361

Ответ 1

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

Просто перейдите со второй формой, упомянутой в ваших инициализаторах:

_bla = [[SomeClass alloc] init];

... и не забудьте зафиксировать счет сохранения в противном случае, например:

self.bla = [[[SomeClass alloc] init] autorelease];

Ответ 2

Я думаю, что это задание ставит счетчик "bla" на два:

True.

Мне было бы интересно узнать, есть ли "правильный" способ сделать это

Ваша последняя часть кода - правильный путь, но главное подчеркивание не рекомендуется. Имущество и ивар могут иметь одно и то же имя. Просто

@interface Foo : Bar {
  SomeClass* bla;
}
@property (nonatomic, retain) SomeClass* bla;
@end

@implementation Foo
@synthesize bla;
-(id)init {
   ...
   bla = [[SomeClass alloc] init];
   ...
}
-(void)dealloc {
  [bla release];
  ...
  [super dealloc];
}

.


Некоторые люди могут использовать

SomeClass* foo = [[SomeClass alloc] init];
self.bla = foo;
[foo release];

или

self.bla = [[[SomeClass alloc] init] autorelease];

в методе -init, но я сильно препятствует, поскольку это вызывает ненужное множество методов и вы не можете гарантировать поведение setter.

Ответ 3

Похоже, основная проблема заключается в непонимании семантики владения объектами в Cocoa. Для каждого вызываемого объекта init, copy или retain требуется вызов release или autorelease. Что здесь происходит, так это то, что вызов init не имеет соответствующего вызова release или autorelease.

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

self.bla = [[SomeClass alloc] init];

- это не то же самое, что:

bla = [[SomeClass alloc] init];

Первый означает:

[self setBla: [[SomeClass] alloc] init]];

в то время как последнее буквально является назначением.

Чтобы исправить вашу проблему, вам действительно нужно убедиться, что код, вызывающий init, вызывает autorelease, так что счетчик сохранения будет уменьшаться после вызова retain установщиком.

Ответ 4

Нет двойного счета. Создатель, созданный путем синтеза, делает релиз перед выполнением сохранения. См. Класс Стэнфорд на объекте c класса 3, как указано на веб-сайте Apple. Также стоит отметить, что в случае iboutlets init init не требуется, поскольку он выполняется посредством загрузки xib файла