Search code examples
swiftwebsocketstarscream

How to make a Singleton Manager Class of Starscream in Web-socket


How can i make a single class manager of starscream web sockets in swift. Kindly help me out how can i do that to get request and response just by managing singleton class manager.

Because i want to use sockets over the app in many views and there child views, it's not good practice i can initiate delegate method on every class and get request and response.

One more question how can i authenticate using websockets format is:

{'UsernameAuth':'Username', 'PasswordAuth':'Password'}

Kindly help me out.

Thanks


Solution

  • Singletones in Swift are quite trivial. Create a separate Swift file: WSHub.swift

    Hub is supposed to deliver messages to observers.

    import Srascream
    
    @objc protocol WSHubObserver: class {
        optional func wsHub(_ hub: WSHub, receivedText: String)
        optional func wsHub(_ hub: WSHub, receivedJsonDic: [String: Any])
        optional func wsHub(_ hub: WSHub, receivedJsonArray: [Any])
    }
    
    class WSHub: NSObject {
        static let shared = WSHub()
        private(set) var webSocket: WebSocket
        // Note these observers are referenced and instances will not die unless removed from observers or you can wrap them into WeakRef struct
        private var observers: [WSHubObserver] = []
    
        private init() { 
            self.webSocket = WebSocket(... some URL or URLRequest here...)
            super.init() 
            self.websocket.onText = { [weak self] (text) in 
                self?.handleText(text)
            }
        }
    
        public func addObserver(_ observer: WSHubObserver) {
            self.observers.append(observer)        
        }
    
        public func addObserver(_ observer: WSHubObserver) {
            if let index = self.objservers.index(observer) {
                self.observers.remove(at: index)
            }
        }
    
        private func handleText(_ text: String) {
            self.observers.forEach { observer in
                observer.wsHub?(self, receivedText: text)
            }
            if let data = text.data(using: .utf8),
            let object = try? JSONSerialization.jsonObject(with: data, options: []) {
                if let dic = object as? [String : Any] { 
                    observer.wsHub?(self, receivedJsonDic: dic)
                } else if let arr = object as? [Any] { 
                    observer.wsHub?(self, receivedJsonArray: arr)
                }
            }
        }
    }
    

    Then you can use lazily-initialized singleton at any place in your code WSHub.shared.webSocket.send(...)

    Authorization part depends on server. It may be separate URLRequest to some https:// url with POST of json data, then you may get response with header Set-Cookie. And when you are going to connect to websocket, you may create URLRequest and do request.set(someCookieString, for: "Cookie") and then server may let you into ws pipe.

    I doubt you should sent login/pass every tme you connect as it is bad fashion to store user credentials inside of app, so you should be based on session.

    And then your handler:

    class SomeWsHubSmallClass: NSObject, WSHubObserver {
        func wsHub(_ hub: WSHub, receivedText: String) {
        }
        func wsHub(_ hub: WSHub, receivedJsonDic: [String: Any]) {
        }
        func wsHub(_ hub: WSHub, receivedJsonArray: [Any]) {
        }
    }
    
    let object = SomeWsHubSmallClass()
    WSHub.shared.addObserver(object)