У меня есть 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];
Если мое начальное предположение корректно - мне было бы интересно слышать, существует ли 'правильный' способ сделать это, т.е. объявление, инициализацию и управление памятью свойств?
Да, вы правы - использование синтезированного установщика свойства keep
увеличит счетчик ссылок на экземпляре, которым вы уже владеете (как alloc
] подразумевает владение).
Просто используйте вторую форму, которую вы упомянули в инициализаторах:
_bla = [[SomeClass alloc] init];
... и не забудьте исправить счетчик сохранения, например:
self.bla = [[[SomeClass alloc] init] autorelease];
Я думаю, что это присваивание увеличивает счетчик удержания для '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
, но я категорически не рекомендую это, так как это вызывает излишне много методов, и вы не может гарантировать поведение установщика .
Похоже, основная проблема здесь - неправильное понимание семантики владения объектами в Какао. Для каждого вызываемого объекта init
, copy
или keep
должен выполняться вызов release
или autorelease
. . Здесь происходит то, что вызов init
не имеет соответствующего вызова release
или autorelease
.
Я думаю, что сбивает с толку то, что точечная нотация для присвоения свойств является синтаксическим сахаром для вызова метода. Похоже, что это просто присвоение, тогда как на самом деле это вызов установщика свойств.
self.bla = [[SomeClass alloc] init];
- это не то же самое, что:
bla = [[SomeClass alloc] init];
Первое переводится как:
[self setBla: [[SomeClass] alloc] init]];
, в то время как последнее буквально означает задание.
Для решения проблемы все, что вам действительно нужно, - это убедиться, что код, вызывающий init
, вызывает autorelease
, чтобы счетчик сохраненных данных уменьшался после сохранения
вызов установщиком.