Используя блоки пула автовыпуска

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

О блоках пула автовыпуска

Блок пула автовыпуска отмечен с помощью @autoreleasepool, как проиллюстрировано в следующем примере:

@autoreleasepool {
    // Code that creates autoreleased objects.
}

В конце блока пула автовыпуска, объекты, получившие autorelease сообщение в блоке отправляется a release сообщение — объект получает a release сообщение в течение каждого раза это было отправлено autorelease сообщение в блоке.

Как любой другой блок кода, могут быть вложены блоки пула автовыпуска:

@autoreleasepool {
    // . . .
    @autoreleasepool {
        // . . .
    }
    . . .
}

(Вы обычно не видели бы код точно как выше; обычно код в блоке пула автовыпуска в одном исходном файле вызвал бы код в другом исходном файле, содержащемся в другом блоке пула автовыпуска.) Для данного autorelease сообщение, соответствие release сообщение отправляется в конце блока пула автовыпуска в который autorelease сообщение было отправлено.

Какао всегда ожидает, что код будет выполнен в блоке пула автовыпуска, иначе автовыпустил объекты, не становятся выпущенными и Ваша память утечек приложения. (Если Вы отправляете autorelease сообщение за пределами блока пула автовыпуска, Какао регистрирует подходящее сообщение об ошибке.) AppKit и платформы UIKit обрабатывают каждую итерацию цикла событий (такую как мышь вниз событие или касание) в блоке пула автовыпуска. Поэтому Вы обычно не должны создавать пул автовыпуска, блокируют себя, или даже видят код, использующийся для создания того. Когда Вы могли бы использовать свои собственные блоки пула автовыпуска, существуют, однако, три случая:

Используйте локальные блоки пула автовыпуска для сокращения пикового объема потребляемой памяти

Много программ создают автовыпущенные временные объекты. Эти объекты добавляют к объему потребляемой памяти программы до конца блока. Во многих ситуациях позволяя временным объектам накопиться, пока конец текущей итерации цикла событий не приводит к чрезмерным издержкам; в некоторых ситуациях, однако, можно создать большое количество временных объектов, добавляющих существенно к объему потребляемой памяти и что Вы хотите избавиться более быстро. В этих последних случаях можно создать собственный блок пула автовыпуска. В конце блока выпущены временные объекты, который обычно приводит к их освобождению, таким образом, сокращающему объем потребляемой памяти программы.

Следующий пример показывает, как Вы могли бы использовать локальный блок пула автовыпуска в a for цикл.

NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {
 
    @autoreleasepool {
        NSError *error;
        NSString *fileContents = [NSString stringWithContentsOfURL:url
                                         encoding:NSUTF8StringEncoding error:&error];
        /* Process the string, creating and autoreleasing more objects. */
    }
}

for цикл обрабатывает один файл за один раз. Любой объект (такой как fileContents) отправленный autorelease сообщение в блоке пула автовыпуска выпущено в конце блока.

После блока пула автовыпуска необходимо расценить любой объект, автовыпущенный в блоке, как «избавлено». Не отправляйте сообщение в тот объект или возвращайте его invoker Вашего метода. Если необходимо использовать временный объект вне блока пула автовыпуска, можно сделать так путем отправки a retain обменивайтесь сообщениями к объекту в блоке и затем отправьте его autorelease после блока, как проиллюстрировано в этом примере:

– (id)findMatchingObject:(id)anObject {
 
    id match;
    while (match == nil) {
        @autoreleasepool {
 
            /* Do a search that creates a lot of temporary objects. */
            match = [self expensiveSearchForObject:anObject];
 
            if (match != nil) {
                [match retain]; /* Keep match around. */
            }
        }
    }
 
    return [match autorelease];   /* Let match go and return it. */
}

Отправка retain к match в автовыпуске пул блокируют и отправка autorelease к нему после того, как блок пула автовыпуска расширяет время жизни match и позволяет ему получать сообщения вне цикла и возвращаться к invoker findMatchingObject:.

Блоки пула автовыпуска и потоки

Каждый поток в приложении Какао поддерживает свой собственный штабель блоков пула автовыпуска. Если Вы пишете программу Только для основы или если Вы отсоединяете поток, необходимо создать собственный блок пула автовыпуска.

Если Ваше приложение или поток долгосрочны и потенциально генерируют много автовыпущенных объектов, необходимо использовать блоки пула автовыпуска (как AppKit, и UIKit делают на основном потоке); иначе, автовыпущенные объекты накапливаются, и Ваш объем потребляемой памяти растет. Если Ваш отдельный поток не выполняет вызовы Какао, Вы не должны использовать блок пула автовыпуска.