Использование веб-сокетов iOS 13 для отображения обновлений криптовалюты в реальном времени

Примечание редактора: эта статья не является советом по инвестициям и предназначена только для развлекательных и образовательных целей.

WebSockets ранее поддерживались Javascript API WebView. С появлением iOS 13 и macOS Catalina Apple представила этот протокол в своих сетевых фреймворках - URLSession и Network.

Зачем нужен WebSocket?

Раньше для двунаправленной передачи данных мы использовали опрос, длинный опрос или запуск тихих push-уведомлений.

Хотя периодический опрос вызывает множество запросов, многие из которых не возвращают никаких новых данных, отправка слишком большого количества тихих push-уведомлений также неэффективна. Часто уведомления не приходят в режиме реального времени.

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

К счастью, нам на помощь пришли протоколы WebSocket, которые лишены каких-либо накладных расходов HTTP.

Как только клиент отправляет серверу запрос на соединение WebSocket, создается двунаправленный поток, позволяющий отправлять и получать сообщения (не запросы) с любой стороны.

Обычно WebSockets используются в приложениях чата и многопользовательских играх.

Наша цель

  • В следующих разделах мы увидим, как создать WebSocket с нашим URLSession на стороне клиента.
  • Кроме того, мы создадим приложение iOS на основе SwiftUI и Combine, которое использует WebSockets для получения обновлений цен на биткойны в реальном времени из API.

Вот пример того, чего мы добьемся к концу этой статьи:

Веб-сокеты с URLSession

URLSessionWebSocketTask упрощает создание WebSocket с URLSession.

Ниже приведены пять основных компонентов соединения WebSocket.

1. Открытое соединение

let urlSession = URLSession(configuration: .default)
let webSocketTask = urlSession.webSocketTask(with: "wss://ws.finnhub.io?token=XYZ")
webSocketTask.resume()

2. Отправить сообщение в виде строки или данных

webSocketTask.send(.string("Hello")){error in ...}

3. Получать сообщение с указанием типа результата

webSocketTask.receive{result in  ...}

4. Отключить

webSocketTask.cancel(with: .goingAway, reason: nil)

5. Настольный теннис.

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

webSocketTask?.sendPing { (error) in ... }

Тикер цены биткойнов SwiftUI с использованием веб-сокетов

Чтобы получать обновления криптовалюты в реальном времени, я создал ключ API и использовал URL-адрес WebSocket с этого веб-сайта.

Следующее представление SwiftUI состоит из изображения, содержащего символ SF с установленным цветом переднего плана вместе с текстом, который показывает обновления цен в реальном времени:

priceResult необходимо опубликовать из класса ObservableObject - WebSocketService.swift, как мы увидим дальше:

В приведенном выше коде мы определили несколько свойств и настроили подписку в методе init. Вам необходимо заменить XYZ собственным сгенерированным ключом API.

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

Чтобы вручную опубликовать изменения в представлении SwiftUI, didChange.send() запускается, когда свойство priceResult обновляется подпиской Combine.

Оставшаяся часть класса WebSocketService, который создает WebSocket URLSession, приведена ниже:

Для декодирования ответа API используются следующие структурные модели:

Когда приложение было построено на симуляторе watchOS, я получил следующий результат:

Заключение

Мы увидели силу операторов Combine в управлении потоком данных в SwiftUI в приведенной выше реализации обновления цен на биткойны в реальном времени.

WebSockets в идеале следует использовать для отправки небольших блоков сообщений. Передача данных быстрая.

Полный исходный код вышеуказанного приложения доступен в репозитории GitHub.

На этом все - спасибо за чтение.