Использование веб-сокетов 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.
На этом все - спасибо за чтение.