runloop swift что это такое

Таймер в iOS

Представьте, что вы работаете над приложением, в котором нужно периодически выполнять некоторые действия. Именно для этого в Swift используется класс Timer.

Timer используется для планирования действий в приложении. Это может быть разовое действие или повторяющаяся процедура.

В этом руководстве вы разберётесь, как в iOS работает таймер, как он может влиять на отзывчивость UI, как оптимизировать потребление батареи при использовании таймера и как использовать CADisplayLink для анимации.

В качестве тестового полигона мы будем использовать приложение — примитивный планировщик задач.

Начинаем

Загрузите исходный проект. Откройте его в Xcode, посмотрите его структуру, скомпилируйте и выполните. Вы увидите простейший планировщик задач:

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Добавим в него новую задачу. Тапните на значке +, введите название задачи, тапните Ok.

В добавленных задачах есть метка времени. Новая задача, которую вы только что создали, отмечена нулём секунд. Как видите, это значение не увеличивается.

Каждую задачу можно отметить как выполненную. Тапните на задаче. Название задачи станет перечеркнутым и она будет помечена как выполненная.

Создаём наш первый таймер

Создадим главный таймер нашего приложения. Класс Timer, известный также как NSTimer — удобный способ запланировать действие на определённый момент, как разовое, так и периодическое.

Откройте TaskListViewController.swift и добавьте в TaskListViewController эту переменную:

Затем там же добавьте экстеншн:

И вставьте этот код в экстеншн:

Запустите приложение и создайте пару новых задач. Вы увидите, что метка времени у каждой задачи меняется каждую секунду.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Добавляем допуск к таймеру

Увеличение количества таймеров приводит к худшей отзывчивости UI и большему потреблению батареи. Каждый таймер пытается исполниться точно в отведённое ему время, так как по умолчанию его допуск (tolerance) равен нулю.

Добавление допуска таймера — простой способ снизить потребление энергии. Это позволяет системе выполнить действие таймера между назначенным временем и назначенным временем плюс время допуска — но никогда не ранее назначенного интервала.

Для таймеров, которые выполняются лишь однажды, значение допуска игнорируется.

В методе createTimer(), сразу за присвоением timer, добавьте эту строчку:

Запустите приложение. В этом конкретном случае эффект будет неочевиден (у нас только один таймер), однако в реальной ситуации нескольких таймеров ваши пользователи получат более отзывчивый интерфейс и приложение будет более энергоэффективным.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Таймеры в бэкграунде

Интересно, а что происходит с таймерами, когда приложение уходит в бэкграунд? Чтобы разобраться с этим, добавим этот код в самом начале метода updateTimer():

Это позволит нам отследить события таймера в консоли.

Запустите приложение, добавьте задачу. Теперь нажмите на вашем устройстве кнопку Home, а затем вернитесь к нашему приложению.

В консоли вы увидите что-то вроде этого:

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Как видите, когда приложение уходит в бэкграунд, iOS приостанавливает все работающие таймеры приложения. Когда же приложение становится активным, iOS возобновляет таймеры.

Разбираемся с циклами выполнения (Run Loops)

Цикл выполнения — это цикл обработки событий, который планирует работу и занимается обработкой входящих событий. Цикл держит поток занятым, пока он работает и переводит его в «спящее» состояние, когда работы для него нет.

Каждый раз, когда вы запускаете приложение, система создаёт главный поток приложения, у каждого потока есть автоматически созданный для него цикл выполнения.

Но почему вся эта информация важна для вас сейчас? Сейчас каждый таймер запускается в главном потоке и присоединяется к циклу выполнения. Вероятно, вы в курсе, что главный поток занимается отрисовкой пользовательского интерфейса, обработкой касаний и так далее. Если главный поток чем-то занят, интерфейс вашего приложения может стать «неотзывчивым» (подвисать).

Вы обратили внимание, что временна́я метка в ячейке не обновляется, когда вы тяните table view?

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Решить эту проблему можно, указав циклу выполнения запускать таймеры в другом режиме.

Разбираемся с режимами цикла выполнения

Режим цикла выполнения — это набор источников ввода, таких, как касания экрана или клики мышкой, за которыми может быть установлено наблюдение и набор «наблюдателей», получающих уведомления.

В iOS есть три режима цикла выполнения:

default: обрабатываются источники ввода, которые не являются NSConnectionObjects.
common: обрабатывается набор циклов ввода, для которых вы можете определить набор источников ввода, таймеров, «наблюдателей».
tracking: обрабатывается UI приложения.

Для нашего приложения наиболее подходящим выглядит режим common. Чтобы использовать его, замените содержимое метода createTimer() следующим:

Главное отличие от предыдущего кода состоит в том, что мы перед присваиванием таймера TaskListViewController‘а добавляем этот таймер в цикл выполнения в режиме common.

Скомпилируйте и запустите приложение.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Теперь временны́е метки ячеек обновляются даже в случае скроллинга таблицы.

Добавляем анимацию на выполнение всех задач

Теперь добавим поздравительную анимацию на выполнение пользователем всех задач — шарик будет подниматься снизу экрана до самого верха.

Добавьте эти переменные в начале TaskListViewController:

Назначение этих переменных:

Здесь мы делаем следующее:

Теперь updateAnimation() вызывается всякий раз при событии таймера.

Ура, мы только что создали анимацию. Однако, при запуске приложения не происходит ничего нового…

Показываем анимацию

Как вы, наверно, догадались, нет ничего, чтобы «запустило» нашу новую анимацию. Чтобы сделать это, нам нужен еще один метод. Добавим этот код в экстеншн анимации TaskListViewController:

Этот метод мы будем вызывать всякий раз, когда пользователь отметит задачу выполненной, он проверяет, все ли задачи выполнены. Если да, то он вызовет showCongratulationAnimation().

В заключение, добавим вызов этого метода в конце tableView(_:didSelectRowAt:):

Запустите приложение, создайте пару задач, отметьте их как выполненные — и вы увидите нашу анимацию!

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Останавливаем таймер

Если вы посмотрите в консоль, вы увидите, что, хотя пользователь отметил все задачи выполненными, таймер продолжает работу. Это совершенно бессмысленно, так что имеет смысл остановить таймер, когда он не нужен.

Сначала создадим новый метод для остановки таймера:

Это обновит таймер и сбросит его в nil, чтобы мы могли правильно его создать вновь позже. invalidate() — это единственный способ удалить Timer из цикла выполнения. Цикл выполнения удалит сильную ссылку на таймер или непосредственно после вызова invalidate() или чуть позже.

Теперь заменим метод showCongratulationsIfNeeded() следующим образом:

Теперь, если пользователь выполнит все задачи, приложение сначала сбросит таймер, а затем покажет анимацию, в противном случае оно попытается создать новый таймер, если его еще нет.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Теперь таймер останавливается и рестартует, как надо.

CADisplayLink для плавной анимации

Timer — неидеальный выбор для управления анимацией. Вы могли заметить пропуск нескольких кадров анимации, особенно, если вы запускаете приложение в симуляторе.

Мы установили таймер на частоту 60Hz. Таким образом, таймер обновляет анимацию каждые 16 мс. Рассмотрим ситуацию внимательнее:

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

При использовании Timer мы не знаем точное время запуска действия. Это может случиться или в начале или в конце кадра. Скажем, таймер выполнится в середине каждого кадра (голубые точки на рисунке). Единственно, что мы знаем наверняка, что вызов будет каждые 16 мс.

Теперь у нас только 8 мс, чтобы исполнить анимацию, и этого может быть недостаточно для нашей анимации. Посмотрим на второй кадр на рисунке. Второй кадр не сможет быть выполнен за отведенное ему время, так что приложение сбросит второй кадр анимации.

Нам поможет CADisplayLink

CADisplayLink вызывается один раз за кадр и пытается синхронизовать реальные кадры анимации, насколько это возможно. Теперь в вашем распоряжении будут все 16 мс и iOS не сбросит ни единого кадра.

Чтобы использовать CADisplayLink, вам нужно заменить animationTimer на новый тип.

Вы заменили Timer на CADisplayLink. CADisplayLink — это представление таймера, который привязан к вертикальной развёртке дисплея. Это означает, что GPU устройства приостановит работу, пока экран не сможет дальше обрабатывать команды GPU. Таким образом мы получаем плавную анимацию.

Вы заменили TimeInterval на CFTimeInterval, что необходимо для работы с CADisplayLink.

Замените текст метода showCongratulationAnimation() на этот:

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое
Прекрасно! Мы успешно заменили анимацию, основанную на Timer, на более подходящий CADisplayLink — и получили анимацию более плавную, без рывков.

Источник

Русские Блоги

RunLoop в iOS

RunLoop в iOS

Что такое RunLoop

Буквально это бегущий цикл. Наша общая программа состоит в том, чтобы выполнить поток, который является прямой линией. Есть начальная и конечная точки. Runloop всегда рисует круг на потоке, пробегает круг и постоянно обнаруживает некоторые круги. События щелчков, таймеры и т. Д. Запускают выполнение после обнаружения, снова переводят в спящий режим после выполнения, а затем обнаруживают во время режима сна, если он не отключен, он всегда будет работать, в противном случае он продолжит цикл. Внутренняя структура представляет собой цикл do-while, в котором непрерывно обрабатываются различные задачи (такие как таймер, источник и Observer).

Основная роль RunLoop

RunLoop и потоки

Как видно из приведенного выше кода, существует взаимно-однозначное соответствие между потоками и RunLoop, и отношение сохраняется в глобальном словаре. Когда поток только что был создан, RunLoop не было, если вы не извлекаете его активно, он никогда не будет там. Создание RunLoop происходит при первом получении, а уничтожение RunLoop происходит в конце потока. Вы можете получить его RunLoop только внутри потока (кроме основного потока).

Примечание: инициализация NSRunLoop не требует alloc, нужно только вызвать [NSRunLoop currentRunLoop] в этом потоке,

RunLoop и связанные классы

(В основном для 5 классов RunLoop в Core Foundation)

Класс CFRunLoopModeRef не предоставляется извне, но инкапсулируется через интерфейс CFRunLoopRef. Их отношения таковы:
runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

CFRunLoopModeRef

CFRunLoopModeRef представляет режим запуска RunLoop. Именно потому, что у runloop есть источники, таймеры и наблюдатели, runloop всегда может работать. Без них runloop будет напрямую выходить из цикла.

RunLoop содержит несколько режимов, и каждый режим содержит несколько источников / таймеров / наблюдателей

При каждом запуске RunLoop может быть указан только один из них. Этот режим называется CurrentMode

Если вам нужно переключить режим, вы можете только выйти из цикла и указать новый режим для входа в цикл.

Каждый режим может установить свой собственный источник / таймер / наблюдатель, чтобы он не влиял друг на друга

5 режимов зарегистрированы по умолчанию (Apple открыла только первые два)

kCFRunLoopDefaultMode: режим приложения по умолчанию, обычно основной поток работает в этом режиме.

UITrackingRunLoopMode: режим отслеживания интерфейса, используемый для ScrollerView для отслеживания касания и скольжения, чтобы гарантировать, что другие интерфейсы не будут влиять на интерфейс при скольжении.

UIInitalizaationRunLoopMode: первый режим, введенный при запуске приложения, больше не будет использоваться после запуска

GSEventReceiveRunLoopMode: принимает внутренний режим (отрисовка чертежа и т. Д.) Системных событий, обычно не используемых

kCFRunLoopCommonModes: это режим заполнителя, а не реальный режим

CFRunLoopTimerRef

CFRunLoopSourceRef

CFRunLoopObserverRef

Если вы добавите Observer в runloop, вы можете использовать только функции CF, обычно используемые для перехвата системных событий и т. Д.

Логика обработки RunLoop

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое
Что касается памяти runloop, в runloop runloop будет соответствовать потоку, а пул автоматического выпуска предназначен для некоторых объектов текущего потока, он будет освобожден один раз перед kCFRunLoopBeforeWaiting и в следующий раз Он будет воссоздан при запуске,

Варианты использования RunLoop в разработке

1, запустить резидентный поток (чтобы дочерний поток не входил в мертвое состояние, ожидал сообщений от других потоков, обрабатывал события)

2, может заставить определенные события выполняться в определенном режиме

Если изображение, загруженное из Интернета, отображается в UIScrollView или UITableView, пользовательский интерфейс иногда зависает при скольжении экрана. Вы можете использовать runloop для решения этой проблемы.

Источник

Русские Блоги

Подробное объяснение и практика iOS RunLoop

оглавление

-Концепция RunLoop

-RunLoop логика и реализация

-RunLoop используется в iOS

-RunLoop практика

-Концепция RunLoop

В документации Apple RunLoop определяется следующим образом:

Run loops are part of the fundamental infrastructure associated with threads.
A run loop is an event processing loop that you use to schedule work and coordinate the receipt of incoming events. The purpose of a run loop is to keep your thread busy when there is work to do and put your thread to sleep when there is none.

RunLoop Основная функция, связанная с потоками, RunLoop Он используется для планирования работы и координации цикла обработки событий, который принимает входящие события. RunLoop Цель состоит в том, чтобы позволить потоку работать, когда есть задача, и спать, когда нет задачи для обработки.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Работающий цикл получает события из двух разных типов источников. Источник ввода доставляет асинхронные события, обычно сообщения из другого потока или из другого приложения. Событие синхронизации, предоставляемое источником синхронизации, которое происходит в заранее определенное время или интервал повторения. Оба типа источников используют процедуры обработки, зависящие от приложения, когда они прибывают для обработки события.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

-RunLoop логика и реализация

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

CFRunLoopTimerRef Это триггер на основе времени, который можно смешивать с NSTimer, включая длину времени и обратный вызов, добавить
Когда RunLoop, RunLoop зарегистрирует соответствующую точку времени, когда точка времени, RunLoop будет активирован для выполнения этого обратного вызова

CFRunLoopObserverRef Наблюдатель, каждый Observer Оба включают обратный вызов (указатель на функцию). Когда состояние RunLoop изменяется, наблюдатель может получить это изменение через обратный вызов. Моменты времени, которые можно наблюдать, следующие:

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

-RunLoop используется в iOS

Роль Run Loop
1. Продолжайте работу программы и примите ввод пользователя.
2. Решите, когда программа должна обрабатывать эти события.
3. Разделение вызовов (очередь сообщений)
4. Экономьте процессорное время.

Когда звонить
1. Использовать порт port Или настраиваемый источник ввода input sources Общайтесь с другими темами
2. Используйте таймер потока timer
3. Используйте любой метод performSelector в Какао.
4. Поток выполняет периодические задачи.

Сценарии приложения RunLoop
AutoreleasePool

Вызов стека среды выполнения приложения основного потока

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

При запуске программы Apple находится в основном потоке RunLoop Добавлены два Observer Для мониторинга RunLoop из kCFRunLoopEntry (Вызвать) и BeforeWating (Готов спать)

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

GCD
GCD и RunLoop Часть реализации использует друг друга, RunLoop из timer Используется dispatch_source_t Достигнуто, а GCD dispatch_async() Также используется RunLoop
При звонке dispatch_async(dispatch_get_main_queue(), block) Время, dispatch Основной поток RunLoop Послать сообщение, RunLoop Буду разбужен и получу от сообщения block Отправить обратный звонок

Сетевой запрос
основан на CFNetwork из NSURLConnection Инициирован NSURLConnectionLoader В потоке цикл выполнения основан на mach port из Source0 Получите из нижнего слоя CFSocket Обратите внимание, просыпайтесь одновременно delegate с участием RunLoop Для обработки этих уведомлений.
Используется ответ на событие __IOHIDEventSystemClientQueueCallback()
Используется распознавание жестов _UIGestureRecognizerUpdateObserver()
Используется обновление интерфейса _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()
и т. д.

Практика RunLoop

// RunLoop-Поддержание жизненного цикла потока, чтобы поток не выходил автоматически, завершаемся, когда isFinished имеет значение Yes. Перед запуском RunLoop необходимо добавить отслеживаемый порт или источники событий источника ввода или таймер событий источника синхронизации, в противном случае вызов [runloop run] вернется напрямую, не входя в цикл, чтобы позволить потоку остаться. Если событие источника ввода или событие таймера не добавлено, поток всегда будет бездействовать в бесконечном цикле, всегда будет занимать срез времени ЦП, и разумное распределение ресурсов не будет реализовано. Если цикла while нет и к потоку не добавлен источник ввода или таймер, поток завершится напрямую и будет повторно использован системой.

// Новая идея tableView задержки загрузки изображений

// RunLoop-NSTimer работает в разных режимах

// RunLoop-NSTimer создает таймер в потоке

// RunLoop-RunLoop используется в RCTWebSocket в среде ReactNative

// AFURLRequestSerilization RunLoop AFNetWorking

// AFURLConnectionOperationRunLoop использовал резидентные потоки в предыдущих версиях AFNetworking

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Релевантная информация:
Официальные документы Справочник по классам NSRunLoop, Справочник по CFRunLoop.
Код CFRunLoopRef:Открытый источникДа вы можете здесьhttp://opensource.apple.com/tarballs/CF/ Загрузите исходный код всего CoreFoundation для просмотра.

Быстрая версия кроссплатформенного CoreFoundation:https://github.com/apple/swift-corelibs-foundation/, Исходный код этой версии может немного отличаться от реализации в существующей системе iOS, но ее легче компилировать, и она адаптирована для Linux / Windows.

Интеллектуальная рекомендация

Запись шага операции Git

Возьмите любое число из массива и суммируйте до решения указанного значения (JavaScript)

По заданному массиву [1,2,3,4,5,6,7,8,9,10] найдите любую комбинацию массивов, сумма которых равна 10. Обратите внимание, что одно число в каждой комбинации может появляться только один раз. Массив им.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Реализация основного боевого проекта Vue-cli 8 main layout

Каталог статей Предыдущая глава Реализация основного макета Базовая реализация Слева прокрутите Украсьте полосу прокрутки Полный код Следующая глава Предыдущая глава Vue-cli Actual Combat Project 7 от.

runloop swift что это такое. Смотреть фото runloop swift что это такое. Смотреть картинку runloop swift что это такое. Картинка про runloop swift что это такое. Фото runloop swift что это такое

Предварительная обработка данных: переменная проверка и преобразование

Переменная проверка и преобразование Мы столкнемся с проблемой фильтрации переменных при обработке данных. Здесь мы либо PCA (анализ основных компонентов), либо простая фильтрация искусственных переме.

Источник

Русские Блоги

iOS: углубленное изучение RunLoop

Определение и понятие RunLoop

Основная функция RunLoop

RunLoop в основной функции

Связь между RunLoop и потоками

Типы сообщений RunLoop

Внешний интерфейс RunLoop

Внутренняя логика RunLoop

Внутреннее приложение RunLoop в iOS

Практика RunLoop в iOS-разработке

Определение и понятие RunLoop

Основная функция RunLoop

RunLoop в основной функции

Связь между RunLoop и потоками

In Core Foundation

CFRunLoopRef с участием NSRunLoop Может трансформироваться, NSRunLoop Использовать getCFRunLoop Метод может получить CFRunLoopRef Объект

Типы сообщений RunLoop

Это изображение официального документа Apple, показывающее типы новостей Runloop.

Я не особо разбирался в этой картинке, она в основном говорит о двух источниках ввода Runloop. Объяснение официального документа

Внешний интерфейс RunLoop

Режим RunLoop

По умолчанию в системе прописано 5 режимов:

Наши основные режимы приложения: kCFRunLoopDefaultMode с участием UITrackingRunLoopMode Два, из которых kCFRunLoopDefaultMode (также называемый NSDefaultRunLoopMode в какао) Это режим по умолчанию, когда мы запускаем цикл выполнения. Пока UITrackingRunLoopMode В основном для отслеживания состояния ScrollView при его перемещении.

CFRunLoop предоставляет только следующие два интерфейса режима управления:

Внутренняя логика RunLoop

Во-первых, поместите изображение, которое я считаю очень хорошим. Есть еще некоторые ошибки. Согласно официальному документу, Шаг 7: Сон, тип источника, ожидающий пробуждения, должен быть source1, а не source0.

Внутренний код реализован следующим образом: если он слишком длинный, просто посмотрите комментарии.

Внутреннее приложение RunLoop в iOS

AutoreleasePool (очень важно)

Ответ на инцидент

Распознавание жестов

Обновление интерфейса

Таймер

PerformSelecter

О GCD

Практика Runloop в iOS-разработке

AFNetworking

AsyncDisplayKit

Отображение с задержкой ImageView

Используйте PerformSelector, чтобы установить рабочий режим RunLoop текущего потока

Постоянный фоновый поток (очень часто используется)

Объясните вышеупомянутую проблему длительного соединения AFNetworking.

Метод 2 Как показано на рисунке, поскольку это не блокирующий поток метод, иногда поток приостанавливается после выхода, что, естественно, приводит к сбою программы.

Я рекомендую метод 3, он может правильно создать фоновый постоянный поток.

Позвольте мне объяснить принцип ниже

The difference is that you can use this technique on run loops you started unconditionally.

If you want the run loop to terminate, you shouldn’t use this method

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *