Search code examples
jsonswiftsocket.iojsondecoder

Swift: How to use response from SocketIO emitWithAck method


I'm using the SocketIO library to connect my iOS app to my server. I want to emit some data to the server and get a json dictionary back in the acknowledgment. I currently have something like this:

SocketHandler.mySocket.emitWithAck("my_event", [session, someInput]).timingOut(after: 3) {data in

       let myData = try? JSONDecoder().decode(myStruct.self, from: data)

MyStruct is defined as Class inheriting from Decodable and resembles the structure of the json I expect.

I get the following error: Cannot convert value of type 'Any' to expected argument type 'Data'

Any idea how I can tackle that type casting? Or would I need to go a totally other route?

(Swift 4.1 for iOS 11.3)

Cheers!


Solution

  • There're two things:

    1. decode(_:from:) accepts a Data as a second parameter. To be able to decode from Any you'll need to add an extension to first serialize the data and then pass it to JSONDecoder, like this:

      extension Decodable {
        init(from any: Any) throws {
          let data = try JSONSerialization.data(withJSONObject: any)
          self = try JSONDecoder().decode(Self.self, from: data)
        }
      }
      
    2. AckCallback's parameter is of an array type (i.e. [Any]), so you should get the first element of that array.

    To make sure that you have indeed a decodable data (a dictionary or a JSON object) you can write something like this:

    SocketHandler.mySocket.emitWithAck("my_event", [session, someInput]).timingOut(after: 3) { data in
      guard let dict = data.first as? [String: Any] else { return }
      let myData = try? myStruct(from: dict)
      // ...
    }