Ответ 1
Каждая программа запускается, по крайней мере, в одном потоке. Вы можете думать о каждом потоке как о отдельном процессе выполнения программы, каждый из которых выполняется параллельно другим.
Если у вас есть какой-то пользовательский интерфейс или другой код, который должен прослушивать события (например, сетевые порты), вам нужен цикл выполнения. Каждый NSThread автоматически получает свой собственный цикл запуска, и вам очень редко приходится беспокоиться о них непосредственно. Запуск цикла также отвечает за создание и освобождение пулов автоопределения.
[EDIT: см. комментарии для более подробного обсуждения пулов авторефератов. Самый важный момент, который следует иметь в виду, это то, что новые потоки должны заботиться о создании пула автозапуска. Например, методы, вызываемые с помощью detachNewThreadSelector (см. Ниже), должны иметь следующие строки в качестве их первой и последней строк:
NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ];
[code here]
[pool release];
То же самое относится к потокам, созданным с использованием других методов.]
В основном потоке, где происходит обработка UI, цикл цикла очень важен, поскольку он поддерживает взаимодействие интерфейса. Вот почему вы никогда не должны запускать код, занимающий много времени в основном потоке: он будет все время тратиться на поток, и цикл выполнения не будет работать достаточно часто, что приведет к блокированному или медленному интерфейсу. Если вам нужно выполнить трудоемкие вычисления или сохранить задание в фоновом режиме, вы должны создать новый поток. Опять же, вам, вероятно, не нужно думать о создании нового цикла цикла. Простой способ выполнения метода в новом потоке:
[NSThread detachNewThreadSelector:@selector(theSelector) toTarget:self withObject:nil];
Связь между потоками может быть сложной, и вы должны знать о методах performSelector:onThread:withObject:waitUntilDone:
и performSelectorOnMainThread:withObject:waitUntilDone:
(Великие советы по отправке NSNotifications по потокам здесь.)
Таймеры также обрабатываются циклами запуска. В отличие от циклов запуска, вы, вероятно, часто используете таймеры непосредственно в своей программе. Самый простой способ создания таймера:
[self performSelector:@selector(aSelector) withObject:nil afterDelay:1.0];
но иногда вы хотите сами создавать и управлять объектами NSTimer, например, чтобы отменить и повторно использовать таймер.
NSTask используется для запуска другой программы в качестве подпроцесса текущего. Это немного похоже на запуск отдельного потока, но если сбой подпроцесса, ваша основная программа будет работать. Связь между программами также очень отличается от связи между несколькими потоками в одном и том же процессе.
Вы отметили свой вопрос с помощью "iphone", и на iPhone вы никогда не будете использовать NSTasks.
NSOperations используются, когда вам нужно обрабатывать большее количество различных задач, помещая их в очереди и/или обрабатывая их в отдельных потоках (хотя они не должны запускаться в отдельных потоках), Если вашему приложению нужно создать только несколько специализированных потоков, то нет причин использовать класс NSOperation. Но если вы будете регулярно создавать задачи (например, общаться с сервером), которые должны отслеживаться, NSOperation и NSOperationQueue пригодится.