выделение + init с синтезируемым свойством - делает оно вызывает, сохраняют количество для увеличения на два?

У меня есть seeen следующий отрывок вполне немного:

В заголовке:

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

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

@synthesize bla;

и затем

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

Я думаю, что это присвоение помещает сохранить счет 'bla' два; однажды через вызов alloc/init, затем посредством сохранения этого мы попросили происходить через синтезируемый метод set свойства.

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

В заголовке:

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

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

@synthesize bla = _bla;

и затем

_bla = [[SomeClass alloc] init];

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

17
задан patschiboy 16 July 2010 в 06:56
поделиться

3 ответа

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

Просто используйте вторую форму, которую вы упомянули в инициализаторах:

_bla = [[SomeClass alloc] init];

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

self.bla = [[[SomeClass alloc] init] autorelease];
8
ответ дан 30 November 2019 в 14:11
поделиться

Я думаю, что это присваивание увеличивает счетчик удержания для 'bla' на два;

True.

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

Ваш последний фрагмент кода правильный, но не рекомендуется использовать начальное подчеркивание. Свойство и ivar могут иметь одно и то же имя. Достаточно

@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 , но я категорически не рекомендую это, так как это вызывает излишне много методов, и вы не может гарантировать поведение установщика .

8
ответ дан 30 November 2019 в 14:11
поделиться

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

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

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

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

bla = [[SomeClass alloc] init];

Первое переводится как:

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

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

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

3
ответ дан 30 November 2019 в 14:11
поделиться