Свойства Objective-C и управление памятью - PullRequest
5 голосов
/ 19 февраля 2010

Учитывая следующее определение свойства:

@property (nonatomic,retain) MyObject* foo;

вызывает ли следующий код утечку памяти:

self.foo = [[MyObject alloc] init];

Похоже, что вызов alloc увеличивает счетчик сохранения для объекта до 1, а затем сохранение в установщике свойств увеличивает его до 1. Но так как начальный счетчик никогда не уменьшается до 0, объект будет задерживаться, даже когда self выпущен. Правильный ли этот анализ?

Если так, похоже, у меня есть две альтернативы:

self.foo = [[[MyObject alloc] init] autorelease];

, который не рекомендуется на iPhone по соображениям производительности или:

MyObject* x = [[MyObject alloc] init];
self.foo = x
[x release];

что немного громоздко. Есть ли другие альтернативы?

Ответы [ 3 ]

3 голосов
/ 19 февраля 2010

Самый простой способ управления сохраненным свойством на iPhone заключается в следующем (авто-релиз не так плох, как вы думаете, по крайней мере, для большинства случаев использования):

-(id)init {
    if (self = [super init]) {
        self.someObject = [[[Object alloc] init] autorelease];
    }
    return self;
}

-(void)dealloc {
    [someObject release];
    [super dealloc];
}

autorelease освобождает ссылку на плавающий экземпляр, который назначен на self.object, который сохраняет свою собственную ссылку, оставляя вам одну нужную ссылку (someObject). Затем, когда класс уничтожен, освобождается единственная оставшаяся ссылка, уничтожающая объект.

Как описано в другом ответе, вы также можете создавать одно или несколько сообщений «конструктора» для создания и автоматического освобождения объектов с необязательными параметрами.

+(Object)object;
+(Object)objectWithCount:(int)count;
+(Object)objectFromFile:(NSString *)path;

Можно определить это как:

// No need to release o if fails because its already autoreleased
+(Object)objectFromFile:(NSString *)path {
    Object *o = [[[Object alloc] init] autorelease];
    if (![o loadFromFile:path]) {
        return nil;
    }
    return o;
}
3 голосов
/ 19 февраля 2010

Есть ли альтернативы?

номер

Вы не сможете написать большую часть приложения для iPhone без использования автоматического выпуска, и библиотека Cocoa Touch использует их во многих местах. Поймите, что он делает (добавив указатель на список для удаления в следующем кадре) и избегайте его использования в тесных циклах.

Вы можете использовать метод класса в MyObject, который делает alloc / init / autorelease для вас, чтобы очистить его.

+ (MyObject *)object {
    return [[[MyObject alloc] init] autorelease];
}

self.foo = [MyObject object];
2 голосов
/ 19 февраля 2010

Вы правы, self.foo = [[MyObject alloc] init]; утечка памяти. Обе альтернативы верны и могут быть использованы. Что касается autorelease в таком утверждении: имейте в виду, что объект будет освобожден пулом автоматического выпуска, как только закончится текущий цикл выполнения, но, скорее всего, он будет сохраняться намного дольше self, поэтому проблема с пиками использования памяти здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...