Swift 6iOS DevelopmentSwiftLangConcurrencyApple DeveloperMobile DevelopmentwebSocket
Perfect question π β right now, in the WebSocketManager, all the messages and events are just being printed inside the class.
To make this reusable and clean, you should expose them through a protocol delegate so any class (like a ViewController) can handle messages/events.
Hereβs the improved version with protocols + event handling:
π¦ WebSocketManager.swift
import Foundation
// MARK: - Protocol
protocol WebSocketManagerDelegate: AnyObject {
func webSocketDidConnect(_ manager: WebSocketManager)
func webSocketDidDisconnect(_ manager: WebSocketManager, code: URLSessionWebSocketTask.CloseCode, reason: Data?)
func webSocketDidReceiveMessage(_ manager: WebSocketManager, text: String)
func webSocketDidReceiveData(_ manager: WebSocketManager, data: Data)
func webSocketDidReceiveError(_ manager: WebSocketManager, error: Error)
}
// MARK: - WebSocketManager
final class WebSocketManager: NSObject {
private var webSocketTask: URLSessionWebSocketTask?
private var urlSession: URLSession!
private let url: URL
weak var delegate: WebSocketManagerDelegate?
init(url: URL) {
self.url = url
super.init()
self.urlSession = URLSession(configuration: .default,
delegate: self,
delegateQueue: OperationQueue())
}
// MARK: - Public Methods
func connect() {
webSocketTask = urlSession.webSocketTask(with: url)
webSocketTask?.resume()
listen()
sendPing()
}
func disconnect() {
webSocketTask?.cancel(with: .goingAway, reason: nil)
}
func send(_ text: String) {
webSocketTask?.send(.string(text)) { [weak self] error in
if let error = error {
self?.delegate?.webSocketDidReceiveError(self!, error: error)
}
}
}
// MARK: - Private Methods
private func listen() {
webSocketTask?.receive { [weak self] result in
guard let self = self else { return }
switch result {
case .failure(let error):
self.delegate?.webSocketDidReceiveError(self, error: error)
case .success(let message):
switch message {
case .string(let text):
self.delegate?.webSocketDidReceiveMessage(self, text: text)
case .data(let data):
self.delegate?.webSocketDidReceiveData(self, data: data)
@unknown default:
break
}
}
self.listen() // keep listening
}
}
private func sendPing() {
webSocketTask?.sendPing { [weak self] error in
guard let self = self else { return }
if let error = error {
self.delegate?.webSocketDidReceiveError(self, error: error)
return
}
DispatchQueue.global().asyncAfter(deadline: .now() + 10) {
self.sendPing()
}
}
}
}
// MARK: - URLSessionWebSocketDelegate
extension WebSocketManager: URLSessionWebSocketDelegate {
func urlSession(_ session: URLSession,
webSocketTask: URLSessionWebSocketTask,
didOpenWithProtocol protocol: String?) {
delegate?.webSocketDidConnect(self)
}
func urlSession(_ session: URLSession,
webSocketTask: URLSessionWebSocketTask,
didCloseWith closeCode: URLSessionWebSocketTask.CloseCode,
reason: Data?) {
delegate?.webSocketDidDisconnect(self, code: closeCode, reason: reason)
}
}
π Usage Example (e.g. in a ViewController)
class ChatViewController: UIViewController, WebSocketManagerDelegate {
private var socketManager: WebSocketManager!
override func viewDidLoad() {
super.viewDidLoad()
socketManager = WebSocketManager(url: URL(string: "wss://echo.websocket.events")!)
socketManager.delegate = self
socketManager.connect()
}
// MARK: - WebSocketManagerDelegate
func webSocketDidConnect(_ manager: WebSocketManager) {
print("β
Connected")
manager.send("Hello from iOS π")
}
func webSocketDidDisconnect(_ manager: WebSocketManager, code: URLSessionWebSocketTask.CloseCode, reason: Data?) {
print("β Disconnected, code: \(code.rawValue)")
}
func webSocketDidReceiveMessage(_ manager: WebSocketManager, text: String) {
print("π© Message: \(text)")
}
func webSocketDidReceiveData(_ manager: WebSocketManager, data: Data) {
print("π¦ Data received: \(data.count) bytes")
}
func webSocketDidReceiveError(_ manager: WebSocketManager, error: Error) {
print("β οΈ Error: \(error.localizedDescription)")
}
}
β Now your WebSocket is:
- Encapsulated in a class
- Event-driven with delegate callbacks
- Reusable across multiple screens
About the Author
HK
Harsh Kadiya
Senior iOS & Flutter Developer
Related Posts
Building Scalable iOS Apps with SwiftUI
Learn how to create scalable and maintainable iOS applications using SwiftUI and modern architecture patterns.
121 views β’ 92 likesRead more β
Best Practices for iOS App Performance Optimization
Discover techniques and best practices to optimize your iOS app's performance and user experience.
123 views β’ 86 likesRead more β