Но в ряде случаев (особенно при работе с GUI) самый простой или даже единственный способ получить желаемый результат - использовать Objective C классы (особенно классы из Cocoa Touch). Например, когда нужен вывод изображения на весь экран или рисование иконок в ячейках TableView.
Если рисовать что-либо в дополнительном потоке, то нередко происходят утечки памяти, которые не происходят с тем же кодом, который рисует в основном потоке программы.
Оказывается, всё дело в том, что основной поток изначально окружён 2-мя волшебными вызовами функций (см. функцию main):
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // первый волшебный вызов
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release]; // второй волшебный вызов
return retVal;
}
Так вот, каждый дополнительный поток как правило создаётся и поддерживается в непрерывно работающем состоянии в специальной функции, внутри которой происходит бесконечный цикл (ожидающий новых вызовов функций именно этого потока). Выглядит эта функция примерно так:
- (void)mainRoutine {
// Все autorelease-объекты, которые попадают в Autorelease пул
// получат автоматически сообщение release, как
// только они перестанут быть нужны:
NSAutoreleasePool *pool =
[[NSAutoreleasePool alloc] init];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
while (isThreadShouldBeRunning_)
{
[runLoop runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
}
[pool release];
}
Сегодня я узнал приятную вещь. Иногда бывает неудобно париться насчёт такой специальной функции. Оказывается, можно окружить этими 2-мя волшебными вызовами любую функцию, если только вы точно знаете, что она всегда будет вызываться в дополнительном потоке (и никогда в основном потоке). После этого утечки памяти прекратятся! Ура!
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // первый волшебный вызов сделайте в самом начале функции
[pool release]; // второй волшебный вызов сделайте в самом конце функции
Комментариев нет:
Отправить комментарий