SocketX Client for iOS using Swift
Introduction
This Swift Package provides the Eclypses SocketX Client for iOS. It enables secure, encrypted WebSocket communication between your iOS app and your backend via a SocketX server. All messages are automatically protected using MTE (Microtokenization) encryption with Kyber-512 post-quantum key exchange.
Purpose of SocketX Client:
- Establish secure WebSocket connections to SocketX servers
- Send and receive encrypted text and binary messages
- Support room-based pub/sub messaging patterns
- Automatic MTE pairing and encryption/decryption
This guide provides a quick-start for experienced developers. For detailed examples, troubleshooting, and in-depth explanations, see the complete documentation on GitHub.
Prerequisites
- iOS 14.0 or later
- Swift 5.5 or later
- Xcode 13.0 or later
- Valid MTE license (configured in
Settings.swift) - Access to a SocketX server instance
Installation
Swift Package Manager (Recommended)
- In Xcode, go to File > Add Packages...
- Enter the package URL:
https://github.com/Eclypses/socketx-client-swift.git - Follow the prompts to add the package to your project.
Setup
- Import the SocketX module:
import SocketXClient
- Create a WebSocket task and initialize the SocketX client:
class ChatManager {
var socketXClient: SocketXClient?
var isConnected = false
func setupConnection() {
// 1. Create URL for the room you want to join
let url = URL(string: "wss://your-server.com/chat/room-1")!
// 2. Configure URLSession
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// 3. Create WebSocket task (do NOT call .resume())
let task = session.webSocketTask(with: url)
// 4. Initialize SocketX client
do {
socketXClient = try SocketXClient(task: task)
setupCallbacks()
} catch {
print("Failed to initialize: \(error)")
}
}
func setupCallbacks() {
socketXClient?.onConnected = { [weak self] in
self?.isConnected = true
print("✅ Connected and ready")
}
socketXClient?.onMessageReceived = { [weak self] text in
print("📨 Received: \(text)")
self?.handleMessage(text)
}
socketXClient?.onBinaryReceived = { [weak self] data in
print("📦 Received: \(data.count) bytes")
self?.handleBinaryData(data)
}
socketXClient?.onError = { [weak self] error in
self?.isConnected = false
print("❌ Error: \(error)")
}
}
func handleMessage(_ text: String) {
// Process received text message
}
func handleBinaryData(_ data: Data) {
// Process received binary data
}
}
Usage
Connecting
socketXClient?.connect()
The client will automatically:
- Establish the WebSocket connection
- Perform MTE pairing with the server (Kyber-512 key exchange)
- Join the specified room
- Trigger
onConnectedwhen ready
Sending Messages
Text Messages:
// Plain text
socketXClient?.send(text: "Hello, World!")
// JSON
let message = ["type": "chat", "content": "Hello"]
if let jsonData = try? JSONSerialization.data(withJSONObject: message),
let jsonString = String(data: jsonData, encoding: .utf8) {
socketXClient?.send(text: jsonString)
}
// Codable objects
struct ChatMessage: Codable {
let type: String
let content: String
}
let message = ChatMessage(type: "chat", content: "Hello")
if let jsonData = try? JSONEncoder().encode(message),
let jsonString = String(data: jsonData, encoding: .utf8) {
socketXClient?.send(text: jsonString)
}
Binary Data:
// Send binary data
let data = Data([0x01, 0x02, 0x03])
socketXClient?.send(binary: data)
// Send image
if let image = UIImage(named: "photo"),
let imageData = image.jpegData(compressionQuality: 0.8) {
socketXClient?.send(binary: imageData)
}
Receiving Messages
Set up callbacks before connecting:
socketXClient?.onMessageReceived = { text in
// Parse JSON
if let data = text.data(using: .utf8),
let message = try? JSONDecoder().decode(ChatMessage.self, from: data) {
print("Message: \(message.content)")
}
}
socketXClient?.onBinaryReceived = { data in
// Display image
if let image = UIImage(data: data) {
DispatchQueue.main.async {
self.imageView.image = image
}
}
}
Room-Based Messaging
The SocketX server routes messages based on the URL path:
// Join different rooms
let chatUrl = URL(string: "wss://your-server.com/chat/general")!
let notificationsUrl = URL(string: "wss://your-server.com/notifications/user-123")!
// Each room has its own client instance
let chatClient = try? SocketXClient(task: session.webSocketTask(with: chatUrl))
let notificationClient = try? SocketXClient(task: session.webSocketTask(with: notificationsUrl))
Messages sent to a room are received by all connected clients in that room.
Disconnecting
socketXClient?.disconnect()
socketXClient = nil
Error Handling
socketXClient?.onError = { error in
switch error {
case .codecError(let reason):
// MTE encryption/decryption error
// Usually resolved by reconnecting
print("Codec error: \(reason)")
case .networkError(let reason):
// Network connectivity issue
print("Network error: \(reason)")
}
}
SwiftUI Integration
import SwiftUI
import SocketXClient
class ChatViewModel: ObservableObject {
@Published var messages: [String] = []
@Published var isConnected = false
private var socketXClient: SocketXClient?
func connect() {
let url = URL(string: "wss://dev-socketx-server.eclypses.com/chat")!
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.webSocketTask(with: url)
socketXClient = try? SocketXClient(task: task)
socketXClient?.onConnected = { [weak self] in
DispatchQueue.main.async {
self?.isConnected = true
}
}
socketXClient?.onMessageReceived = { [weak self] text in
DispatchQueue.main.async {
self?.messages.append(text)
}
}
socketXClient?.onError = { [weak self] error in
DispatchQueue.main.async {
self?.isConnected = false
}
}
socketXClient?.connect()
}
func send(_ message: String) {
socketXClient?.send(text: message)
}
func disconnect() {
socketXClient?.disconnect()
socketXClient = nil
isConnected = false
}
}
struct ChatView: View {
@StateObject private var viewModel = ChatViewModel()
@State private var messageText = ""
var body: some View {
VStack {
List(viewModel.messages, id: \.self) { message in
Text(message)
}
HStack {
TextField("Message", text: $messageText)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("Send") {
viewModel.send(messageText)
messageText = ""
}
.disabled(!viewModel.isConnected)
}
.padding()
}
.onAppear { viewModel.connect() }
.onDisappear { viewModel.disconnect() }
}
}
Demo Server
A public demo server is available for testing:
let url = URL(string: "wss://dev-socketx-server.eclypses.com/test")!
Available rooms:
/dogs,/cats,/fish- Text messaging rooms/bytes-1,/bytes-2- Binary messaging rooms
API Reference
See the complete API documentation for full details. Key classes:
-
SocketXClient: Main entry point for WebSocket communicationinit(task: URLSessionWebSocketTask) throwsconnect()- Establish connection and perform MTE pairingdisconnect()- Close connectionsend(text: String)- Send encrypted text messagesend(binary: Data)- Send encrypted binary data
-
Callbacks:
onConnected: (() -> Void)?- Called when connection is readyonMessageReceived: ((String) -> Void)?- Called when text message receivedonBinaryReceived: ((Data) -> Void)?- Called when binary data receivedonError: ((SocketXClientError) -> Void)?- Called on errors
-
SocketXClientError: Error typescodecError(String)- MTE encryption/decryption errornetworkError(String)- Network connectivity error
Support
Email: info@eclypses.com
Web: www.eclypses.com
Additional Resources
For detailed examples, troubleshooting, and advanced implementation patterns:
- GitHub Repository – Complete documentation with examples
- Release Notes – Latest updates and changes
- Getting Started Guide – Official documentation
All trademarks of Eclypses Inc. may not be used without Eclypses Inc.'s prior written consent.