Как стать автором
Обновить

Вариант работы с вебсокетами в iOS на языке Swift / Написал менеджер для работы с websocket

Время на прочтение3 мин
Количество просмотров20K
Всем привет.

4 года назад я уже разбирался с вебсокетами в iOS, тогда я решил задачу с помощью одной из библиотек cocoapods, статья есть на Хабре. А сегодня хочу продемонстрировать еще одно решение, нативное без cocoapods.

Я написал свой менеджер для работы с вебсокетами (Менеджер в данном случае синглтон класс который может быть вызван в любом месте приложения, так как это синглтон его экземпляр будет создан только один раз для всего приложения).

Воспользуюсь я для своих целей нативными средствами.

import Foundation

class WSManager {
    public static let shared = WSManager() // создаем Синглтон
    private init(){}
    
    private var dataArray = [МОДЕЛЬ_МОИХ_ДАННЫХ]()
    
    let webSocketTask = URLSession(configuration: .default).webSocketTask(with: URL(string: "wss://ТУТ_ВАШ_АДРЕС"*))
    
   //функция вызова подключения
    public func connectToWebSocket() {
        webSocketTask.resume()
        self.receiveData() { _ in }
    }
    
//функция подписки на что либо
    public func subscribeBtcUsd() {
        let message = URLSessionWebSocketTask.Message.string("SUBSCRIBE: НА_ЧТО_ПОДПИСЫВАЕМСЯ")
        webSocketTask.send(message) { error in
            if let error = error {
                print("WebSocket couldn’t send message because: \(error)")
            }
        }
    }

//функция отписки от чего либо    
    public func unSubscribeBtcUsd() {
           let message = URLSessionWebSocketTask.Message.string("UNSUBSCRIBE: ОТ_ЧЕГО_ОТПИСЫВАЕМСЯ ")
           webSocketTask.send(message) { error in
               if let error = error {
                   print("WebSocket couldn’t send message because: \(error)")
               }
           }
       }
    
//функция получения данных, с эскейпингом чтобы получить данные наружу
    func receiveData(completion: @escaping ([МОДЕЛЬ_МОИХ_ДАННЫХ]?) -> Void) {
      webSocketTask.receive { result in
        switch result {
            case .failure(let error):
              print("Error in receiving message: \(error)")
            case .success(let message):
              switch message {
                case .string(let text):
                    let data: Data? = text.data(using: .utf8)
                    let srvData = try? CODABLE_МОДЕЛЬ_ТОГО_ЧТО_ДОЛЖНО_ПРИЙТИ.decode(from: data ?? Data())
                    for singleData in srvData ?? [] {
                        self.dataArray.append(МОДЕЛЬ_МОИХ_ДАННЫХ(параметр1:  singleData.parametr1, параметр2:  singleData.parametr2, параметр3:  singleData.parametr3))  
                    }

                case .data(let data):
// В вашем варианте данные могут приходить сразу сюда
                    print("Received data: \(data)")
              @unknown default:
                debugPrint("Unknown message")
              }
              
              self.receiveData() {_ in } // рекурсия
        }
      }
        completion(self.dataArray) // отправляем в комплишн то что насобирали в нашу модель
    }
}

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

import UIKit

class MainViewController: UIViewController {
    
    private var dataArray = [МОДЕЛЬ_МОИХ_ДАННЫХ]()

    override func viewDidLoad() {
        super.viewDidLoad()
        WSManager.shared.connectToWebSocket() // подключаемся 
        WSManager.shared.subscribeBtcUsd() //подписываемся на получение данных
        self.getData() //получаем данные
    }

    private func getData() {
        //получаем данные
        WSManager.shared.receiveData() { [weak self] (data) in
            guard let self = self else { return }
            guard let data = data else { return }
             self.dataArray = data // кладем данные в переменную и дальше можно делать с ними то что требуется
        }
    }

}

*по поводу адреса
wss:// это аналог https://
ws:// это аналог http://

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

Тестовый пример доступен у меня в гитхабе

Также я использую extension для Decodable который доступен тоже у меня в гитхабе
я про вот эту часть

let srvData = try? CODABLE_МОДЕЛЬ_ТОГО_ЧТО_ДОЛЖНО_ПРИЙТИ.decode(from: data ?? Data())
Теги:
Хабы:
Всего голосов 5: ↑4 и ↓1+7
Комментарии17

Публикации

Истории

Работа

iOS разработчик
22 вакансии
Swift разработчик
30 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
11 сентября
Митап по BigData от Честного ЗНАКа
Санкт-ПетербургОнлайн
14 сентября
Конференция Practical ML Conf
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн