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: Why WebSocket is Important for a Swift Developer

In modern mobile and desktop development, users are accustomed to instant updates: the news feed updates without reloading, the interlocutor's status in a chat changes in real-time, and stock quotes arrive with millisecond delays. Traditional HTTP with its request-response model is inefficient for such tasks — it creates excessive load on the server and the device's battery.

The WebSocket protocol comes to the rescue. It establishes a permanent bidirectional connection between the client (an iOS/macOS app in Swift) and the server. In this article, we will look at two main ways to work with WebSocket in Swift: the native URLSessionWebSocketTask (iOS 13+ / macOS 10.15+) and the popular third-party library Starscream. You will learn how to create a real-time chat, configure automatic reconnection, and handle errors.



WebSocket Basics in Swift: URLSessionWebSocketTask

Starting with iOS 13 and macOS Catalina, Apple provides built-in WebSocket support through the URLSessionWebSocketTask class. This is a simple and secure way that does not require installing additional dependencies.



Creating and Configuring a Connection

First, let's create an instance of URLSession and set the configuration. Note: to work with WebSocket, you need to use the wss:// protocol (secure connection) or ws:// (unsecured, for development only).

import Foundation

class WebSocketManager: NSObject { private var webSocketTask: URLSessionWebSocketTask? private let session: URLSession override init() { let config = URLSessionConfiguration.default config.timeoutIntervalForRequest = 30 config.waitsForConnectivity = true 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() print("WebSocket connection established") receiveMessage() }}


Sending and Receiving Messages

WebSocket supports two types of messages: String and binary (Data). Let's look at sending:

func sendMessage(_ text: String) {    let message = URLSessionWebSocketTask.Message.string(text)    webSocketTask?.send(message) { error in        if let error = error {            print("Send error: \\(error.localizedDescription)")        } else {            print("Message sent: \\(text)")        }    }}

To receive messages, you need to implement a recursive call to the receive method:

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:                break            }            // Continue listening for the next messages            self?.receiveMessage()        case .failure(let error):            print("Receive error: \\(error.localizedDescription)")            // Here you can implement reconnection        }    }}


Closing the Connection and Error Handling

Properly terminating a WebSocket connection is an important part of a production application:

func disconnect() {    let closeCode = URLSessionWebSocketTask.CloseCode.normalClosure    webSocketTask?.cancel(with: closeCode, reason: nil)    p                

Blogs

Book Recommendations