ios 从Web套接字数组中删除特定的WebSocket

dkqlctbz  于 2022-11-26  发布在  iOS
关注(0)|答案(1)|浏览(104)

我有一个元组数组:

private var clientsConnections = [ (String,[WebSocket]) ]()
    • String**:文件室的ID
  • *[网络套接字]**:该房间中用户的websockets

我尝试关闭房间内特定WebSocket的连接,比如说当用户退出房间时,并从我的阵列中删除该WebSocket。我遇到的问题是WebSocket无法转换为AnyHashable。
我尝试过:

ws.onClose.whenComplete { _ in
  for i in 0..<clientsConnections.count {
     if clientsConnections[i].0 == roomID {
       if let socketIndex = clientsConnections[i].1.firstIndex(where: {$0 == ws}) {
          clientsConnections[i].1.remove(at: socketIndex)
       }
     }
  }
}

获取此信息:(右下方声明:"{$0 == ws}"
'WebSocket'无法转换为'AnyHashable'

j5fpnvbx

j5fpnvbx1#

我会用字典如果使用键引用WebSocket,则它不必符合Hashable
我已经在我和Swift一起做的一个辅助项目中实现了它。
下面是一个精心挑选的实现:

actor ChatWebSocketManager: WebSocketManager {
    var clients: ChatWebSocketClients

    init(eventLoop: EventLoop) {
        clients = ChatWebSocketClients(eventLoop: eventLoop)
    }

    func connect(_ request: Request, _ webSocket: WebSocket) {
        webSocket.onBinary { webSocket, buffer async -> () in
            // Handle data from client connection on server
        }
    }
}

actor ChatWebSocketClients {
    var storage: [UUID: ChatWebSocketClient] // <~ Money shot
    var eventLoop: EventLoop

    init(eventLoop: EventLoop, clients: [UUID: ChatWebSocketClient] = [:]) {
        self.eventLoop = eventLoop
        storage = clients
    }

    deinit {
        let futures = self.storage.values
            .map {
                $0.socket.close()
            }
        do {
            try self.eventLoop.flatten(futures).wait()
        } catch {
            print("Failed to flatten WebSocket futures:", error)
            assertionFailure("Failed to flatten WebSocket futures")
        }
    }
    
    func active() -> [UUID: ChatWebSocketClient] {
        storage.filter({ !$0.value.socket.isClosed })
    }

    func add(_ client: ChatWebSocketClient) throws {
        storage[client.id] = client
    }

    func remove(clientId: UUID) {
        storage.removeValue(forKey: clientId)
    }

    func getConnectedClients(for chatId: UUID) -> [UUID: ChatWebSocketClient] {
        active().filter({ $0.value.chatId == chatId })
    }
}

open class ChatWebSocketClient {
    open var id: UUID
    open var userId: UUID
    open var chatId: UUID
    open var socket: WebSocket
    
    required public init(id: UUID, userId: UUID, chatId: UUID, socket: WebSocket) {
        self.id = id
        self.userId = userId
        self.chatId = chatId
        self.socket = socket
    }
}

然后在configure.swift文件中:

public func configure(_ app: Application) throws {
    // Configure Database
    // ...

    // Register Routes
    // ...

    // Set up WebSocket endpoint
    let chatWebSocketManager = ChatWebSocketManager(eventLoop: app.eventLoopGroup.next())
    app
        .grouped(SessionToken.authenticator(), SessionToken.guardMiddleware())
        .webSocket("chats", ":chatId") { request, webSocket async in
            await chatWebSocketManager.connect(request, webSocket)
        }
}

相关问题