Socket.IO-Client-Swift

repository·master·Indexed 26 days ago

https://github.com/socketio/socket.io-client-swift

A client-side library for iOS and macOS enabling real-time, bidirectional communication with Socket.IO servers. It supports server versions 2.0 through 4.0+, binary data, polling, WebSockets, and TLS/SSL. The library utilizes a SocketManager to handle connections and namespaces, ensuring efficient transport sharing. Installation is supported via Swift Package Manager, Carthage, and CocoaPods.

Tokens
2.6K
Snippets
9
Records
12
Agent score
90%

What's inside Socket.IO-Client-Swift

  1. Install Socket.IO-Client-Swift via Carthage

    master

    Add the following line to your Cartfile:

    github "socketio/socket.io-client-swift" ~> 16.1.1

    Then run carthage update --platform ios,macosx. You must add both the Starscream and SocketIO frameworks to your project following the standard Carthage integration process.

    github "socketio/socket.io-client-swift" ~> 16.1.1
  2. Upgrade from v15 to v16

    master

    To upgrade from version 15 to version 16, follow these steps to ensure compatibility with your Socket.IO server:

    1. Upgrade the Socket.IO server to v4 and enable compatibility mode by setting allowEIO3: true.
    2. Upgrade the clients to v16.
    3. Disable compatibility mode on the server once all clients have been successfully upgraded.

    Note: Objective-C is no longer supported in v16; you must use Swift.

  3. Upgrade from v12 to v13: Use SocketManager instead of SocketIOClient

    master

    In v13, the architecture changed to use a single engine per connection. Instead of creating multiple SocketIOClient instances (which would open multiple connections), you must now create a single SocketManager and use it to access different namespaces. This ensures that multiple namespaces share a single transport/connection.

    Key changes:

    • Replace direct SocketIOClient instantiation with SocketManager.
    • Use manager.defaultSocket for the default namespace (/).
    • Use manager.socket(forNamespace: "/name") to access specific namespaces.
    • SocketIOClient no longer accepts configuration; configuration is now managed by the SocketManager.
    // v13 approach
    let manager = SocketManager(socketURL: myURL)
    let defaultSocket = manager.defaultSocket
    let namespaceSocket = manager.socket(forNamespace: "/swift")
    
    // add handlers for sockets and connect
  4. Manage Socket Lifecycle with SocketManager

    master

    To prevent sockets from being released prematurely, you should maintain a strong reference to the SocketManager rather than individual SocketIOClient instances. The SocketManager automatically maintains strong references to the sockets it creates.

    Important behaviors:

    • Subsequent calls to socket(forNamespace:) return the same socket instance.
    • If you require multiple distinct sockets on the same namespace, you must use multiple SocketManager instances.
    • joinNamespace() and leaveNamespace() on SocketIOClient no longer take arguments and are often unnecessary; use connect() and disconnect() on the specific namespace socket instead.
    class Manager {
        let socketManager = SocketManager(socketURL: someURL)
        
        func addHandlers() {
            // The manager maintains the reference to this socket
            let socket = socketManager.socket(forNamespace: "/swift")
            
            // Add handlers
        }
    }
  5. Support Socket.IO v2 servers in v16

    master

    The Socket.IO-Client-Swift v16 client supports Socket.IO v3 servers by default. If your server is running Socket.IO v2, you must explicitly pass .version(.two) in the configuration options when initializing the SocketManager.

    SocketManager(socketURL: URL(string:"http://localhost:8087/")!, config: [.version(.two)])
  6. Install Socket.IO-Client-Swift via Swift Package Manager

    master

    Add the repository as a dependency in your Package.swift file. Ensure you specify the version requirement (e.g., .upToNextMinor(from: "16.1.1")). After adding the dependency, import the module using import SocketIO in your Swift files.

    // swift-tools-version:4.2
    
    import PackageDescription
    
    let package = Package(
        name: "socket.io-test",
        products: [
            .executable(name: "socket.io-test", targets: ["YourTargetName"])
        ],
        dependencies: [
            .package(url: "https://github.com/socketio/socket.io-client-swift", .upToNextMinor(from: "16.1.1"))
        ],
        targets: [
            .target(name: "YourTargetName", dependencies: ["SocketIO"], path: "./Path/To/Your/Sources")
        ]
    )
  7. Install Socket.IO-Client-Swift via CocoaPods

    master

    Add pod 'Socket.IO-Client-Swift', '~> 16.1.1' to your Podfile within your target block. Ensure use_frameworks! is present. Run pod install to complete the installation.

    In Swift, use import SocketIO. In Objective-C, use @import SocketIO;.

    use_frameworks!
    
    target 'YourApp' do
        pod 'Socket.IO-Client-Swift', '~> 16.1.1'
    end
  8. Verify server compatibility for Socket.IO-Client-Swift

    master
    Ensure your server implements the Socket.IO protocol. This library is NOT a plain WebSockets client. If your server only supports standard WebSockets and not the Socket.IO protocol, this library will not work. For plain WebSocket support, consider using Starscream (Swift) or JetFire (Objective-C).
  9. Prevent event handlers from failing due to ARC memory release

    master

    If your event handlers (e.g., .on("eventName")) are not being called, ensure that your SocketManager instance is being retained in memory. If you initialize the manager inside a local function scope, it will be released by Automatic Reference Counting (ARC) as soon as the function finishes, causing the socket to disconnect and handlers to fail.

    To fix this, store the SocketManager as a property of a long-lived class (like a Manager or ViewController) rather than a local variable within a method.

    // INCORRECT: manager is local to the function and will be released immediately
    class Manager {
        func addHandlers() {
            let manager = SocketManager(socketURL: URL(string: "http://somesocketioserver.com")!)
            
            manager.defaultSocket.on("myEvent") {data, ack in
                print(data)
            }
        }
    }
    
    // CORRECT: manager is a class property and stays in memory
    class Manager {
        let manager = SocketManager(socketURL: URL(string: "http://somesocketioserver.com")!)
        
        func addHandlers() {
            manager.defaultSocket.on("myEvent") {data, ack in
                print(data)
            }
        }
    }
  10. Basic usage of SocketManager and SocketIO

    master

    To use the client, initialize a SocketManager with a socketURL and an optional configuration array (e.g., .log(true), .compress). Access the connection via manager.defaultSocket. You can listen for events using .on(clientEvent:) for system events like .connect, or .on("eventName") for custom server events. Use .emit() to send data and .emitWithAck() for acknowledgments.

    import SocketIO
    
    let manager = SocketManager(socketURL: URL(string: "http://localhost:8080")!, config: [.log(true), .compress])
    let socket = manager.defaultSocket
    
    socket.on(clientEvent: .connect) {data, ack in
        print("socket connected")
    }
    
    socket.on("currentAmount") {data, ack in
        guard let cur = data[0] as? Double else { return }
        
        socket.emitWithAck("canUpdate", cur).timingOut(after: 0) {data in
            if data.first as? String ?? "passed" == SocketAckStatus.noAck {
                // Handle ack timeout 
            }
    
            socket.emit("update", ["amount": cur + 2.50])
        }
    
        ack.with("Got your currentAmount", "dude")
    }
    
    socket.connect()
  11. Check Socket.IO connection protocol version on the server

    master

    You can determine the protocol version of a connection on the server side by checking socket.conn.protocol.

    • A value of 3 indicates the 3rd revision of the protocol (Socket.IO v2).
    • A value of 4 indicates the 4th revision of the protocol (Socket.IO v3/v4).
    io.on("connection", (socket) => {
      // either 3 for the 3rd revision of the protocol (Socket.IO v2) or 4 for the 4th revision (Socket.IO v3/v4)
      const version = socket.conn.protocol;
    });
  12. Connect to the Server and Namespaces

    master

    You can initiate connections by calling connect() on either the SocketManager or an individual SocketIOClient.

    Connection behaviors:

    • Calling connect() on the SocketManager: Opens the connection to the server. However, only the default socket (/) will automatically connect to its namespace. Other namespace-specific sockets will require individual connect() calls.
    • Calling connect() on a SocketIOClient: If the manager is not connected, it will open the connection to the server, then connect the specific client to its namespace and fire a connect event.
    • In both cases, the default socket (/) will fire a connect event.