it-swarm-ru.tech

Как работает пул автозапуска NSAutoreleasePool?

Насколько я понимаю, все, что создано с помощью alloc , new или copy , должно быть выпущено вручную. Например:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

Мой вопрос, однако, разве это не было бы так же верно?

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}
94
James Sumners

Да, ваш второй фрагмент кода полностью действителен.

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

Автозапуск пулов - это просто удобство, которое позволяет отложить отправку -релизов до «позже». Это «позднее» может произойти в нескольких местах, но наиболее распространенным в приложениях GUI Cocoa является конец текущего цикла цикла выполнения.

65
kperryua

NSAutoreleasePool: сток против выпуска

Поскольку функции drain и release, по-видимому, вызывают путаницу, здесь, возможно, стоит пояснить (хотя это описано в документации ...).

Строго говоря, с точки зрения общей картины drainне эквивалентен release:

В среде с подсчетом ссылок drain выполняет те же операции, что и release, поэтому оба в этом смысле эквивалентны. Подчеркнем, это означает, что вы не пропускаете пул, если используете drain, а не release.

В среде сборки мусора release не используется. Таким образом, это не имеет никакого эффекта. drain, с другой стороны, содержит подсказку сборщику, что он должен «собирать при необходимости». Таким образом, в среде сбора мусора использование drain помогает системному сбору баланса.

37
mmalc

Как уже указывалось, ваш второй фрагмент кода правильный.

Я хотел бы предложить более краткий способ использования пула автоматического выпуска, который работает во всех средах (подсчет ссылок, GC, ARC), а также избегает путаницы утечки/выпуска:

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

В приведенном выше примере обратите внимание на блок @autoreleasepool. Это задокументировано здесь .

17
Neovibrant

Нет ты ошибаешься. В документации четко указано, что при не-GC -drain эквивалентен -release, что означает, что NSAutoreleasePool будет не протекать.

7
kperryua

Я обнаружил, что эта ссылка дала лучшее объяснение того, когда и как использовать NSAutoReleasePool: AutoReleasePool

1
Wayne Lo

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

0
Hardik Mamtora

да, ваш код идеален, если вы будете использовать сборщик мусора, этого будет достаточно просто установить строку в ноль, когда вы закончите с ней. Сборка мусора плохо влияет на производительность вашего приложения, поэтому я бы не рекомендовал его использовать: P

0
Antwan van Houdt

Что я прочитал от Apple: "В конце блока пула автоматического выпуска, объектам, которые получили сообщение автоматического выпуска в блоке, отправляется сообщение освобождения - объект получает сообщение освобождения каждый раз, когда ему было отправлено сообщение автоматического выпуска в пределах блок."

https://developer.Apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

0
Gagan_iOS