Swift: 如何使用来自 SocketIO emitWithAck 方法的响应
Swift: How to use response from SocketIO emitWithAck method
我正在使用 SocketIO 库将我的 iOS 应用程序连接到我的服务器。
我想向服务器发送一些数据并在确认中返回一个 json 字典。我目前有这样的东西:
SocketHandler.mySocket.emitWithAck("my_event", [session, someInput]).timingOut(after: 3) {data in
let myData = try? JSONDecoder().decode(myStruct.self, from: data)
MyStruct 被定义为 Class 继承自 Decodable 并且类似于我期望的 json 的结构。
我收到以下错误:无法将类型 'Any' 的值转换为预期的参数类型 'Data'
知道如何处理该类型转换吗?或者我需要走完全不同的路线吗?
(Swift 4.1 对于 iOS 11.3)
干杯!
有两件事:
decode(_:from:)
接受 Data
作为第二个参数。为了能够从 Any
解码,您需要添加扩展以首先序列化数据,然后将其传递给 JSONDecoder
,如下所示:
extension Decodable {
init(from any: Any) throws {
let data = try JSONSerialization.data(withJSONObject: any)
self = try JSONDecoder().decode(Self.self, from: data)
}
}
AckCallback
的参数是数组类型(即[Any]
),所以应该得到数组的第一个元素。
为了确保您确实拥有可解码的数据(字典或 JSON 对象),您可以这样写:
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)
// ...
}
如果有人想知道如何将 SocketIO 与 Decodable 一起使用,我根据 Dan Karbayev 的回答为客户端创建了一个小扩展以在回调中接受 Decodable。
import Foundation
import SocketIO
extension Decodable {
init(from any: Any) throws {
let data = try JSONSerialization.data(withJSONObject: any)
self = try JSONDecoder().decode(Self.self, from: data)
}
}
extension SocketIOClient {
func on<T: Decodable>(_ event: String, callback: @escaping (T)-> Void) {
self.on(event) { (data, _) in
guard !data.isEmpty else {
print("[SocketIO] \(event) data empty")
return
}
guard let decoded = try? T(from: data[0]) else {
print("[SocketIO] \(event) data \(data) cannot be decoded to \(T.self)")
return
}
callback(decoded)
}
}
}
用法:
socket.on("location") { (data: LocationEventData) in
// ...
}
socket.on("success") { (name: String) in
// ...
}
其中 LocationEventData
和 String
是 Decodable
。
我正在使用 SocketIO 库将我的 iOS 应用程序连接到我的服务器。 我想向服务器发送一些数据并在确认中返回一个 json 字典。我目前有这样的东西:
SocketHandler.mySocket.emitWithAck("my_event", [session, someInput]).timingOut(after: 3) {data in
let myData = try? JSONDecoder().decode(myStruct.self, from: data)
MyStruct 被定义为 Class 继承自 Decodable 并且类似于我期望的 json 的结构。
我收到以下错误:无法将类型 'Any' 的值转换为预期的参数类型 'Data'
知道如何处理该类型转换吗?或者我需要走完全不同的路线吗?
(Swift 4.1 对于 iOS 11.3)
干杯!
有两件事:
decode(_:from:)
接受Data
作为第二个参数。为了能够从Any
解码,您需要添加扩展以首先序列化数据,然后将其传递给JSONDecoder
,如下所示:extension Decodable { init(from any: Any) throws { let data = try JSONSerialization.data(withJSONObject: any) self = try JSONDecoder().decode(Self.self, from: data) } }
AckCallback
的参数是数组类型(即[Any]
),所以应该得到数组的第一个元素。
为了确保您确实拥有可解码的数据(字典或 JSON 对象),您可以这样写:
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)
// ...
}
如果有人想知道如何将 SocketIO 与 Decodable 一起使用,我根据 Dan Karbayev 的回答为客户端创建了一个小扩展以在回调中接受 Decodable。
import Foundation
import SocketIO
extension Decodable {
init(from any: Any) throws {
let data = try JSONSerialization.data(withJSONObject: any)
self = try JSONDecoder().decode(Self.self, from: data)
}
}
extension SocketIOClient {
func on<T: Decodable>(_ event: String, callback: @escaping (T)-> Void) {
self.on(event) { (data, _) in
guard !data.isEmpty else {
print("[SocketIO] \(event) data empty")
return
}
guard let decoded = try? T(from: data[0]) else {
print("[SocketIO] \(event) data \(data) cannot be decoded to \(T.self)")
return
}
callback(decoded)
}
}
}
用法:
socket.on("location") { (data: LocationEventData) in
// ...
}
socket.on("success") { (name: String) in
// ...
}
其中 LocationEventData
和 String
是 Decodable
。