2015-12-09 2 views
2

Я купил «Путеводитель по Большому Nerd Ranch» для Objective-C, и есть что-то около NSRunLoop. Я не могу понять.Зачем нужен NSRunLoop для запуска таймера?

Вот кусок кода из книги:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 
                target:logger 
               selector:@selector(updateLastTime:) 
               userInfo:nil 
               repeats:YES]; 
[[NSRunLoop currentRunLoop] run]; 

Мой вопрос, почему мне нужно положить NSRunLoop для NSTimer обрабатываемого объекта? И почему он должен быть в конце, а не в начале?

Почему это не похоже на другие функции или методы объекта, где мне просто нужно вызвать функцию для ее обработки и входа в консоль?

Я действительно пытаюсь выяснить каждую логику каждой детали здесь.

+1

Это может быть полезно: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html – quellish

ответ

3

С ранних дней становления Какао, когда динозавры бродили по Земле, скалы были мягкими, а рабочие станции NeXT были новыми, вплоть до выхода 10.6, наиболее распространенным типом многозадачности был цикл цикла. Это совместная многозадачность. Нет нитей. Нет упреждающего планировщика или ядра. Нет переключателей контекста. Есть только большой цикл цикла, в котором говорится: «Что нужно делать сейчас?» и запускает его. И когда эта вещь завершается, она ждет следующего, что нужно делать и запускает это. Это буквально большая петля while(true). Ну, технически строка кода:

for (;;) { ... } 

Вы можете посмотреть на себя в CFRunLoop.c. Ищите __CFRunLoopRun.

NSTimer был изобретен в те дни. Все, что он делает, делает заметку в runloop, говоря ей, «когда это время пройдет, тогда, пожалуйста, сделайте это». (Это немного сложнее, потому что он использует порты mach, ищите __CFRunLoopTimerSchedule в этом же файле, но в основном это идея.)

Итак, дело в том, что нет волшебства. Есть только большой цикл for(;;), который обрабатывает этот материал. Что-то должно его запустить. И когда вы начинаете (с run), он не возвращается. Это бесконечный цикл. Нет «фона». Других потоков нет. Вот почему вам нужно делать все в порядке, о котором говорит вам BNR. В противном случае ваша следующая строка кода не будет работать.

Конечно, в приложениях iOS и приложениях с графическим интерфейсом OS X вы обычно не должны делать это самостоятельно. Запуск цикла создается для вас во время запуска программы, и весь основной поток живет внутри него. Это то, что звонит вам большую часть времени. Вы не называете это. Но если вы используете нить, отличную от основного потока, и хотите использовать функции цикла выполнения, вам придется запускать ее самостоятельно.

Сегодня многие вещи выполняются с помощью GCD, а не для запуска циклов. Это «до 10.6 вышел», о котором я упоминал. Это действительно изменило мир какао. Но огромное количество Cocoa по-прежнему зависит от цикла запуска, и это все еще рабочая лошадка большинства приложений, даже если вы никогда не задумываетесь об этом.

В большинстве случаев сегодня, если вам нужно создать runloop для использования NSTimer, вы не должны использовать NSTimer. Просто используйте dispatch_after. Фактически, это то, что я обычно рекомендую большую часть времени сегодня, даже если у вас do есть runloop.

(И вы обязательно должны прочитать ссылку @quelish в комментариях. Это окончательное слово для циклов запуска.)

+0

блестящий ответ – Astoria

+0

Хороший ответ. Разве основная очередь GCD не запланирована с цикла запуска? Таким образом, цикл запуска по-прежнему является основополагающим постулатом 10.6. – CRD

+0

@CRD Это абсолютно фундаментально. «Это все еще рабочая лошадка большинства приложений, даже если вы никогда не задумываетесь об этом». Но в большинстве случаев GCD - лучшее решение на уровне приложения. И гораздо более дружелюбный к Свифт. –