From f9d8595a25bf239d78cfec4639558b5888afcde1 Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 29 Sep 2018 15:47:30 +0700 Subject: [PATCH 01/13] add optional write completion handler for emit's --- Source/SocketIO/Client/SocketIOClient.swift | 19 +++++++++--- Source/SocketIO/Engine/SocketEngine.swift | 30 +++++++++++-------- .../Engine/SocketEnginePollable.swift | 20 ++++++++----- Source/SocketIO/Engine/SocketEngineSpec.swift | 9 +++--- .../Engine/SocketEngineWebsocket.swift | 10 ++++--- Source/SocketIO/Manager/SocketManager.swift | 2 +- Source/SocketIO/Util/SocketTypes.swift | 5 +++- Tests/TestSocketIO/SocketMangerTest.swift | 2 +- Tests/TestSocketIO/SocketSideEffectTest.swift | 2 +- Tests/TestSocketIOObjc/SocketObjectiveCTest.m | 14 +++++++++ 10 files changed, 77 insertions(+), 36 deletions(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index 501fe30..ac7dbff 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -213,7 +213,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter items: The items to send with this event. May be left out. open func emit(_ event: String, _ items: SocketData...) { do { - try emit(event, with: items.map({ try $0.socketRepresentation() })) + try emit(event, with: items.map({ try $0.socketRepresentation() }), completion: {}) } catch { DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", type: logType) @@ -228,7 +228,17 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter items: The items to send with this event. Send an empty array to send no data. @objc open func emit(_ event: String, with items: [Any]) { - emit([event] + items) + emit([event] + items, completion: {}) + } + + /// Same as emit, but meant for Objective-C + /// + /// - parameter event: The event to send. + /// - parameter items: The items to send with this event. Send an empty array to send no data. + /// - parameter completion: Callback called on transport write completion. + @objc + open func emit(_ event: String, with items: [Any], completion: @escaping () -> ()) { + emit([event] + items, completion: completion) } /// Sends a message to the server, requesting an ack. @@ -284,8 +294,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { return createOnAck([event] + items) } - func emit(_ data: [Any], ack: Int? = nil, binary: Bool = true, isAck: Bool = false) { + func emit(_ data: [Any], ack: Int? = nil, binary: Bool = true, isAck: Bool = false, completion: (() -> ())? = nil) { guard status == .connected else { + completion?(); handleClientEvent(.error, data: ["Tried emitting when not connected"]) return } @@ -295,7 +306,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { DefaultSocketLogger.Logger.log("Emitting: \(str), Ack: \(isAck)", type: logType) - manager?.engine?.send(str, withData: packet.binary) + manager?.engine?.send(str, withData: packet.binary, completion: completion) } /// Call when you wish to tell the server that you've received the event for `ack`. diff --git a/Source/SocketIO/Engine/SocketEngine.swift b/Source/SocketIO/Engine/SocketEngine.swift index 738bf30..70bea00 100644 --- a/Source/SocketIO/Engine/SocketEngine.swift +++ b/Source/SocketIO/Engine/SocketEngine.swift @@ -49,7 +49,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So /// A queue of engine.io messages waiting for POSTing /// /// **You should not touch this directly** - public var postWait = [String]() + public var postWait = [Post]() /// `true` if there is an outstanding poll. Trying to poll before the first is done will cause socket.io to /// disconnect us. @@ -340,7 +340,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So if polling { disconnectPolling(reason: reason) } else { - sendWebSocketMessage("", withType: .close, withData: []) + sendWebSocketMessage("", withType: .close, withData: [], completion: {}) closeOutEngine(reason: reason) } } @@ -348,7 +348,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So // We need to take special care when we're polling that we send it ASAP // Also make sure we're on the emitQueue since we're touching postWait private func disconnectPolling(reason: String) { - postWait.append(String(SocketEnginePacketType.close.rawValue)) + postWait.append((String(SocketEnginePacketType.close.rawValue), {})) doRequest(for: createRequestForPostWithPostWait()) {_, _, _ in } closeOutEngine(reason: reason) @@ -366,7 +366,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So DefaultSocketLogger.Logger.log("Switching to WebSockets", type: SocketEngine.logType) - sendWebSocketMessage("", withType: .upgrade, withData: []) + sendWebSocketMessage("", withType: .upgrade, withData: [], completion: {}) polling = false fastUpgrade = false probing = false @@ -384,7 +384,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So DefaultSocketLogger.Logger.log("Flushing probe wait", type: SocketEngine.logType) for waiter in probeWait { - write(waiter.msg, withType: waiter.type, withData: waiter.data) + write(waiter.msg, withType: waiter.type, withData: waiter.data, completion:waiter.completion) } probeWait.removeAll(keepingCapacity: false) @@ -398,7 +398,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So guard let ws = self.ws else { return } for msg in postWait { - ws.write(string: msg) + ws.write(string: msg.msg, completion: msg.completion) } postWait.removeAll(keepingCapacity: false) @@ -544,7 +544,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So } pongsMissed += 1 - write("", withType: .ping, withData: []) + write("", withType: .ping, withData: [], completion: {}) engineQueue.asyncAfter(deadline: DispatchTime.now() + .milliseconds(pingInterval)) {[weak self, id = self.sid] in // Make sure not to ping old connections @@ -600,7 +600,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So DefaultSocketLogger.Logger.log("Upgrading transport to WebSockets", type: SocketEngine.logType) fastUpgrade = true - sendPollMessage("", withType: .noop, withData: []) + sendPollMessage("", withType: .noop, withData: [], completion: {}) // After this point, we should not send anymore polling messages } } @@ -610,11 +610,15 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So /// - parameter msg: The message to send. /// - parameter type: The type of this message. /// - parameter data: Any data that this message has. - open func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) { + /// - parameter completion: Callback called on transport write completion. + open func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping () -> ()) { engineQueue.async { - guard self.connected else { return } + guard self.connected else { + completion() + return + } guard !self.probing else { - self.probeWait.append((msg, type, data)) + self.probeWait.append((msg, type, data, completion)) return } @@ -622,11 +626,11 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So if self.polling { DefaultSocketLogger.Logger.log("Writing poll: \(msg) has data: \(data.count != 0)", type: SocketEngine.logType) - self.sendPollMessage(msg, withType: type, withData: data) + self.sendPollMessage(msg, withType: type, withData: data, completion: completion) } else { DefaultSocketLogger.Logger.log("Writing ws: \(msg) has data: \(data.count != 0)", type: SocketEngine.logType) - self.sendWebSocketMessage(msg, withType: type, withData: data) + self.sendWebSocketMessage(msg, withType: type, withData: data, completion: completion) } } } diff --git a/Source/SocketIO/Engine/SocketEnginePollable.swift b/Source/SocketIO/Engine/SocketEnginePollable.swift index faec93a..29a40bf 100644 --- a/Source/SocketIO/Engine/SocketEnginePollable.swift +++ b/Source/SocketIO/Engine/SocketEnginePollable.swift @@ -34,7 +34,7 @@ public protocol SocketEnginePollable : SocketEngineSpec { /// A queue of engine.io messages waiting for POSTing /// /// **You should not touch this directly** - var postWait: [String] { get set } + var postWait: [Post] { get set } /// The URLSession that will be used for polling. var session: URLSession? { get } @@ -65,7 +65,7 @@ public protocol SocketEnginePollable : SocketEngineSpec { /// - parameter message: The message to send. /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. - func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) + func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) /// Call to stop polling and invalidate the URLSession. func stopPolling() @@ -74,12 +74,15 @@ public protocol SocketEnginePollable : SocketEngineSpec { // Default polling methods extension SocketEnginePollable { func createRequestForPostWithPostWait() -> URLRequest { - defer { postWait.removeAll(keepingCapacity: true) } + defer { + for packet in postWait { packet.completion() } + postWait.removeAll(keepingCapacity: true) + } var postStr = "" for packet in postWait { - postStr += "\(packet.utf16.count):\(packet)" + postStr += "\(packet.msg.utf16.count):\(packet.msg)" } DefaultSocketLogger.Logger.log("Created POST string: \(postStr)", type: "SocketEnginePolling") @@ -209,14 +212,17 @@ extension SocketEnginePollable { /// - parameter message: The message to send. /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. - public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) { + /// - parameter completion: Callback called on transport write completion. + public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) { DefaultSocketLogger.Logger.log("Sending poll: \(message) as type: \(type.rawValue)", type: "SocketEnginePolling") - postWait.append(String(type.rawValue) + message) + postWait.append((String(type.rawValue) + message, completion)) for data in datas { if case let .right(bin) = createBinaryDataForSend(using: data) { - postWait.append(bin) + // completion handler will be called on initial message write + // TODO: call completion after last message in batch + postWait.append((bin, {})) } } diff --git a/Source/SocketIO/Engine/SocketEngineSpec.swift b/Source/SocketIO/Engine/SocketEngineSpec.swift index 4078535..c7b073c 100644 --- a/Source/SocketIO/Engine/SocketEngineSpec.swift +++ b/Source/SocketIO/Engine/SocketEngineSpec.swift @@ -137,7 +137,8 @@ import Starscream /// - parameter msg: The message to send. /// - parameter type: The type of this message. /// - parameter data: Any data that this message has. - func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) + /// - parameter completion: Callback called on transport write completion. + func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping () -> ()) } extension SocketEngineSpec { @@ -162,7 +163,7 @@ extension SocketEngineSpec { if !cookiesToAdd.isEmpty { req.allHTTPHeaderFields = HTTPCookie.requestHeaderFields(with: cookiesToAdd) } - + if let extraHeaders = extraHeaders { for (headerName, value) in extraHeaders { req.setValue(value, forHTTPHeaderField: headerName) @@ -179,7 +180,7 @@ extension SocketEngineSpec { } /// Send an engine message (4) - func send(_ msg: String, withData datas: [Data]) { - write(msg, withType: .message, withData: datas) + func send(_ msg: String, withData datas: [Data], completion: (() -> ())? = nil) { + write(msg, withType: .message, withData: datas, completion: completion ?? {}) } } diff --git a/Source/SocketIO/Engine/SocketEngineWebsocket.swift b/Source/SocketIO/Engine/SocketEngineWebsocket.swift index 6dc11ac..b3fad5e 100644 --- a/Source/SocketIO/Engine/SocketEngineWebsocket.swift +++ b/Source/SocketIO/Engine/SocketEngineWebsocket.swift @@ -37,14 +37,15 @@ public protocol SocketEngineWebsocket : SocketEngineSpec { /// - parameter message: The message to send. /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. - func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data]) + /// - parameter completion: Callback called on transport write completion. + func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) } // WebSocket methods extension SocketEngineWebsocket { func probeWebSocket() { if ws?.isConnected ?? false { - sendWebSocketMessage("probe", withType: .ping, withData: []) + sendWebSocketMessage("probe", withType: .ping, withData: [], completion: {}) } } @@ -55,14 +56,15 @@ extension SocketEngineWebsocket { /// - parameter message: The message to send. /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. - public func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data]) { + /// - parameter completion: Callback called on transport write completion. + public func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) { DefaultSocketLogger.Logger.log("Sending ws: \(str) as type: \(type.rawValue)", type: "SocketEngineWebSocket") ws?.write(string: "\(type.rawValue)\(str)") for data in datas { if case let .left(bin) = createBinaryDataForSend(using: data) { - ws?.write(data: bin) + ws?.write(data: bin, completion: completion) } } } diff --git a/Source/SocketIO/Manager/SocketManager.swift b/Source/SocketIO/Manager/SocketManager.swift index 126aec1..ed6ae14 100644 --- a/Source/SocketIO/Manager/SocketManager.swift +++ b/Source/SocketIO/Manager/SocketManager.swift @@ -290,7 +290,7 @@ open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDa /// - parameter items: The data to send with this event. open func emitAll(_ event: String, withItems items: [Any]) { forAll {socket in - socket.emit(event, with: items) + socket.emit(event, with: items, completion: {}) } } diff --git a/Source/SocketIO/Util/SocketTypes.swift b/Source/SocketIO/Util/SocketTypes.swift index bbc1b6d..f8cdc05 100644 --- a/Source/SocketIO/Util/SocketTypes.swift +++ b/Source/SocketIO/Util/SocketTypes.swift @@ -73,8 +73,11 @@ public typealias AckCallback = ([Any]) -> () /// A typealias for a normal callback. public typealias NormalCallback = ([Any], SocketAckEmitter) -> () +/// A typealias for a queued POST +public typealias Post = (msg: String, completion: (() -> ())) + typealias JSON = [String: Any] -typealias Probe = (msg: String, type: SocketEnginePacketType, data: [Data]) +typealias Probe = (msg: String, type: SocketEnginePacketType, data: [Data], completion: (() -> ())) typealias ProbeWaitQueue = [Probe] enum Either { diff --git a/Tests/TestSocketIO/SocketMangerTest.swift b/Tests/TestSocketIO/SocketMangerTest.swift index 22da481..dc76441 100644 --- a/Tests/TestSocketIO/SocketMangerTest.swift +++ b/Tests/TestSocketIO/SocketMangerTest.swift @@ -188,7 +188,7 @@ public class TestSocket : SocketIOClient { super.didDisconnect(reason: reason) } - public override func emit(_ event: String, with items: [Any]) { + public override func emit(_ event: String, with items: [Any], completion: @escaping () -> ()) { expectations[ManagerExpectation.emitAllEventCalled]?.fulfill() expectations[ManagerExpectation.emitAllEventCalled] = nil diff --git a/Tests/TestSocketIO/SocketSideEffectTest.swift b/Tests/TestSocketIO/SocketSideEffectTest.swift index 5c8a77d..49542ce 100644 --- a/Tests/TestSocketIO/SocketSideEffectTest.swift +++ b/Tests/TestSocketIO/SocketSideEffectTest.swift @@ -506,5 +506,5 @@ class TestEngine : SocketEngineSpec { func flushWaitingForPostToWebSocket() { } func parseEngineData(_ data: Data) { } func parseEngineMessage(_ message: String) { } - func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) { } + func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping () -> ()) { } } diff --git a/Tests/TestSocketIOObjc/SocketObjectiveCTest.m b/Tests/TestSocketIOObjc/SocketObjectiveCTest.m index 1ad3475..28c21b9 100644 --- a/Tests/TestSocketIOObjc/SocketObjectiveCTest.m +++ b/Tests/TestSocketIOObjc/SocketObjectiveCTest.m @@ -67,6 +67,20 @@ [self.socket emit:@"testEmit" with:@[@YES]]; } +- (void)testEmitWriteCompletionSyntax { + [self.socket emit:@"testEmit" with:@[@YES] completion:^{}]; +} + +- (void)testEmitWriteCompletion { + XCTestExpectation* expect = [self expectationWithDescription:@"Write completion should be called"]; + + [self.socket emit:@"testEmit" with:@[@YES] completion:^{ + [expect fulfill]; + }]; + + [self waitForExpectationsWithTimeout:0.3 handler:nil]; +} + - (void)testRawEmitSyntax { [[self.socket rawEmitView] emit:@"myEvent" with:@[@1]]; } From 28fad62ccd37bcb45a6af0b6a620c9cb746f01f0 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 2 Oct 2018 13:47:03 +0700 Subject: [PATCH 02/13] wrap completion handler to run on handleQueue --- Source/SocketIO/Client/SocketIOClient.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index ac7dbff..4e70417 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -295,8 +295,14 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { } func emit(_ data: [Any], ack: Int? = nil, binary: Bool = true, isAck: Bool = false, completion: (() -> ())? = nil) { + // wrap the completion handler so it always runs async via handlerQueue + let wrappedCompletion = {[weak self, completion] in + guard let this = self else { return } + this.manager?.handleQueue.async { completion?() } + } + guard status == .connected else { - completion?(); + wrappedCompletion(); handleClientEvent(.error, data: ["Tried emitting when not connected"]) return } @@ -306,7 +312,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { DefaultSocketLogger.Logger.log("Emitting: \(str), Ack: \(isAck)", type: logType) - manager?.engine?.send(str, withData: packet.binary, completion: completion) + manager?.engine?.send(str, withData: packet.binary, completion: completion != nil ? wrappedCompletion : nil) } /// Call when you wish to tell the server that you've received the event for `ack`. From d763fad4496df113476efc4361795c3e16722699 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 2 Oct 2018 19:05:22 +0700 Subject: [PATCH 03/13] no need to capture completion hander in wrapper --- Source/SocketIO/Client/SocketIOClient.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index 4e70417..a4c892c 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -296,7 +296,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { func emit(_ data: [Any], ack: Int? = nil, binary: Bool = true, isAck: Bool = false, completion: (() -> ())? = nil) { // wrap the completion handler so it always runs async via handlerQueue - let wrappedCompletion = {[weak self, completion] in + let wrappedCompletion = {[weak self] in guard let this = self else { return } this.manager?.handleQueue.async { completion?() } } From b3e305fd1448165fa52e0a2d2b2afffbecbbadae Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 2 Oct 2018 20:55:38 +0700 Subject: [PATCH 04/13] Add a variadic method for emit completion handlers in swift --- Source/SocketIO/Client/SocketIOClient.swift | 12 ++++++++++++ Source/SocketIO/Client/SocketIOClientSpec.swift | 10 ++++++++++ Tests/TestSocketIO/SocketSideEffectTest.swift | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index a4c892c..a0d89a7 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -221,6 +221,18 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { handleClientEvent(.error, data: [event, items, error]) } } + + /// Send an event to the server, with optional data items and write completion handler. + /// + /// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error` + /// will be emitted. The structure of the error data is `[eventName, items, theError]` + /// + /// - parameter event: The event to send. + /// - parameter items: The items to send with this event. May be left out. + /// - parameter completion: Callback called on transport write completion. + open func emit(_ event: String, _ items: SocketData..., completion: @escaping () -> ()) { + emit([event] + items, completion: completion) + } /// Same as emit, but meant for Objective-C /// diff --git a/Source/SocketIO/Client/SocketIOClientSpec.swift b/Source/SocketIO/Client/SocketIOClientSpec.swift index 3835412..629ee78 100644 --- a/Source/SocketIO/Client/SocketIOClientSpec.swift +++ b/Source/SocketIO/Client/SocketIOClientSpec.swift @@ -101,6 +101,16 @@ public protocol SocketIOClientSpec : AnyObject { /// - parameter items: The items to send with this event. May be left out. func emit(_ event: String, _ items: SocketData...) + /// Send an event to the server, with optional data items and write completion handler. + /// + /// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error` + /// will be emitted. The structure of the error data is `[eventName, items, theError]` + /// + /// - parameter event: The event to send. + /// - parameter items: The items to send with this event. May be left out. + /// - parameter completion: Callback called on transport write completion. + func emit(_ event: String, _ items: SocketData..., completion: @escaping () -> ()) + /// Call when you wish to tell the server that you've received the event for `ack`. /// /// - parameter ack: The ack number. diff --git a/Tests/TestSocketIO/SocketSideEffectTest.swift b/Tests/TestSocketIO/SocketSideEffectTest.swift index 49542ce..72c43f9 100644 --- a/Tests/TestSocketIO/SocketSideEffectTest.swift +++ b/Tests/TestSocketIO/SocketSideEffectTest.swift @@ -27,6 +27,11 @@ class SocketSideEffectTest: XCTestCase { XCTAssertEqual(socket.currentAck, 1) } + func testEmitCompletionSyntax() { + socket.emit("test", completion: {}) + socket.emit("test", "thing", completion: {}) + } + func testHandleAck() { let expect = expectation(description: "handled ack") socket.emitWithAck("test").timingOut(after: 0) {data in From 09fc43349ff5c2736cb24cc015dfdd564d2302c3 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 2 Oct 2018 21:08:55 +0700 Subject: [PATCH 05/13] convert SocketData to serialisable socket representation --- Source/SocketIO/Client/SocketIOClient.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index a0d89a7..7ac8b74 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -231,7 +231,14 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter items: The items to send with this event. May be left out. /// - parameter completion: Callback called on transport write completion. open func emit(_ event: String, _ items: SocketData..., completion: @escaping () -> ()) { - emit([event] + items, completion: completion) + do { + try emit(event, with: items.map({ try $0.socketRepresentation() }), completion: completion) + } catch { + DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", + type: logType) + + handleClientEvent(.error, data: [event, items, error]) + } } /// Same as emit, but meant for Objective-C From 0d8890defd73627789833a81624077f72bcf9ba3 Mon Sep 17 00:00:00 2001 From: Erik Little Date: Thu, 4 Oct 2018 06:55:05 -0400 Subject: [PATCH 06/13] update xcode settings --- Socket.IO-Client-Swift.xcodeproj/project.pbxproj | 10 +++++++--- .../xcshareddata/xcschemes/SocketIO.xcscheme | 4 +--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj index 3d611e0..cf7e6e2 100644 --- a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj +++ b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj @@ -391,7 +391,7 @@ attributes = { LastSwiftMigration = 0730; LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 1000; TargetAttributes = { 572EF2371B51F18A00EEBB58 = { CreatedOnToolsVersion = 6.4; @@ -523,18 +523,20 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Developer ID Application"; + CODE_SIGN_IDENTITY = "Mac Developer"; ENABLE_BITCODE = YES; "ENABLE_BITCODE[sdk=macosx*]" = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -596,18 +598,20 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Developer ID Application"; + CODE_SIGN_IDENTITY = "Mac Developer"; ENABLE_BITCODE = YES; "ENABLE_BITCODE[sdk=macosx*]" = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; diff --git a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO.xcscheme b/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO.xcscheme index 74dc491..2868081 100644 --- a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO.xcscheme +++ b/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO.xcscheme @@ -1,6 +1,6 @@ Date: Wed, 17 Oct 2018 06:56:30 -0400 Subject: [PATCH 07/13] update deps: Fix #1105 --- Package.resolved | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/Package.resolved b/Package.resolved index 0c163c0..8a888aa 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,31 +1,13 @@ { "object": { "pins": [ - { - "package": "SSCommonCrypto", - "repositoryURL": "https://github.com/daltoniam/common-crypto-spm", - "state": { - "branch": null, - "revision": "2eb3aff0fb57f92f5722fac5d6d20bf64669ca66", - "version": "1.1.0" - } - }, { "package": "Starscream", "repositoryURL": "https://github.com/daltoniam/Starscream", "state": { "branch": null, - "revision": "114e5df9b6251970a069e8f1c0cbb5802759f0a9", - "version": "3.0.5" - } - }, - { - "package": "SSCZLib", - "repositoryURL": "https://github.com/daltoniam/zlib-spm.git", - "state": { - "branch": null, - "revision": "83ac8d719a2f3aa775dbdf116a57f56fb2c49abb", - "version": "1.1.0" + "revision": "ebdc260ea64e68f7569c62e8744b5cd15d3a49d6", + "version": "3.0.6" } } ] From d839a35340225a5d26bf560cd0e06ca4f07cd312 Mon Sep 17 00:00:00 2001 From: Erik Little Date: Wed, 17 Oct 2018 06:57:59 -0400 Subject: [PATCH 08/13] update cartfile too --- Cartfile.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index c433ad3..d6801c9 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "daltoniam/Starscream" "3.0.5" +github "daltoniam/Starscream" "3.0.6" From 75057023cbccc252ab35bc0580332e9dfd15936b Mon Sep 17 00:00:00 2001 From: Erik Little Date: Wed, 17 Oct 2018 09:55:11 -0400 Subject: [PATCH 09/13] clean up emit completion code --- Source/SocketIO/Client/SocketIOClient.swift | 25 ++++++++++++------- .../Engine/SocketEnginePollable.swift | 2 -- Source/SocketIO/Engine/SocketEngineSpec.swift | 6 ++--- .../Engine/SocketEngineWebsocket.swift | 11 ++++++-- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index 7ac8b74..f724552 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -213,7 +213,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter items: The items to send with this event. May be left out. open func emit(_ event: String, _ items: SocketData...) { do { - try emit(event, with: items.map({ try $0.socketRepresentation() }), completion: {}) + try emit(event, with: items.map({ try $0.socketRepresentation() })) } catch { DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", type: logType) @@ -221,7 +221,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { handleClientEvent(.error, data: [event, items, error]) } } - + /// Send an event to the server, with optional data items and write completion handler. /// /// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error` @@ -247,9 +247,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter items: The items to send with this event. Send an empty array to send no data. @objc open func emit(_ event: String, with items: [Any]) { - emit([event] + items, completion: {}) + emit([event] + items) } - + /// Same as emit, but meant for Objective-C /// /// - parameter event: The event to send. @@ -313,15 +313,22 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { return createOnAck([event] + items) } - func emit(_ data: [Any], ack: Int? = nil, binary: Bool = true, isAck: Bool = false, completion: (() -> ())? = nil) { + func emit(_ data: [Any], + ack: Int? = nil, + binary: Bool = true, + isAck: Bool = false, + completion: @escaping () -> () = {} + ) { // wrap the completion handler so it always runs async via handlerQueue let wrappedCompletion = {[weak self] in guard let this = self else { return } - this.manager?.handleQueue.async { completion?() } + this.manager?.handleQueue.async { + completion() + } } - + guard status == .connected else { - wrappedCompletion(); + wrappedCompletion() handleClientEvent(.error, data: ["Tried emitting when not connected"]) return } @@ -331,7 +338,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { DefaultSocketLogger.Logger.log("Emitting: \(str), Ack: \(isAck)", type: logType) - manager?.engine?.send(str, withData: packet.binary, completion: completion != nil ? wrappedCompletion : nil) + manager?.engine?.send(str, withData: packet.binary, completion: wrappedCompletion) } /// Call when you wish to tell the server that you've received the event for `ack`. diff --git a/Source/SocketIO/Engine/SocketEnginePollable.swift b/Source/SocketIO/Engine/SocketEnginePollable.swift index 7b70736..7e09307 100644 --- a/Source/SocketIO/Engine/SocketEnginePollable.swift +++ b/Source/SocketIO/Engine/SocketEnginePollable.swift @@ -226,8 +226,6 @@ extension SocketEnginePollable { for data in datas { if case let .right(bin) = createBinaryDataForSend(using: data) { - // completion handler will be called on initial message write - // TODO: call completion after last message in batch postWait.append((bin, {})) } } diff --git a/Source/SocketIO/Engine/SocketEngineSpec.swift b/Source/SocketIO/Engine/SocketEngineSpec.swift index c7b073c..f97490e 100644 --- a/Source/SocketIO/Engine/SocketEngineSpec.swift +++ b/Source/SocketIO/Engine/SocketEngineSpec.swift @@ -159,7 +159,7 @@ extension SocketEngineSpec { func addHeaders(to req: inout URLRequest, includingCookies additionalCookies: [HTTPCookie]? = nil) { var cookiesToAdd: [HTTPCookie] = cookies ?? [] cookiesToAdd += additionalCookies ?? [] - + if !cookiesToAdd.isEmpty { req.allHTTPHeaderFields = HTTPCookie.requestHeaderFields(with: cookiesToAdd) } @@ -180,7 +180,7 @@ extension SocketEngineSpec { } /// Send an engine message (4) - func send(_ msg: String, withData datas: [Data], completion: (() -> ())? = nil) { - write(msg, withType: .message, withData: datas, completion: completion ?? {}) + func send(_ msg: String, withData datas: [Data], completion: @escaping () -> () = {}) { + write(msg, withType: .message, withData: datas, completion: completion) } } diff --git a/Source/SocketIO/Engine/SocketEngineWebsocket.swift b/Source/SocketIO/Engine/SocketEngineWebsocket.swift index b3fad5e..0ded9a4 100644 --- a/Source/SocketIO/Engine/SocketEngineWebsocket.swift +++ b/Source/SocketIO/Engine/SocketEngineWebsocket.swift @@ -38,7 +38,10 @@ public protocol SocketEngineWebsocket : SocketEngineSpec { /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. /// - parameter completion: Callback called on transport write completion. - func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) + func sendWebSocketMessage(_ str: String, + withType type: SocketEnginePacketType, + withData datas: [Data], + completion: @escaping () -> ()) } // WebSocket methods @@ -57,7 +60,11 @@ extension SocketEngineWebsocket { /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. /// - parameter completion: Callback called on transport write completion. - public func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) { + public func sendWebSocketMessage(_ str: String, + withType type: SocketEnginePacketType, + withData datas: [Data], + completion: @escaping () -> () + ) { DefaultSocketLogger.Logger.log("Sending ws: \(str) as type: \(type.rawValue)", type: "SocketEngineWebSocket") ws?.write(string: "\(type.rawValue)\(str)") From 5a6a4f02d9716bc1fd434380f6563ff0e2cf717f Mon Sep 17 00:00:00 2001 From: Valentin Slawicek Date: Wed, 17 Oct 2018 21:38:19 +0200 Subject: [PATCH 10/13] Propagate http header callback from websocket back to client. --- Source/SocketIO/Client/SocketIOClientSpec.swift | 12 ++++++++++++ Source/SocketIO/Engine/SocketEngine.swift | 10 +++++++++- Source/SocketIO/Engine/SocketEngineClient.swift | 5 +++++ Source/SocketIO/Manager/SocketManager.swift | 12 ++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Source/SocketIO/Client/SocketIOClientSpec.swift b/Source/SocketIO/Client/SocketIOClientSpec.swift index 629ee78..80e1e6a 100644 --- a/Source/SocketIO/Client/SocketIOClientSpec.swift +++ b/Source/SocketIO/Client/SocketIOClientSpec.swift @@ -344,4 +344,16 @@ public enum SocketClientEvent : String { /// } /// ``` case statusChange + + /// Emitted when when upgrading the http connection to a websocket connection. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .websocketUpgrade) {data, ack in + /// let headers = (data as [Any])[0] + /// // Some header logic + /// } + /// ``` + case websocketUpgrade } diff --git a/Source/SocketIO/Engine/SocketEngine.swift b/Source/SocketIO/Engine/SocketEngine.swift index 1ed0b62..9466a9e 100644 --- a/Source/SocketIO/Engine/SocketEngine.swift +++ b/Source/SocketIO/Engine/SocketEngine.swift @@ -313,6 +313,12 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So this.parseEngineMessage(message) } + ws?.onHttpResponseHeaders = {[weak self] headers in + guard let this = self else { return } + + this.client?.engineDidWebsocketUpgrade(headers: headers) + } + ws?.connect() } @@ -666,7 +672,9 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So connected = false polling = true - if let reason = error?.localizedDescription { + if let error = error as? WSError { + didError(reason: "\(error.message). code=\(error.code), type=\(error.type)") + } else if let reason = error?.localizedDescription { didError(reason: reason) } else { client?.engineDidClose(reason: "Socket Disconnected") diff --git a/Source/SocketIO/Engine/SocketEngineClient.swift b/Source/SocketIO/Engine/SocketEngineClient.swift index eefc2ac..00d68fa 100644 --- a/Source/SocketIO/Engine/SocketEngineClient.swift +++ b/Source/SocketIO/Engine/SocketEngineClient.swift @@ -59,4 +59,9 @@ import Foundation /// /// - parameter data: The data the engine received. func parseEngineBinaryData(_ data: Data) + + /// Called when when upgrading the http connection to a websocket connection. + /// + /// - parameter headers: The http headers. + func engineDidWebsocketUpgrade(headers: [String: String]) } diff --git a/Source/SocketIO/Manager/SocketManager.swift b/Source/SocketIO/Manager/SocketManager.swift index fd47ead..19c6c9e 100644 --- a/Source/SocketIO/Manager/SocketManager.swift +++ b/Source/SocketIO/Manager/SocketManager.swift @@ -377,6 +377,18 @@ open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDa } } + /// Called when when upgrading the http connection to a websocket connection. + /// + /// - parameter headers: The http headers. + open func engineDidWebsocketUpgrade(headers: [String: String]) { + handleQueue.async { + self._engineDidWebsocketUpgrade(headers: headers) + } + } + private func _engineDidWebsocketUpgrade(headers: [String: String]) { + emitAll(clientEvent: .websocketUpgrade, data: [headers]) + } + /// Called when the engine has a message that must be parsed. /// /// - parameter msg: The message that needs parsing. From a4b334b6f203ba6dcb6de99b3a6d7cffce0f3908 Mon Sep 17 00:00:00 2001 From: Valentin Slawicek Date: Wed, 7 Nov 2018 12:37:48 +0100 Subject: [PATCH 11/13] =?UTF-8?q?Don=E2=80=99t=20create=20empty=20closures?= =?UTF-8?q?=20when=20we=20don=E2=80=99t=20need=20them.=20Fixes=20https://g?= =?UTF-8?q?ithub.com/socketio/socket.io-client-swift/issues/1118.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/SocketIO/Client/SocketIOClient.swift | 10 +++++----- Source/SocketIO/Client/SocketIOClientSpec.swift | 2 +- Source/SocketIO/Engine/SocketEngine.swift | 14 +++++++------- Source/SocketIO/Engine/SocketEnginePollable.swift | 6 +++--- Source/SocketIO/Engine/SocketEngineSpec.swift | 4 ++-- Source/SocketIO/Engine/SocketEngineWebsocket.swift | 6 +++--- Source/SocketIO/Manager/SocketManager.swift | 2 +- Source/SocketIO/Util/SocketTypes.swift | 4 ++-- Tests/TestSocketIO/SocketMangerTest.swift | 2 +- Tests/TestSocketIO/SocketSideEffectTest.swift | 2 +- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index f724552..000b61f 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -230,7 +230,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter event: The event to send. /// - parameter items: The items to send with this event. May be left out. /// - parameter completion: Callback called on transport write completion. - open func emit(_ event: String, _ items: SocketData..., completion: @escaping () -> ()) { + open func emit(_ event: String, _ items: SocketData..., completion: @escaping (() -> ())? = nil) { do { try emit(event, with: items.map({ try $0.socketRepresentation() }), completion: completion) } catch { @@ -256,7 +256,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter items: The items to send with this event. Send an empty array to send no data. /// - parameter completion: Callback called on transport write completion. @objc - open func emit(_ event: String, with items: [Any], completion: @escaping () -> ()) { + open func emit(_ event: String, with items: [Any], completion: @escaping (() -> ())? = nil) { emit([event] + items, completion: completion) } @@ -317,10 +317,10 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { ack: Int? = nil, binary: Bool = true, isAck: Bool = false, - completion: @escaping () -> () = {} + completion: @escaping (() -> ())? = nil ) { // wrap the completion handler so it always runs async via handlerQueue - let wrappedCompletion = {[weak self] in + let wrappedCompletion: (() -> ())? = (completion == nil) ? nil : {[weak self] in guard let this = self else { return } this.manager?.handleQueue.async { completion() @@ -328,7 +328,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { } guard status == .connected else { - wrappedCompletion() + wrappedCompletion?() handleClientEvent(.error, data: ["Tried emitting when not connected"]) return } diff --git a/Source/SocketIO/Client/SocketIOClientSpec.swift b/Source/SocketIO/Client/SocketIOClientSpec.swift index 80e1e6a..c9c6c24 100644 --- a/Source/SocketIO/Client/SocketIOClientSpec.swift +++ b/Source/SocketIO/Client/SocketIOClientSpec.swift @@ -109,7 +109,7 @@ public protocol SocketIOClientSpec : AnyObject { /// - parameter event: The event to send. /// - parameter items: The items to send with this event. May be left out. /// - parameter completion: Callback called on transport write completion. - func emit(_ event: String, _ items: SocketData..., completion: @escaping () -> ()) + func emit(_ event: String, _ items: SocketData..., completion: @escaping (() -> ())? = nil) /// Call when you wish to tell the server that you've received the event for `ack`. /// diff --git a/Source/SocketIO/Engine/SocketEngine.swift b/Source/SocketIO/Engine/SocketEngine.swift index 9466a9e..82d6c2c 100644 --- a/Source/SocketIO/Engine/SocketEngine.swift +++ b/Source/SocketIO/Engine/SocketEngine.swift @@ -346,7 +346,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So if polling { disconnectPolling(reason: reason) } else { - sendWebSocketMessage("", withType: .close, withData: [], completion: {}) + sendWebSocketMessage("", withType: .close, withData: [], completion: nil) closeOutEngine(reason: reason) } } @@ -372,7 +372,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So DefaultSocketLogger.Logger.log("Switching to WebSockets", type: SocketEngine.logType) - sendWebSocketMessage("", withType: .upgrade, withData: [], completion: {}) + sendWebSocketMessage("", withType: .upgrade, withData: [], completion: nil) polling = false fastUpgrade = false probing = false @@ -390,7 +390,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So DefaultSocketLogger.Logger.log("Flushing probe wait", type: SocketEngine.logType) for waiter in probeWait { - write(waiter.msg, withType: waiter.type, withData: waiter.data, completion:waiter.completion) + write(waiter.msg, withType: waiter.type, withData: waiter.data, completion: waiter.completion) } probeWait.removeAll(keepingCapacity: false) @@ -550,7 +550,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So } pongsMissed += 1 - write("", withType: .ping, withData: [], completion: {}) + write("", withType: .ping, withData: [], completion: nil) engineQueue.asyncAfter(deadline: .now() + .milliseconds(pingInterval)) {[weak self, id = self.sid] in // Make sure not to ping old connections @@ -606,7 +606,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So DefaultSocketLogger.Logger.log("Upgrading transport to WebSockets", type: SocketEngine.logType) fastUpgrade = true - sendPollMessage("", withType: .noop, withData: [], completion: {}) + sendPollMessage("", withType: .noop, withData: [], completion: nil) // After this point, we should not send anymore polling messages } } @@ -617,10 +617,10 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So /// - parameter type: The type of this message. /// - parameter data: Any data that this message has. /// - parameter completion: Callback called on transport write completion. - open func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping () -> ()) { + open func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping (() -> ())? = nil) { engineQueue.async { guard self.connected else { - completion() + completion?() return } guard !self.probing else { diff --git a/Source/SocketIO/Engine/SocketEnginePollable.swift b/Source/SocketIO/Engine/SocketEnginePollable.swift index 7e09307..16db822 100644 --- a/Source/SocketIO/Engine/SocketEnginePollable.swift +++ b/Source/SocketIO/Engine/SocketEnginePollable.swift @@ -65,7 +65,7 @@ public protocol SocketEnginePollable : SocketEngineSpec { /// - parameter message: The message to send. /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. - func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) + func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping (() -> ())?) /// Call to stop polling and invalidate the URLSession. func stopPolling() @@ -75,7 +75,7 @@ public protocol SocketEnginePollable : SocketEngineSpec { extension SocketEnginePollable { func createRequestForPostWithPostWait() -> URLRequest { defer { - for packet in postWait { packet.completion() } + for packet in postWait { packet.completion?() } postWait.removeAll(keepingCapacity: true) } @@ -219,7 +219,7 @@ extension SocketEnginePollable { /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. /// - parameter completion: Callback called on transport write completion. - public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping () -> ()) { + public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping (() -> ())? = nil) { DefaultSocketLogger.Logger.log("Sending poll: \(message) as type: \(type.rawValue)", type: "SocketEnginePolling") postWait.append((String(type.rawValue) + message, completion)) diff --git a/Source/SocketIO/Engine/SocketEngineSpec.swift b/Source/SocketIO/Engine/SocketEngineSpec.swift index f97490e..5252815 100644 --- a/Source/SocketIO/Engine/SocketEngineSpec.swift +++ b/Source/SocketIO/Engine/SocketEngineSpec.swift @@ -138,7 +138,7 @@ import Starscream /// - parameter type: The type of this message. /// - parameter data: Any data that this message has. /// - parameter completion: Callback called on transport write completion. - func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping () -> ()) + func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping (() -> ())?) } extension SocketEngineSpec { @@ -180,7 +180,7 @@ extension SocketEngineSpec { } /// Send an engine message (4) - func send(_ msg: String, withData datas: [Data], completion: @escaping () -> () = {}) { + func send(_ msg: String, withData datas: [Data], completion: @escaping (() -> ())? = nil) { write(msg, withType: .message, withData: datas, completion: completion) } } diff --git a/Source/SocketIO/Engine/SocketEngineWebsocket.swift b/Source/SocketIO/Engine/SocketEngineWebsocket.swift index 0ded9a4..7fad5bc 100644 --- a/Source/SocketIO/Engine/SocketEngineWebsocket.swift +++ b/Source/SocketIO/Engine/SocketEngineWebsocket.swift @@ -41,14 +41,14 @@ public protocol SocketEngineWebsocket : SocketEngineSpec { func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], - completion: @escaping () -> ()) + completion: @escaping (() -> ())?) } // WebSocket methods extension SocketEngineWebsocket { func probeWebSocket() { if ws?.isConnected ?? false { - sendWebSocketMessage("probe", withType: .ping, withData: [], completion: {}) + sendWebSocketMessage("probe", withType: .ping, withData: [], completion: nil) } } @@ -63,7 +63,7 @@ extension SocketEngineWebsocket { public func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], - completion: @escaping () -> () + completion: @escaping (() -> ())? ) { DefaultSocketLogger.Logger.log("Sending ws: \(str) as type: \(type.rawValue)", type: "SocketEngineWebSocket") diff --git a/Source/SocketIO/Manager/SocketManager.swift b/Source/SocketIO/Manager/SocketManager.swift index 19c6c9e..e348eed 100644 --- a/Source/SocketIO/Manager/SocketManager.swift +++ b/Source/SocketIO/Manager/SocketManager.swift @@ -286,7 +286,7 @@ open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDa /// - parameter items: The data to send with this event. open func emitAll(_ event: String, withItems items: [Any]) { forAll {socket in - socket.emit(event, with: items, completion: {}) + socket.emit(event, with: items, completion: nil) } } diff --git a/Source/SocketIO/Util/SocketTypes.swift b/Source/SocketIO/Util/SocketTypes.swift index f8cdc05..7bb6517 100644 --- a/Source/SocketIO/Util/SocketTypes.swift +++ b/Source/SocketIO/Util/SocketTypes.swift @@ -74,10 +74,10 @@ public typealias AckCallback = ([Any]) -> () public typealias NormalCallback = ([Any], SocketAckEmitter) -> () /// A typealias for a queued POST -public typealias Post = (msg: String, completion: (() -> ())) +public typealias Post = (msg: String, completion: (() -> ())?) typealias JSON = [String: Any] -typealias Probe = (msg: String, type: SocketEnginePacketType, data: [Data], completion: (() -> ())) +typealias Probe = (msg: String, type: SocketEnginePacketType, data: [Data], completion: (() -> ())?) typealias ProbeWaitQueue = [Probe] enum Either { diff --git a/Tests/TestSocketIO/SocketMangerTest.swift b/Tests/TestSocketIO/SocketMangerTest.swift index fc5ad21..9ac3c40 100644 --- a/Tests/TestSocketIO/SocketMangerTest.swift +++ b/Tests/TestSocketIO/SocketMangerTest.swift @@ -198,7 +198,7 @@ public class TestSocket : SocketIOClient { super.didDisconnect(reason: reason) } - public override func emit(_ event: String, with items: [Any], completion: @escaping () -> ()) { + public override func emit(_ event: String, with items: [Any], completion: @escaping (() -> ())?) { expectations[ManagerExpectation.emitAllEventCalled]?.fulfill() expectations[ManagerExpectation.emitAllEventCalled] = nil diff --git a/Tests/TestSocketIO/SocketSideEffectTest.swift b/Tests/TestSocketIO/SocketSideEffectTest.swift index 72c43f9..8f1bef9 100644 --- a/Tests/TestSocketIO/SocketSideEffectTest.swift +++ b/Tests/TestSocketIO/SocketSideEffectTest.swift @@ -511,5 +511,5 @@ class TestEngine : SocketEngineSpec { func flushWaitingForPostToWebSocket() { } func parseEngineData(_ data: Data) { } func parseEngineMessage(_ message: String) { } - func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping () -> ()) { } + func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping (() -> ())?) { } } From 8f94c038d8c120d57ce9fb4bffc0a95512845e04 Mon Sep 17 00:00:00 2001 From: Valentin Slawicek Date: Wed, 7 Nov 2018 12:47:55 +0100 Subject: [PATCH 12/13] Fix build --- Source/SocketIO/Client/SocketIOClient.swift | 8 ++++---- Source/SocketIO/Client/SocketIOClientSpec.swift | 2 +- Source/SocketIO/Engine/SocketEngine.swift | 2 +- Source/SocketIO/Engine/SocketEnginePollable.swift | 4 ++-- Source/SocketIO/Engine/SocketEngineSpec.swift | 4 ++-- Source/SocketIO/Engine/SocketEngineWebsocket.swift | 4 ++-- Tests/TestSocketIO/SocketMangerTest.swift | 2 +- Tests/TestSocketIO/SocketSideEffectTest.swift | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index 000b61f..ef83bcd 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -230,7 +230,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter event: The event to send. /// - parameter items: The items to send with this event. May be left out. /// - parameter completion: Callback called on transport write completion. - open func emit(_ event: String, _ items: SocketData..., completion: @escaping (() -> ())? = nil) { + open func emit(_ event: String, _ items: SocketData..., completion: (() -> ())? = nil) { do { try emit(event, with: items.map({ try $0.socketRepresentation() }), completion: completion) } catch { @@ -256,7 +256,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter items: The items to send with this event. Send an empty array to send no data. /// - parameter completion: Callback called on transport write completion. @objc - open func emit(_ event: String, with items: [Any], completion: @escaping (() -> ())? = nil) { + open func emit(_ event: String, with items: [Any], completion: (() -> ())? = nil) { emit([event] + items, completion: completion) } @@ -317,13 +317,13 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { ack: Int? = nil, binary: Bool = true, isAck: Bool = false, - completion: @escaping (() -> ())? = nil + completion: (() -> ())? = nil ) { // wrap the completion handler so it always runs async via handlerQueue let wrappedCompletion: (() -> ())? = (completion == nil) ? nil : {[weak self] in guard let this = self else { return } this.manager?.handleQueue.async { - completion() + completion!() } } diff --git a/Source/SocketIO/Client/SocketIOClientSpec.swift b/Source/SocketIO/Client/SocketIOClientSpec.swift index c9c6c24..f2658a8 100644 --- a/Source/SocketIO/Client/SocketIOClientSpec.swift +++ b/Source/SocketIO/Client/SocketIOClientSpec.swift @@ -109,7 +109,7 @@ public protocol SocketIOClientSpec : AnyObject { /// - parameter event: The event to send. /// - parameter items: The items to send with this event. May be left out. /// - parameter completion: Callback called on transport write completion. - func emit(_ event: String, _ items: SocketData..., completion: @escaping (() -> ())? = nil) + func emit(_ event: String, _ items: SocketData..., completion: (() -> ())?) /// Call when you wish to tell the server that you've received the event for `ack`. /// diff --git a/Source/SocketIO/Engine/SocketEngine.swift b/Source/SocketIO/Engine/SocketEngine.swift index 82d6c2c..ee3af22 100644 --- a/Source/SocketIO/Engine/SocketEngine.swift +++ b/Source/SocketIO/Engine/SocketEngine.swift @@ -617,7 +617,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So /// - parameter type: The type of this message. /// - parameter data: Any data that this message has. /// - parameter completion: Callback called on transport write completion. - open func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping (() -> ())? = nil) { + open func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: (() -> ())? = nil) { engineQueue.async { guard self.connected else { completion?() diff --git a/Source/SocketIO/Engine/SocketEnginePollable.swift b/Source/SocketIO/Engine/SocketEnginePollable.swift index 16db822..9e55bd9 100644 --- a/Source/SocketIO/Engine/SocketEnginePollable.swift +++ b/Source/SocketIO/Engine/SocketEnginePollable.swift @@ -65,7 +65,7 @@ public protocol SocketEnginePollable : SocketEngineSpec { /// - parameter message: The message to send. /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. - func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping (() -> ())?) + func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: (() -> ())?) /// Call to stop polling and invalidate the URLSession. func stopPolling() @@ -219,7 +219,7 @@ extension SocketEnginePollable { /// - parameter withType: The type of message to send. /// - parameter withData: The data associated with this message. /// - parameter completion: Callback called on transport write completion. - public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: @escaping (() -> ())? = nil) { + public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data], completion: (() -> ())? = nil) { DefaultSocketLogger.Logger.log("Sending poll: \(message) as type: \(type.rawValue)", type: "SocketEnginePolling") postWait.append((String(type.rawValue) + message, completion)) diff --git a/Source/SocketIO/Engine/SocketEngineSpec.swift b/Source/SocketIO/Engine/SocketEngineSpec.swift index 5252815..2f01d74 100644 --- a/Source/SocketIO/Engine/SocketEngineSpec.swift +++ b/Source/SocketIO/Engine/SocketEngineSpec.swift @@ -138,7 +138,7 @@ import Starscream /// - parameter type: The type of this message. /// - parameter data: Any data that this message has. /// - parameter completion: Callback called on transport write completion. - func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping (() -> ())?) + func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: (() -> ())?) } extension SocketEngineSpec { @@ -180,7 +180,7 @@ extension SocketEngineSpec { } /// Send an engine message (4) - func send(_ msg: String, withData datas: [Data], completion: @escaping (() -> ())? = nil) { + func send(_ msg: String, withData datas: [Data], completion: (() -> ())? = nil) { write(msg, withType: .message, withData: datas, completion: completion) } } diff --git a/Source/SocketIO/Engine/SocketEngineWebsocket.swift b/Source/SocketIO/Engine/SocketEngineWebsocket.swift index 7fad5bc..0b85ce1 100644 --- a/Source/SocketIO/Engine/SocketEngineWebsocket.swift +++ b/Source/SocketIO/Engine/SocketEngineWebsocket.swift @@ -41,7 +41,7 @@ public protocol SocketEngineWebsocket : SocketEngineSpec { func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], - completion: @escaping (() -> ())?) + completion: (() -> ())?) } // WebSocket methods @@ -63,7 +63,7 @@ extension SocketEngineWebsocket { public func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data], - completion: @escaping (() -> ())? + completion: (() -> ())? ) { DefaultSocketLogger.Logger.log("Sending ws: \(str) as type: \(type.rawValue)", type: "SocketEngineWebSocket") diff --git a/Tests/TestSocketIO/SocketMangerTest.swift b/Tests/TestSocketIO/SocketMangerTest.swift index 9ac3c40..8041948 100644 --- a/Tests/TestSocketIO/SocketMangerTest.swift +++ b/Tests/TestSocketIO/SocketMangerTest.swift @@ -198,7 +198,7 @@ public class TestSocket : SocketIOClient { super.didDisconnect(reason: reason) } - public override func emit(_ event: String, with items: [Any], completion: @escaping (() -> ())?) { + public override func emit(_ event: String, with items: [Any], completion: (() -> ())?) { expectations[ManagerExpectation.emitAllEventCalled]?.fulfill() expectations[ManagerExpectation.emitAllEventCalled] = nil diff --git a/Tests/TestSocketIO/SocketSideEffectTest.swift b/Tests/TestSocketIO/SocketSideEffectTest.swift index 8f1bef9..a37f198 100644 --- a/Tests/TestSocketIO/SocketSideEffectTest.swift +++ b/Tests/TestSocketIO/SocketSideEffectTest.swift @@ -511,5 +511,5 @@ class TestEngine : SocketEngineSpec { func flushWaitingForPostToWebSocket() { } func parseEngineData(_ data: Data) { } func parseEngineMessage(_ message: String) { } - func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: @escaping (() -> ())?) { } + func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: (() -> ())?) { } } From e0cbe59a102ffeb5697d1eff21ae4cd3d68ec023 Mon Sep 17 00:00:00 2001 From: Valentin Slawicek Date: Wed, 7 Nov 2018 13:53:25 +0100 Subject: [PATCH 13/13] Remove unnecessary function calls. --- Source/SocketIO/Client/SocketIOClient.swift | 20 +------------------ .../SocketIO/Client/SocketIOClientSpec.swift | 11 +--------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index ef83bcd..b05b0ec 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -204,25 +204,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { leaveNamespace() } - /// Send an event to the server, with optional data items. - /// - /// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error` - /// will be emitted. The structure of the error data is `[eventName, items, theError]` - /// - /// - parameter event: The event to send. - /// - parameter items: The items to send with this event. May be left out. - open func emit(_ event: String, _ items: SocketData...) { - do { - try emit(event, with: items.map({ try $0.socketRepresentation() })) - } catch { - DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", - type: logType) - - handleClientEvent(.error, data: [event, items, error]) - } - } - - /// Send an event to the server, with optional data items and write completion handler. + /// Send an event to the server, with optional data items and optional write completion handler. /// /// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error` /// will be emitted. The structure of the error data is `[eventName, items, theError]` diff --git a/Source/SocketIO/Client/SocketIOClientSpec.swift b/Source/SocketIO/Client/SocketIOClientSpec.swift index f2658a8..17cee73 100644 --- a/Source/SocketIO/Client/SocketIOClientSpec.swift +++ b/Source/SocketIO/Client/SocketIOClientSpec.swift @@ -92,16 +92,7 @@ public protocol SocketIOClientSpec : AnyObject { /// Disconnects the socket. func disconnect() - /// Send an event to the server, with optional data items. - /// - /// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error` - /// will be emitted. The structure of the error data is `[eventName, items, theError]` - /// - /// - parameter event: The event to send. - /// - parameter items: The items to send with this event. May be left out. - func emit(_ event: String, _ items: SocketData...) - - /// Send an event to the server, with optional data items and write completion handler. + /// Send an event to the server, with optional data items and optional write completion handler. /// /// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error` /// will be emitted. The structure of the error data is `[eventName, items, theError]`