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

от автора

Всем привет.

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

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

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

import Foundation import CFNetwork  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())

ссылка на оригинал статьи https://habr.com/ru/post/485468/


Комментарии

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

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