Таймер - это быстрый мост NSTimer, который восходит к NeXTSTEP, задолго до появления Grand Central Dispatch (GCD) и таких вещей, как DispatchSourceTimer, который появился только до 10.6 (в форме dispatch_source_set_timer) и dispatchAfter (в форме dispatch_after).
NSTimer основан на цикле выполнения, который был основным способом параллелизма до GCD.Это кооперативная система параллелизма, предназначенная для запуска в одном потоке на одном ядре (хотя она может быть расширена до многопоточных сред).
Хотя цикл выполнения все еще очень важен в Какао, онбольше не является основным или даже предпочтительным способом управления параллелизмом.Начиная с 10.6, GCD становится все более предпочтительным подходом (хотя добавление API NSTimer на основе блоков в таймфрейме 10.12 было желанной модернизацией).
В масштабе 15 секунд различия в эффективности довольно несущественны.Тем не менее, я не понимаю ваш комментарий «Таймер удерживает процессор от перехода в состояние ожидания».Я не верю, что это правда.Процессор определенно все еще будет переходить в состояние ожидания при ожидании срабатывания NSTimer.
Я бы не устанавливал цикл запуска только для запуска NSTimer.Вам было бы намного лучше запланировать это в главном цикле выполнения, а затем использовать DispatchQueue.async
для выполнения фактической работы в какой-то другой очереди.
Как правило, я использую инструмент самого высокого уровня, который удовлетворяет потребности,Это те, которые Apple, вероятно, оптимизирует лучше всего со временем, когда я внесу наименьшее количество изменений.Например, даты пожара NSTimer автоматически корректируются для повышения энергоэффективности.С DispatchSourceTimer вы получаете контроль над параметром leeway
, чтобы получить то же преимущество, но вы можете установить его (по умолчанию - ноль, что оказывает наименьшее влияние на энергию).Конечно, верно и обратное.DispatchSourceTimer является самым низким уровнем и дает вам максимальный контроль, поэтому, если это то, что вам нужно, это тот, который нужно использовать.
Для вашего примера я лично, вероятно, использовал бы Таймер и просто отправлял бы в частную очередькак часть блока.Но DispatchSourceTimer был бы полностью уместен.
asyncAfter - это действительно другая вещь, так как это всегда один выстрел.Это замечательно, если вы хотите один выстрел, но он меняет вещи, если вы хотите повторить.Если вы просто вызовете asyncAfter в блоке, чтобы повторить, это будет через 15 секунд после того, как вы в последний раз закончили, вместо того, чтобы быть разнесенными на 15 секунд.Первый будет иметь тенденцию дрейфовать немного позже со временемВопрос в следующем: если по какой-то причине ваша задача заняла 5 секунд, вы бы хотели, чтобы следующий пожар произошел через 15 секунд после его окончания, или вы хотите, чтобы между каждым событием пожара оставались постоянные 15 секунд?Ваш выбор там определит, какой инструмент правильный.
В качестве небольшого примечания, события NSTimer всегда немного позже, чем они запланированы.Мероприятия GCD с задержкой могут быть немного раньше или немного позже.С практической точки зрения, нет такой вещи, как «вовремя» (это период нулевой длины; вы не собираетесь его ударить).Таким образом, вопрос всегда в том, обещали ли вы опоздать, как NSTimer, или вы можете быть рано, как GCD с задержкой.