What solution did you use for working with WebSocket?
sobes.tech AI
Answer from AI
In projects where real-time two-way interaction was required, I successfully used URLSessionWebSocketTask.
This is a built-in solution of the Network framework, available starting from iOS 13.
Advantages of URLSessionWebSocketTask:
- Native: Integrated with
URLSession, which simplifies connection management and network event handling. - Performance: Optimized for network operations at the system level.
- Reliability: Built-in ping and pong mechanisms, automatic reconnection attempts (though additional logic may be needed for complex scenarios).
- Security: Supports TLS out of the box.
Main steps of operation:
-
Creating an instance of
URLSessionWebSocketTask.// Creating a URLSession instance with default settings let session = URLSession(configuration: .default) // Initializing WebSocket task let webSocketTask = session.webSocketTask(with: URL(string: "wss://example.com/socket")!) -
Starting the connection.
// Resuming the task to establish the connection webSocketTask.resume() -
Sending messages (text or binary data).
// Sending a text message webSocketTask.send(.string("Hello, world!")) { error in if let error = error { print("Send error: \(error)") } } // Sending binary data let dataToSend = Data([1, 2, 3]) webSocketTask.send(.data(dataToSend)) { error in if let error = error { print("Send error: \(error)") } } -
Receiving messages. This is an asynchronous process.
// Recursive function to receive messages func receiveMessage() { webSocketTask.receive { result in switch result { case .failure(let error): print("Receive error: \(error)") // Handle error, possibly attempt reconnection case .success(let message): switch message { case .string(let text): print("Received text message: \(text)") case .data(let data): print("Received binary data: \(data)") @unknown default: fatalError("Unknown message type") } // Continue listening for messages self.receiveMessage() } } } // Start listening receiveMessage() -
Handling connection lifecycle events (open, close, errors) using the
URLSessionWebSocketDelegatedelegate.// Delegate implementation example class WebSocketHandler: NSObject, URLSessionWebSocketDelegate { func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) { print("Connection opened") // Start receiving messages after opening receiveMessage() // Assumes receiveMessage is defined } func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) { let reasonString = reason.flatMap { String(data: $0, encoding: .utf8) } ?? "Unknown reason" print("Connection closed with code \(closeCode.rawValue), reason: \(reasonString)") // Reconnection logic or cleanup } // Session error handling func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { if let error = error { print("Task completed with error: \(error)") // Additional error handling logic } } } // When creating the session, use the delegate let delegate = WebSocketHandler() let sessionWithDelegate = URLSession(configuration: .default, delegate: delegate, delegateQueue: OperationQueue()) let webSocketTaskWithDelegate = sessionWithDelegate.webSocketTask(with: URL(string: "wss://example.com/socket")!)
I also used third-party libraries like Starscream when support for older iOS versions or certain features not available in the native solution (such as automatic reconnection with exponential backoff) was required. However, when possible, I preferred URLSessionWebSocketTask due to the advantages mentioned above.