### Run Console Example Source: https://github.com/centrifugal/centrifuge-swift/blob/master/Examples/ConsoleExample/README.md Executes the example command using 'make run-console-example'. This command is typically used to test or demonstrate functionality after the server is running. ```bash make run-console-example ``` -------------------------------- ### Example Token Getter for Connection Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md An example of a token getter callback for establishing a connection. It fetches a new connection token and completes the operation. ```swift let tokenGetter: CentrifugeConnectionTokenGetter = { event, completion in // Fetch new connection token completion(.success(token)) } ``` -------------------------------- ### Full Centrifuge Client Example Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/QUICK_START.md This comprehensive example demonstrates setting up the Centrifuge client, connecting, subscribing to a channel, and publishing messages within a UIKit application. It includes delegate implementations for connection, disconnection, errors, subscription, and message publications. ```swift import UIKit import SwiftCentrifuge class ViewController: UIViewController { var client: CentrifugeClient? var sub: CentrifugeSubscription? override func viewDidLoad() { super.viewDidLoad() setupCentrifuge() } func setupCentrifuge() { // Create config let config = CentrifugeClientConfig( timeout: 5.0, token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ) // Create client client = CentrifugeClient( endpoint: "wss://localhost:8000/connection/websocket?cf_protocol=protobuf", config: config, delegate: self ) // Connect client?.connect() } @IBAction func sendMessage(_ sender: UIButton) { let message = ["text": "Hello from iOS!"] let data = try? JSONSerialization.data(withJSONObject: message) sub?.publish(data: data!) { result in switch result { case .success: print("Message sent") case .failure(let error): print("Error: \(error)") } } } } extension ViewController: CentrifugeClientDelegate { func onConnected(_ client: CentrifugeClient, _ event: CentrifugeConnectedEvent) { print("Connected!") // Create subscription after connecting do { sub = try client.newSubscription( channel: "chat", delegate: self ) sub?.subscribe() } catch { print("Error: \(error)") } } func onDisconnected(_ client: CentrifugeClient, _ event: CentrifugeDisconnectedEvent) { print("Disconnected") } func onError(_ client: CentrifugeClient, _ event: CentrifugeErrorEvent) { print("Client error: \(event.error)") } } extension ViewController: CentrifugeSubscriptionDelegate { func onSubscribed(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscribedEvent) { print("Subscribed to \(sub.channel)") } func onPublication(_ sub: CentrifugeSubscription, _ event: CentrifugePublicationEvent) { let json = try? JSONSerialization.jsonObject(with: event.data) print("New message: \(json ?? [:])") } func onError(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscriptionErrorEvent) { print("Subscription error: \(event.error)") } } ``` -------------------------------- ### Fetch Presence Statistics Swift Example Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/TYPES.md Example of how to fetch and handle presence statistics for a channel. This code should be used within a client context after establishing a connection. ```swift client.presenceStats(channel: "users") { result in switch result { case .success(let stats): print("Clients: \(stats.numClients), Users: \(stats.numUsers)") case .failure(let error): print("Error: \(error)") } } ``` -------------------------------- ### Example: Starts With Filter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of using the `startsWith` function to match publications where the 'country' tag begins with 'US'. ```swift CentrifugeFilter.startsWith("country", "US") ``` -------------------------------- ### Swift Example: Implementing Subscription Token Getter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Provides an example of how to implement the `CentrifugeSubscriptionTokenGetter` to fetch tokens from a remote API. Ensure the API returns a JSON object with a 'token' key. ```swift let tokenGetter: CentrifugeSubscriptionTokenGetter = { event, completion in // Fetch channel-specific token let channelName = event.channel URLSession.shared.dataTask(with: URL(string: "https://api.example.com/channel/\(channelName)/token")!) { data, response, error in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let token = json["token"] as? String else { completion(.failure(NSError(domain: "InvalidResponse", code: -1))) return } completion(.success(token)) }.resume() } let subConfig = CentrifugeSubscriptionConfig( token: "initial-token", tokenGetter: tokenGetter ) ``` -------------------------------- ### Example Token Getter for Subscription Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md An example of a token getter callback for a specific subscription. It retrieves the channel from the event and fetches the token for that channel. ```swift let tokenGetter: CentrifugeSubscriptionTokenGetter = { event, completion in let channel = event.channel // Fetch token for specific channel completion(.success(token)) } ``` -------------------------------- ### Example: AND Logical Operator Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of combining filters with logical AND to match publications where 'ticker' is 'AAPL' AND 'price' is greater than or equal to '100'. ```swift CentrifugeFilter.and([ CentrifugeFilter.eq("ticker", "AAPL"), CentrifugeFilter.gte("price", "100") ]) ``` -------------------------------- ### Example State Getter for Subscription Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md An example of a state getter callback for a subscription. It retrieves the channel from the event and fetches the last known position for that channel. ```swift let stateGetter: CentrifugeSubscriptionStateGetter = { event, completion in let channel = event.channel let position = database.getLastPosition(channel: channel) completion(.success(position)) } ``` -------------------------------- ### Example: OR Logical Operator Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of combining filters with logical OR to match publications where 'priority' is 'high' OR 'priority' is 'critical'. ```swift CentrifugeFilter.or([ CentrifugeFilter.eq("priority", "high"), CentrifugeFilter.eq("priority", "critical") ]) ``` -------------------------------- ### CentrifugeClient Initialization Example Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Creates a new Centrifuge client instance. Use this to establish a connection to the Centrifugo server with specified configuration and delegate. ```swift let config = CentrifugeClientConfig( timeout: 5.0, token: "jwt-auth-token", debug: true ) let client = CentrifugeClient( endpoint: "ws://localhost:8000/connection/websocket?cf_protocol=protobuf", config: config, delegate: self ) ``` -------------------------------- ### Example: Equality Filter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of using the `eq` function to match publications where the 'ticker' tag equals 'AAPL'. ```swift CentrifugeFilter.eq("ticker", "AAPL") ``` -------------------------------- ### Handle User Join Event Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md Example of how to implement the `onJoin` delegate method to react to a user joining a channel. Use this to update UI or perform other actions. ```swift func onJoin(_ sub: CentrifugeSubscription, _ event: CentrifugeJoinEvent) { print("\(event.user) joined \(sub.channel)") // Update presence UI } ``` -------------------------------- ### Minimal SwiftCentrifuge Client Setup Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/00-START-HERE.txt Demonstrates the basic steps to initialize and connect a Centrifuge client, including configuration, client creation, and subscribing to a channel. Ensure you provide a valid JWT token and endpoint. ```swift import SwiftCentrifuge // 1. Create config let config = CentrifugeClientConfig(token: "jwt-token") // 2. Create client let client = CentrifugeClient( endpoint: "wss://example.com/connection/websocket?cf_protocol=protobuf", config: config, delegate: self ) // 3. Connect client.connect() // 4. Subscribe do { let sub = try client.newSubscription( channel: "updates", delegate: self ) sub.subscribe() } catch { print("Error: \(error)") } ``` -------------------------------- ### Example: Fetching History with SwiftCentrifuge Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/TYPES.md Demonstrates how to fetch historical publications for a channel and process the results or errors. Requires an active client connection. ```swift client.history(channel: "news", limit: 50) { result in switch result { case .success(let history): print("Offset: \(history.offset), Epoch: \(history.epoch)") for pub in history.publications { print("Publication: offset=\(pub.offset)") } case .failure(let error): print("Error: \(error)") } } ``` -------------------------------- ### Full Delegate Implementation Example Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/DELEGATES.md Implement `CentrifugeClientDelegate` and `CentrifugeSubscriptionDelegate` to handle connection, disconnection, errors, subscription, and publication events. Instantiate delegates and assign them to the client and subscription. ```swift class MyClientDelegate: CentrifugeClientDelegate { func onConnected(_ client: CentrifugeClient, _ event: CentrifugeConnectedEvent) { print("Connected with ID: \(event.client)") } func onDisconnected(_ client: CentrifugeClient, _ event: CentrifugeDisconnectedEvent) { print("Disconnected: \(event.reason)") } func onError(_ client: CentrifugeClient, _ event: CentrifugeErrorEvent) { print("Error: \(event.error)") } } class MySubscriptionDelegate: CentrifugeSubscriptionDelegate { func onSubscribed(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscribedEvent) { print("Subscribed to: \(sub.channel)") } func onPublication(_ sub: CentrifugeSubscription, _ event: CentrifugePublicationEvent) { let json = try? JSONSerialization.jsonObject(with: event.data) print("Received: \(json ?? [:])") } func onError(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscriptionErrorEvent) { print("Subscription error: \(event.error)") } } // Usage let clientDelegate = MyClientDelegate() let config = CentrifugeClientConfig(token: "...") let client = CentrifugeClient(endpoint: "ws://...", config: config, delegate: clientDelegate) let subDelegate = MySubscriptionDelegate() let sub = try client.newSubscription(channel: "updates", delegate: subDelegate) sub.subscribe() ``` -------------------------------- ### Example CentrifugeFilter Usage Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/TYPES.md Demonstrates how to construct a server-side filter expression using CentrifugeFilter helper functions and apply it to a subscription configuration. ```swift let filter = CentrifugeFilter.and([ CentrifugeFilter.eq("status", "active"), CentrifugeFilter.gte("price", "100") ]) let config = CentrifugeSubscriptionConfig(tagsFilter: filter) ``` -------------------------------- ### Example: Greater Than Filter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of using the `gt` function to match publications where the 'price' tag is numerically greater than '100'. ```swift CentrifugeFilter.gt("price", "100") ``` -------------------------------- ### Configure Subscription for Recovery Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Set up subscription configuration to enable message recovery and positioning, specifying the starting point for recovery. ```swift let config = CentrifugeSubscriptionConfig( recoverable: true, positioned: true, since: lastKnownPosition ) ``` -------------------------------- ### Swift Example: Implementing Subscription State Getter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Demonstrates implementing `CentrifugeSubscriptionStateGetter` to load the last stream position and application state from a database. It's crucial to read the stream position first. ```swift let stateGetter: CentrifugeSubscriptionStateGetter = { event, completion in let channel = event.channel // Step 1: Read stream position FIRST let position = database.getLastStreamPosition(channel: channel) // Step 2: Read app state from database let state = database.loadState(channel: channel) // Return the stream position to resume from completion(.success(position)) } let subConfig = CentrifugeSubscriptionConfig( recoverable: true, stateGetter: stateGetter ) ``` -------------------------------- ### Subscribe to a Channel Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/INDEX.md Create a new subscription to a specified channel and assign a delegate for handling subscription events. The subscription must be explicitly started. ```swift let sub = try client.newSubscription(channel: "news", delegate: self) sub.subscribe() ``` -------------------------------- ### Example: In List Filter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of using the `inList` function to match publications where the 'source' tag is either 'NASDAQ' or 'NYSE'. ```swift CentrifugeFilter.inList("source", ["NASDAQ", "NYSE"]) ``` -------------------------------- ### Perform an RPC Call and Handle Response Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/TYPES.md Example of making an RPC call to the server and processing the success or failure of the result. The response data can be deserialized from Data. ```swift client.rpc(method: "getData", data: requestData) { result in switch result { case .success(let rpcResult): let response = try? JSONSerialization.jsonObject(with: rpcResult.data) print("RPC response: \(response ?? [:])") case .failure(let error): print("RPC error: \(error)") } } ``` -------------------------------- ### Catching Unauthorized Error Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/ERRORS.md Example of how to catch the 'unauthorized' error, which indicates authentication failure. ```swift delegate?.onError(client, CentrifugeErrorEvent(error: CentrifugeError.unauthorized)) ``` -------------------------------- ### Handle CentrifugePublicationEvent Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md Example implementation of the `onPublication` delegate method. This function logs the publication offset, attempts to deserialize the data as JSON, and prints client information if available. ```swift func onPublication(_ sub: CentrifugeSubscription, _ event: CentrifugePublicationEvent) { print("New publication at offset \(event.offset)") let json = try? JSONSerialization.jsonObject(with: event.data) print("Data: \(json ?? [:])") if let info = event.info { print("Published by user: \(info.user), client: \(info.client)") } } ``` -------------------------------- ### Swift Package Manager Installation Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/QUICK_START.md Add SwiftCentrifuge to your project's Package.swift file for Swift Package Manager integration. ```swift .package(url: "https://github.com/centrifugal/centrifuge-swift", from: "0.11.0") ``` -------------------------------- ### CentrifugeSubscriptionConfig with Delta Type Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Example of creating a subscription configuration with the Fossil delta compression type specified. ```swift let config = CentrifugeSubscriptionConfig( delta: .fossil ) ``` -------------------------------- ### Get All Subscriptions Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Returns a dictionary of all active subscriptions currently managed by the client, keyed by their channel names. ```swift public func getSubscriptions() -> [String: CentrifugeSubscription] ``` ```swift let allSubs = client.getSubscriptions() for (channel, sub) in allSubs { print("Subscribed to \(channel)") } ``` -------------------------------- ### Handle CentrifugeSubscribedEvent Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md Example implementation of the `onSubscribed` delegate method. This function logs subscription details and checks if recovery was successful or attempted. ```swift func onSubscribed(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscribedEvent) { print("Subscribed to \(sub.channel)") if event.recovered { print("Successfully recovered \(event.streamPosition?.offset ?? 0) messages") } else if event.wasRecovering { print("Recovery attempted but not all messages recovered") } } ``` -------------------------------- ### Handle SSLClientCertificateError Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SSL_CERTIFICATES.md Example of how to load an SSL client certificate and catch potential SSLClientCertificateError exceptions. This demonstrates handling common issues like file not found or invalid passwords. ```swift do { let cert = try SSLClientCertificate( pkcs12Path: certPath, password: password ) } catch let error as SSLClientCertificateError { print("Certificate error: \(error.localizedDescription ?? "Unknown")") } catch { print("Other error: \(error)") } ``` -------------------------------- ### Handling Duplicate Subscription Error Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/ERRORS.md Example of catching 'duplicateSub' error when trying to create a subscription for an already subscribed channel. It shows how to access the existing subscription. ```swift do { let sub = try client.newSubscription(channel: "news", delegate: self) } catch CentrifugeError.duplicateSub { print("Already subscribed to this channel") if let existing = client.getSubscription(channel: "news") { // Use existing subscription } } ``` -------------------------------- ### Generate JWT Token with Python Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/QUICK_START.md Backend service must generate a JWT token for client authentication. This example uses Python with the PyJWT library. ```python import jwt import time secret = "your-secret-key" payload = { "sub": "user-id", "iat": int(time.time()) } token = jwt.encode(payload, secret, algorithm="HS256") ``` -------------------------------- ### Store and Recover Stream Position Swift Example Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/TYPES.md Demonstrates how to store the stream position when subscribed and use it to recover or query history. Ensure `recoverable` is set to true in subscription configuration. ```swift // Store position when subscribed var lastPosition: CentrifugeStreamPosition? extension MyDelegate: CentrifugeSubscriptionDelegate { func onSubscribed(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscribedEvent) { if let pos = event.streamPosition { lastPosition = pos } } } // Recover from last known position let config = CentrifugeSubscriptionConfig( recoverable: true, since: lastPosition ) let sub = try client.newSubscription( channel: "updates", delegate: self, config: config ) ``` -------------------------------- ### Run Centrifugo Docker Container Source: https://github.com/centrifugal/centrifuge-swift/blob/master/Examples/ConsoleExample/README.md Pulls the Centrifugo Docker image and runs it with various environment variables for configuration. Ensure Docker is installed and running. ```bash docker pull centrifugo/centrifugo:v6 docker run -p 8000:8000 \ -e CENTRIFUGO_CLIENT_INSECURE="true" \ -e CENTRIFUGO_CLIENT_ALLOWED_ORIGINS="*" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_DELTA_PUBLISH="true" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_PRESENCE="true" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_JOIN_LEAVE="true" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_FORCE_PUSH_JOIN_LEAVE="true" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_HISTORY_SIZE="100" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_HISTORY_TTL="300s" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_FORCE_RECOVERY="true" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_ALLOW_PUBLISH_FOR_SUBSCRIBER="true" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_ALLOW_PRESENCE_FOR_SUBSCRIBER="true" \ -e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_ALLOW_HISTORY_FOR_SUBSCRIBER="true" \ -e CENTRIFUGO_CLIENT_SUBSCRIBE_TO_USER_PERSONAL_CHANNEL_ENABLED="true" \ -e CENTRIFUGO_LOG_LEVEL="trace" \ centrifugo/centrifugo:v6 centrifugo ``` -------------------------------- ### Example: NOT Logical Operator Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of using the `not` function to invert a filter, matching publications where the 'status' tag is NOT 'inactive'. ```swift CentrifugeFilter.not(CentrifugeFilter.eq("status", "inactive")) ``` -------------------------------- ### Build a Compound Filter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/INDEX.md Construct complex filters by combining multiple conditions using logical operators like AND. This example shows an AND filter for ticker and price. ```swift let filter = CentrifugeFilter.and([ CentrifugeFilter.eq("ticker", "AAPL"), CentrifugeFilter.gte("price", "100") ]) ``` -------------------------------- ### Example: Contains Filter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Example of using the `contains` function to match publications where the 'description' tag includes the substring 'important'. ```swift CentrifugeFilter.contains("description", "important") ``` -------------------------------- ### Implement Connection Token Getter with URLSession Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Example of implementing the CentrifugeConnectionTokenGetter to fetch a new token from a backend API using URLSession. The completion handler must be called with a success or failure result. ```swift let tokenGetter: CentrifugeConnectionTokenGetter = { event, completion in // Fetch new token from backend API URLSession.shared.dataTask(with: URL(string: "https://api.example.com/token")!) { data, response, error in if let err = error { completion(.failure(err)) return } guard let data = data, let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let token = json["token"] as? String else { completion(.failure(NSError(domain: "InvalidResponse", code: -1))) return } completion(.success(token)) }.resume() } let config = CentrifugeClientConfig(tokenGetter: tokenGetter) ``` -------------------------------- ### Get Channel Presence Information Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SUBSCRIPTION.md Use this method to fetch the current list of connected clients and their associated information within a channel. The callback provides a result containing presence data or an error. ```swift sub.presence { result in switch result { case .success(let presenceResult): print("Clients in channel: \(presenceResult.presence.count)") for (clientId, info) in presenceResult.presence { print("User: \(info.user), Client: \(clientId)") } case .failure(let error): print("Error: \(error)") } } ``` -------------------------------- ### Query Channel Presence Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Use this method to get a list of connected clients and their associated user information for a specific channel. It's useful for real-time user tracking within a channel. ```swift public func presence( channel: String, completion: @escaping (Result) -> () ) ``` ```swift client.presence(channel: "users") { result in switch result { case .success(let presenceResult): for (clientId, clientInfo) in presenceResult.presence { print("User: \(clientInfo.user), Client: \(clientId)") } case .failure(let error): print("Failed to get presence: \(error)") } } ``` -------------------------------- ### Create SSLClientCertificate from PKCS#12 file path Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SSL_CERTIFICATES.md Use this initializer to create a certificate from a PKCS#12 file (.p12 or .pfx) located on disk. Ensure the file path is correct and the password is valid. ```swift do { let cert = try SSLClientCertificate( pkcs12Path: "/path/to/client.p12", password: "certificate_password" ) } catch { print("Failed to load certificate: \(error)") } ``` -------------------------------- ### Environment-Specific SSL Certificate Configuration Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SSL_CERTIFICATES.md Illustrates how to use preprocessor macros to load different SSL certificates and passwords for development and production environments. This ensures appropriate security levels are maintained across different deployment stages. ```swift #if DEBUG // Development: use test certificate let certPath = Bundle.main.path(forResource: "dev-client", ofType: "p12")! let password = "dev-password" #else // Production: use production certificate let certPath = Bundle.main.path(forResource: "prod-client", ofType: "p12")! let password = loadPasswordFromKeychain() #endif let cert = try SSLClientCertificate(pkcs12Path: certPath, password: password) ``` -------------------------------- ### connect() Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Initiates a connection to the server. This method is idempotent; it has no effect if the client is already connecting or connected. ```APIDOC ## connect() ### Description Initiates a connection to the server. No-op if already connecting or connected. ### Method `public func connect()` ### Example ```swift client.connect() ``` ``` -------------------------------- ### Create and Subscribe to a Channel Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Instantiate a new subscription to a named channel with specified configuration and initiate the subscription. ```swift let sub = try client.newSubscription( channel: "chat", delegate: self, config: CentrifugeSubscriptionConfig( recoverable: true, positioned: true ) ) sub.subscribe() ``` -------------------------------- ### Retrieve All Subscriptions Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Get a dictionary of all active subscriptions using `getSubscriptions()`. ```swift let subs = client.getSubscriptions() for (channel, sub) in subs { print("Subscribed to: \(channel)") } ``` -------------------------------- ### Subscription Configuration with Delta Compression and Token Getter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Configures a subscription for bandwidth optimization using delta compression and a dynamic token getter. ```swift let config = CentrifugeSubscriptionConfig( token: "sub-token", delta: .fossil, tokenGetter: { event, completion in getChannelToken(channel: event.channel) { token in completion(.success(token)) } } ) ``` -------------------------------- ### Starts With Filter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Match publications where a string tag begins with a specified substring. ```swift public static func startsWith(_ key: String, _ val: String) -> CentrifugeFilterNode ``` -------------------------------- ### Basic Subscription Configuration Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Configures a basic subscription with a channel-specific token. ```swift let config = CentrifugeSubscriptionConfig( token: "sub-token" ) ``` -------------------------------- ### CentrifugeSubscriptionGetStateEvent Struct Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/API_SURFACE.md Represents an event to get the state of a subscription, including the channel name. ```swift public struct CentrifugeSubscriptionGetStateEvent - let channel: String ``` -------------------------------- ### Configure Client Authentication with JWT Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Set up client configuration with a JWT token for authentication. Includes a token getter for refreshing expired tokens. ```swift let config = CentrifugeClientConfig( token: "jwt-token-from-backend", tokenGetter: { event, completion in // Called when token expires fetchNewToken { token in completion(.success(token)) } } ) ``` -------------------------------- ### Install SwiftCentrifuge with CocoaPods Source: https://github.com/centrifugal/centrifuge-swift/blob/master/README.md Integrate SwiftCentrifuge into your Xcode project by adding this line to your Podfile. ```ruby pod 'SwiftCentrifuge' ``` -------------------------------- ### Handle CentrifugeConnectingEvent Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md Example of handling the CentrifugeConnectingEvent in the onConnecting delegate method. Logs the connecting code and reason. ```swift func onConnecting(_ client: CentrifugeClient, _ event: CentrifugeConnectingEvent) { print("Connecting: code=\(event.code), reason=\(event.reason)") // Show loading indicator, etc. } ``` -------------------------------- ### Handle CentrifugeDisconnectedEvent Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md Example of handling the CentrifugeDisconnectedEvent in the onDisconnected delegate method. Logs the disconnect code and reason. ```swift func onDisconnected(_ client: CentrifugeClient, _ event: CentrifugeDisconnectedEvent) { print("Disconnected: code=\(event.code), reason=\(event.reason)") // Handle cleanup, UI updates } ``` -------------------------------- ### Create and Subscribe to a Channel Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Create a new subscription to a channel and subscribe to it. Ensure the delegate is set for handling channel events. ```swift let sub = try client.newSubscription(channel: "updates", delegate: self) sub.subscribe() ``` -------------------------------- ### Convenience Method: info Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/LOGGER.md Logs a message at the info level. ```swift func info(_ message: @autoclosure () -> String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) ``` -------------------------------- ### Configure and Create Centrifuge Client Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Configure the Centrifuge client with authentication token and endpoint, then initialize it with a delegate. ```swift let config = CentrifugeClientConfig(token: "jwt-token") let client = CentrifugeClient( endpoint: "wss://example.com/connection/websocket?cf_protocol=protobuf", config: config, delegate: self ) ``` -------------------------------- ### Handle CentrifugeConnectedEvent Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/EVENTS.md Example of handling the CentrifugeConnectedEvent in the onConnected delegate method. Shows how to access client ID and server data. ```swift func onConnected(_ client: CentrifugeClient, _ event: CentrifugeConnectedEvent) { print("Connected with client ID: \(event.client)") if let data = event.data { let json = try? JSONSerialization.jsonObject(with: data) print("Server data: \(json ?? [:])") } // Update UI, start subscriptions, etc. } ``` -------------------------------- ### Get Existing Subscription Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Retrieves an existing subscription by its channel name. Returns nil if no subscription exists for the given channel. ```swift public func getSubscription(channel: String) -> CentrifugeSubscription? ``` ```swift if let sub = client.getSubscription(channel: "news") { print("Already subscribed to news") } ``` -------------------------------- ### Create SSLClientCertificate with custom import options Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SSL_CERTIFICATES.md This initializer allows for creating a certificate from a PKCS#12 URL while providing custom Security framework import options, such as specifying the passphrase directly in the options dictionary. ```swift let importOptions: CFDictionary = [ kSecImportExportPassphrase as String: "password" ] as CFDictionary let cert = try SSLClientCertificate( pkcs12Url: certURL, importOptions: importOptions ) ``` -------------------------------- ### Create and Subscribe to a Channel Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/QUICK_START.md Create a new subscription to a channel with its own delegate and then subscribe to receive real-time updates. ```swift class MySubscriptionDelegate: CentrifugeSubscriptionDelegate { func onSubscribed(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscribedEvent) { print("Subscribed to \(sub.channel)") } func onPublication(_ sub: CentrifugeSubscription, _ event: CentrifugePublicationEvent) { let json = try? JSONSerialization.jsonObject(with: event.data) print("Received: \(json ?? [:])") } func onError(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscriptionErrorEvent) { print("Subscription error: \(event.error)") } } do { let subDelegate = MySubscriptionDelegate() let sub = try client.newSubscription( channel: "updates", delegate: subDelegate ) sub.subscribe() } catch { print("Failed to create subscription: \(error)") } ``` -------------------------------- ### Securely Storing SSL Certificates Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SSL_CERTIFICATES.md Demonstrates how to load SSL client certificates from the app bundle or the documents directory. Ensure certificates are stored securely to protect sensitive information. ```swift // Store in app bundle (for embedded certs) if let certPath = Bundle.main.path(forResource: "client", ofType: "p12") { do { let cert = try SSLClientCertificate( pkcs12Path: certPath, password: "password" ) } catch { print("Error: \(error)") } } // Or load from documents directory let fileManager = FileManager.default let documentsURL = fileManager.urls( for: .documentDirectory, in: .userDomainMask )[0] let certURL = documentsURL.appendingPathComponent("client.p12") ``` -------------------------------- ### Configuration and Logging Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/INDEX.md Methods and types related to client configuration and custom logging. ```APIDOC ## Configuration and Logging ### `CentrifugeClientConfig` **Description**: Configuration object for the `CentrifugeClient`. Allows setting parameters like token, logger, and connection options. ### `CentrifugeLogger` Protocol **Description**: Protocol defining the interface for custom loggers. Implement this protocol to provide your own logging implementation. ### `CentrifugeLoggerLevel` Enum **Description**: Enum representing different log levels (e.g., `debug`, `info`, `error`). ``` -------------------------------- ### Complex Filter: String Patterns Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/FILTERING.md Apply filters based on string patterns, such as checking if a string starts with a prefix or contains a substring. ```swift // Exchange codes starting with "US" let filter = CentrifugeFilter.startsWith("exchange", "US") // Error messages containing "timeout" let filter = CentrifugeFilter.contains("message", "timeout") ``` -------------------------------- ### Handling Transport Error Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/ERRORS.md Example of catching a 'transportError', which signifies a failure or unexpected drop in the WebSocket connection. It prints the underlying error description. ```swift if case .transportError(let innerError) = error { print("Transport failed: \(innerError.localizedDescription)") } ``` -------------------------------- ### Convenience Method: warning Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/LOGGER.md Logs a message at the warning level. ```swift func warning(_ message: @autoclosure () -> String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) ``` -------------------------------- ### Subscription Configuration with Tags Filter and State Getter Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Configures a subscription with server-side filtering based on tags and a callback to load app state and stream position. ```swift let config = CentrifugeSubscriptionConfig( token: "sub-token", recoverable: true, tagsFilter: CentrifugeFilter.and([ CentrifugeFilter.eq("status", "active"), CentrifugeFilter.gte("price", "100") ]), stateGetter: { event, completion in // Load app's current state and stream position let position = database.getStreamPosition() let state = database.loadState() completion(.success(position)) } ) ``` -------------------------------- ### Customize Native WebSocket Transport with URLSessionConfiguration Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Example of providing a custom URLSessionConfiguration to CentrifugeClientConfig. This configuration sets waitsForConnectivity to true and configures a SOCKS proxy. ```swift let config = CentrifugeClientConfig( useNativeWebSocket: true, urlSessionConfigurationProvider: { let config = URLSessionConfiguration.default config.waitsForConnectivity = true config.connectionProxyDictionary = [ kCFProxyTypeKey: kCFProxyTypeSOCKS, kCFProxyHostNameKey: "proxy.example.com", kCFProxyPortNumberKey: 1080 ] return config } ) ``` -------------------------------- ### Centrifuge Client Initialization with Configuration Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Instantiates a Centrifuge client using a specified endpoint and a custom configuration object. ```swift let client = CentrifugeClient( endpoint: "wss://example.com/connection/websocket?cf_protocol=protobuf", config: config, delegate: self ) ``` -------------------------------- ### Retrieve Channel Presence Information Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/TYPES.md Demonstrates how to fetch presence information for a given channel and iterate through the connected clients. Handles potential errors during the presence retrieval. ```swift client.presence(channel: "users") { result in switch result { case .success(let presenceResult): for (clientId, info) in presenceResult.presence { print("Client \(clientId): user=\(info.user)") } case .failure(let error): print("Error: \(error)") } } ``` -------------------------------- ### presence Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SUBSCRIPTION.md Gets current presence information for this channel, including connected clients and their associated data. Results are returned asynchronously via a completion callback. ```APIDOC ## presence ### Description Gets current presence information for this channel (connected clients and their info). ### Method `presence(completion:)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```swift sub.presence { result in switch result { case .success(let presenceResult): print("Clients in channel: \(presenceResult.presence.count)") for (clientId, info) in presenceResult.presence { print("User: \(info.user), Client: \(clientId)") } case .failure(let error): print("Error: \(error)") } } ``` ### Response #### Success Response `CentrifugePresenceResult` containing presence data. #### Response Example (See Request Example for structure) ``` -------------------------------- ### CentrifugeClientConfig Initialization Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Initializes the Centrifuge client with various configuration options. Defaults are provided for most parameters. ```swift public init( timeout: Double = 5.0, headers: [String : String] = [:] tlsSkipVerify: Bool = false, minReconnectDelay: Double = 0.5, maxReconnectDelay: Double = 20.0, maxServerPingDelay: Double = 10.0, name: String = "swift", version: String = "", token: String = "", data: Data? = nil, debug: Bool = false, useNativeWebSocket: Bool = false, urlSessionConfigurationProvider: URLSessionConfigurationProvider? = nil, tokenGetter: CentrifugeConnectionTokenGetter? = nil, logger: CentrifugeLogger? = nil ) ``` -------------------------------- ### Create SSLClientCertificate from PKCS#12 URL Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SSL_CERTIFICATES.md This initializer creates a certificate from a PKCS#12 file specified by a URL. It's useful when the certificate file is managed within the application's accessible directories. ```swift let documentURL = try FileManager.default.url( for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false ) let certURL = documentURL.appendingPathComponent("client.p12") do { let cert = try SSLClientCertificate( pkcs12Url: certURL, password: "password" ) } catch { print("Certificate error: \(error)") } ``` -------------------------------- ### CentrifugeClient Initialization Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/API_SURFACE.md Initializes a new CentrifugeClient. Requires an endpoint URL, configuration, and a delegate to handle client events. ```swift init(endpoint:config:delegate:) ``` -------------------------------- ### Implement Delegate Callbacks for Lifecycle Events Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Implement delegate methods to respond to lifecycle events such as connection established and message publications. ```swift func onConnected(_ client: CentrifugeClient, _ event: CentrifugeConnectedEvent) { print("Connected with ID: \(event.client)") } func onPublication(_ sub: CentrifugeSubscription, _ event: CentrifugePublicationEvent) { print("Received: offset=\(event.offset)") } ``` -------------------------------- ### Basic CentrifugeClient Configuration Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CONFIGURATION.md Creates a basic Centrifuge client configuration with a custom timeout and authentication token. ```swift // Basic configuration let config = CentrifugeClientConfig( timeout: 10.0, token: "my-jwt-token" ) ``` -------------------------------- ### presenceStats(channel:completion:) Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Gets aggregated presence statistics, including unique user and client counts, for a specified channel. This method is asynchronous and uses a completion callback. ```APIDOC ## presenceStats(channel:completion:) ### Description Gets aggregated presence statistics (unique user and client counts) for a channel. ### Method Swift Function Call ### Parameters #### Path Parameters - **channel** (String) - Required - Channel name #### Query Parameters - **completion** (Result) -> () - Required - Callback with stats ### Response #### Success Response - **numClients** (Int) - The total number of connected clients. - **numUsers** (Int) - The total number of unique users. ### Example ```swift client.presenceStats(channel: "users") { result in switch result { case .success(let stats): print("Total clients: \(stats.numClients), Total users: \(stats.numUsers)") case .failure(let error): print("Failed: \(error)") } } ``` ``` -------------------------------- ### Convenience Methods Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/LOGGER.md Convenience methods provided by protocol extensions for each log level, simplifying the logging process. ```APIDOC ## Protocol Extensions (Convenience Methods) The protocol provides convenient methods for each log level: ### trace(_:file:function:line:) #### Description Log at trace level (most verbose). #### Declaration ```swift func trace(_ message: @autoclosure () -> String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) ``` ### debug(_:file:function:line:) #### Description Log at debug level. #### Declaration ```swift func debug(_ message: @autoclosure () -> String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) ``` ### info(_:file:function:line:) #### Description Log at info level. #### Declaration ```swift func info(_ message: @autoclosure () -> String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) ``` ### warning(_:file:function:line:) #### Description Log at warning level. #### Declaration ```swift func warning(_ message: @autoclosure () -> String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) ``` ### error(_:file:function:line:) #### Description Log at error level (least verbose). #### Declaration ```swift func error(_ message: @autoclosure () -> String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) ``` ``` -------------------------------- ### Retrieve Channel Publication History Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Use this function to fetch past publications from a channel. You can specify a limit, a starting point (since), and whether to retrieve them in reverse order. ```swift public func history( channel: String, limit: Int32 = 0, since: CentrifugeStreamPosition? = nil, reverse: Bool = false, completion: @escaping (Result) -> () ) ``` ```swift client.history(channel: "news", limit: 50, reverse: true) { result in switch result { case .success(let historyResult): print("Retrieved \(historyResult.publications.count) publications") print("Current offset: \(historyResult.offset), epoch: \(historyResult.epoch)") case .failure(let error): print("Failed: \(error)") } } ``` -------------------------------- ### Handle Connecting State Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/DELEGATES.md Use this method to observe the client entering the connecting state. It provides codes for specific reasons like user-initiated connects or transport closures. ```swift func onConnecting(_ client: CentrifugeClient, _ event: CentrifugeConnectingEvent) { if event.code == 0 { // connectingCodeConnectCalled print("User initiated connect") } else if event.code == 1 { // connectingCodeTransportClosed print("Transport closed, attempting reconnect") } } ``` -------------------------------- ### CentrifugeClient Initialization Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Initializes a new Centrifuge client instance with the specified endpoint, configuration, and an optional delegate. ```APIDOC ## init(endpoint:config:delegate:) ### Description Creates a new Centrifuge client instance. ### Parameters #### Path Parameters - **endpoint** (String) - Required - WebSocket endpoint URL (protobuf). Format: `ws://host:port/connection/websocket?cf_protocol=protobuf` or `wss://...` for TLS - **config** (CentrifugeClientConfig) - Required - Client configuration object with auth tokens, timeouts, and connection settings - **delegate** (CentrifugeClientDelegate?) - Optional - Delegate object to receive client events (connected, disconnected, errors, publications) ### Request Example ```swift let config = CentrifugeClientConfig( timeout: 5.0, token: "jwt-auth-token", debug: true ) let client = CentrifugeClient( endpoint: "ws://localhost:8000/connection/websocket?cf_protocol=protobuf", config: config, delegate: self ) ``` ``` -------------------------------- ### Get Channel Presence Statistics Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/SUBSCRIPTION.md Retrieve aggregated statistics for a channel, including the total number of unique clients and users. The completion handler receives either the statistics or an error. ```swift sub.presenceStats { result in switch result { case .success(let stats): print("Clients: \(stats.numClients), Users: \(stats.numUsers)") case .failure(let error): print("Error: \(error)") } } ``` -------------------------------- ### Enable Debug Logging Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/README.md Enable debug mode and provide a custom logger in the client configuration for detailed logging. ```swift let config = CentrifugeClientConfig( debug: true, logger: MyLogger() ) ``` -------------------------------- ### onSubscribing Event Handler Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/DELEGATES.md Implement this method to handle the event when a subscription enters the .subscribing state. It provides a code and reason for entering this state. ```swift func onSubscribing(_ sub: CentrifugeSubscription, _ event: CentrifugeSubscribingEvent) ``` -------------------------------- ### history(channel:limit:since:reverse:completion:) Source: https://github.com/centrifugal/centrifuge-swift/blob/master/_autodocs/CLIENT.md Retrieves historical publications for a channel with options to limit the number of results, specify a starting point, and control the order of retrieval. ```APIDOC ## history(channel:limit:since:reverse:completion:) ### Description Retrieves publication history for a channel. ### Method Swift Function Call ### Parameters #### Path Parameters - **channel** (String) - Required - Channel name - **limit** (Int32) - Optional - Max publications to return. 0 means no limit. Defaults to 0. - **since** (CentrifugeStreamPosition?) - Optional - Stream position to retrieve from. nil starts from beginning. - **reverse** (Bool) - Optional - If true, returns latest publications first. Defaults to false. #### Query Parameters - **completion** (Result) -> () - Required - Callback with history data ### Response #### Success Response - **publications** (Array) - An array of historical publications. - **offset** (Int) - The offset for the next retrieval. - **epoch** (String) - The epoch of the history retrieval. ### Example ```swift client.history(channel: "news", limit: 50, reverse: true) { result in switch result { case .success(let historyResult): print("Retrieved \(historyResult.publications.count) publications") print("Current offset: \(historyResult.offset), epoch: \(historyResult.epoch)") case .failure(let error): print("Failed: \(error)") } } ``` ```