Документация CFRunLoopRun
сообщает нам:
Цикл выполнения текущего потока выполняется в режиме по умолчанию (см. Режим цикла выполнения по умолчанию) до тех пор, пока цикл выполнения не будет остановлен с помощью CFRunLoopStop
или пока все источники и таймеры не будут удалены из режима цикла выполнения по умолчанию.
Но документация run
не содержит ссылок на это. Это говорит:
Если входные источники или таймеры не подключены к циклу выполнения, этот метод завершается немедленно; в противном случае он запускает приемник в NSDefaultRunLoopMode
, повторно вызывая runMode:beforeDate:
. Другими словами, этот метод эффективно запускает бесконечный цикл, который обрабатывает данные из входных источников и таймеров цикла выполнения.
Но он продолжает предупреждать:
Удаление всех известных входных источников и таймеров из цикла выполнения вручную не гарантирует выхода из цикла выполнения. macOS может устанавливать и удалять дополнительные источники ввода для обработки запросов, направленных на поток получателя. Поэтому эти источники могут препятствовать выходу из цикла выполнения.
Если вы хотите завершить цикл выполнения, вы не должны использовать этот метод. Вместо этого используйте один из других методов выполнения, а также проверьте другие произвольные условия в цикле. Простой пример:
BOOL shouldKeepRunning = YES; // global
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
где shouldKeepRunning
установлен в NO
где-то еще в программе.
Я также предлагаю вам обратиться к Руководство по программированию потоков: Завершение потока .
Вы спрашиваете:
Код, похоже, намеревается показать правильный способ выхода из потока. Практично ли это в реальной жизни?
Нет, мы редко пишем собственный код NSThread
. Grand Central Dispatch (GCD) устранил все эти неприятности. Он более эффективен (потому что он имеет пул рабочих потоков, готовых к работе, не требует циклического вращения или NSRunLoop
для каждого потока и т. Д.) И намного, намного проще для написания кода. Я бы не советовал писать код NSThread
, если нет какой-то очень специфической проблемы, которую трудно решить с помощью GCD.
Кстати, обратите внимание, что когда вы пишете NSThread
код, вам действительно нужно, чтобы ваш поток настроил свой собственный пул автоматического выпуска (хотя мы использовали бы @autoreleasepool { ... }
вместо шаблона, описанного в это руководство). Например:
- (void)runThread {
@autoreleasepool {
...
}
}
Если вы используете GCD, это управление памятью позаботится о вас.
Если вам нужна дополнительная информация о NSThread
, NSRunLoop
и т. Д., См. Руководство по программированию потоков . Или избавьте себя от боли и просто используйте GCD .