WebSocket in Swift: Building Real-Time Applications for iOS and macOS

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to WebSocket in Swift: from theory to practice



Modern mobile and desktop applications increasingly require instant data transfer. Whether it's a chat, stock exchange terminal, online game, or monitoring system — users expect information to update in real time without constantly refreshing the screen. This is where the WebSocket protocol comes to the rescue.



Unlike a classic HTTP request, which works on a "request-response" principle, WebSocket establishes a permanent bidirectional connection between the client and server. This means the server can send data to the client at any time without a prior request. In the Apple ecosystem, both native solutions (URLSessionWebSocketTask) and popular third-party libraries, such as Starscream, are available for working with WebSocket.



In this article, we will look at how to integrate WebSocket into your Swift application for iOS and macOS, write working code examples, and review best practices.



1. Native WebSocket implementation via URLSession



Starting with iOS 13 and macOS 10.15, Apple provides built-in WebSocket support through the URLSessionWebSocketTask class. This is the simplest and recommended method, requiring no installation of third-party dependencies.



Creating and configuring the connection



First, you need to create an instance of URLSession and set its configuration. Then we form a URL with the ws:// protocol (or wss:// for a secure connection) and create a WebSocket task.



import Foundation

class WebSocketManager: NSObject { private var webSocketTask: URLSessionWebSocketTask? private let session: URLSession override init() { let config = URLSessionConfiguration.default self.session = URLSession(configuration: config, delegate: nil, delegateQueue: OperationQueue()) super.init() } func connect() { guard let url = URL(string: "wss://echo.websocket.org") else { return } webSocketTask = session.webSocketTask(with: url) webSocketTask?.resume() receiveMessage() } func disconnect() { webSocketTask?.cancel(with: .normalClosure, reason: nil) }}


Sending and receiving messages



WebSocket supports sending both text (URLSessionWebSocketTask.Message.string) and binary data (.data). To receive messages, you need to recursively call the receive method, as it processes only one message at a time.



extension WebSocketManager {    func sendMessage(_ text: String) {        let message = URLSessionWebSocketTask.Message.string(text)        webSocketTask?.send(message) { error in            if let error = error {                print("Send error: \\(error.localizedDescription)")            }        }    }        private func receiveMessage() {        webSocketTask?.receive { [weak self] result in            switch result {            case .success(let message):                switch message {                case .string(let text):                    print("Received text message: \\(text)")                case .data(let data):                    print("Received binary data: \\(data.count) bytes")                @unknown default:                    print("Unknown message type")                }                // Recursively continue listening                self?.receiveMessage()            case .failure(let error):                print("Receive error: \\(error.localizedDescription)")            }        }    }}


Note the recursive call to receiveMessage() inside the success closure — this ensures your application will continuously receive new data.

Blogs

Book Recommendations