Исходя из JavaScript и Python, создание задержки в Swift было странным. Вот как заставить ваши задержки работать.

Прежде чем я понял это, я пробовал GCD (Grand Central Dispatch), поскольку это то, что все предлагают на большинстве популярных форумов, но всякий раз, когда я пытался использовать GCD, я не мог найти решение, которое сработало бы для этого сценария.
Я уверен, что более опытный Swift-программист скажет мне, что есть способ, но я здесь, чтобы предоставить рабочее решение, которое соответствует моим потребностям ... И, надеюсь, поможет кому-то еще!

Мой сценарий был таким:

  • Сделайте вызов API, чтобы получить данные
  • Предоставлять напоминания через заданные интервалы времени, пока пользователь не остановит их или данные не станут доступны

Я начал с вызова API на каждой итерации и использования GCD для выполнения этого кода с помощью asyncAfter в фоновой очереди. Это работало нормально, пока я не вспомнил, что в настоящее время я единственный, кто отправляет запросы API, и что если бы больше пользователей делали то же самое, я бы быстро достиг своего предела скорости. < br /> Итак, требовалось новое решение, и я знал, что данные, которые я собирал, вряд ли изменится в течение 30–60 секунд; У меня было некоторое пространство для маневра, чтобы зациклиться и предоставить ту же обратную связь пользователю, уменьшив при этом количество вызовов API в 3 раза. Никто даже не узнает!

Сценарий стал:

  • Сделать вызов API
  • Напоминания о нескольких циклах таймера без вызова API
  • Повторяйте до тех пор, пока пользователь не остановится или данные не станут доступны

Здесь GCD перестает работать для меня.
Я пробовал цикл for с asyncAfter, но это не сработало, потому что asyncAfter возвращает сразу, что означает, что все итерации запускаются почти сразу, а затем возвращаются почти в одно и то же время . Не то, что нам нужно!
Пробовал разные методы НОД. Я даже пробовал sleep (), хотя знал, что он заблокирует обновления моего пользовательского интерфейса.
Все, что я пробовал, либо запускало все итерации одновременно, либо блокировало основной поток и оставляло пользовательский интерфейс непригодным для использования ...

Таймер спешит на помощь!
Я достаточно объяснил свои беды, так как же нам это исправить? .. Таймер!

Этот таймер будет повторять цикл каждые 10 секунд и при этом увеличивать значение переменной count.
Если count равно 2, мы запускаем вызов API, а затем аннулируем таймер. Я выделил таймер жирным шрифтом, потому что он важен. Он будет продолжать цикл до тех пор, пока вы не сделаете его недействительным, и вы можете получить несколько таймеров, если снова вызовете запись в цикл в своем коде.

Итак, как это работает в бесконечном (но допускающем прерывание) цикле? Мы можем сделать что-то вроде этого:

  • Когда появится представление, вызовите функцию, содержащую вызов API.
  • Если вызов API прошел успешно; вызовите функцию, содержащую таймер, и сделайте все, что вам нужно, с данными.
  • Позвольте циклу таймера до тех пор, пока он не выполнит свое условие, обеспечивая обратную связь по каждому циклу, как если бы был другой вызов API, сделайте его недействительным, а затем снова вызовите функцию с вызовом API.

После этого я добавил возможность приостанавливать тактильную обратную связь с помощью долгого нажатия на пользовательский интерфейс. Для этого вы можете создать логическое значение, например shouldStopAPICalls и переключите его на жест, оберните блок кода, который таймер выполняет, с помощью if-else, if shouldStopAPICalls false, затем выполнить цикл, иначе - отключить таймер.
Вам нужно будет вызвать функцию с вызовом API, чтобы снова запустить цикл, но у вас будет рабочий цикл (с задержками, если вы добавлена ​​эта часть), которую можно приостановить, не блокируя ваш основной поток!

Спасибо за чтение, удачи в ваших приложениях!