diff --git a/.travis.yml b/.travis.yml index d9ed958..91243b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: objective-c xcode_project: Socket.IO-Client-Swift.xcodeproj # path to your xcodeproj folder xcode_scheme: SocketIO-Mac -osx_image: xcode9 +osx_image: xcode9.2 branches: only: - master diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c9bcee..d7a3dc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +# v13.2.0 + +- Add ability to bypass Data inspection in emits. [#992]((https://github.com/socketio/socket.io-client-swift/issues/992)) +- Allow `SocketEngine` to be subclassed + +# v13.1.3 + +- Fix setting reconnectAttempts [#989]((https://github.com/socketio/socket.io-client-swift/issues/989)) + + # v13.1.2 - Fix [#950](https://github.com/socketio/socket.io-client-swift/issues/950) @@ -29,7 +39,7 @@ Checkout out the migration guide in Usage Docs for a more detailed guide on how What's new: --- -- Adds a new `SocketManager` class that multiplexes multiple namespaces through a single engine. +- Adds a new `SocketManager` class that multiplexes multiple namespaces through a single engine. - Adds `.sentPing` and `.gotPong` client events for tracking ping/pongs. - watchOS support. diff --git a/Package.resolved b/Package.resolved index 3f29cea..88064dd 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,15 +1,6 @@ { "object": { "pins": [ - { - "package": "SSCZLib", - "repositoryURL": "https://github.com/daltoniam/zlib-spm.git", - "state": { - "branch": null, - "revision": "83ac8d719a2f3aa775dbdf116a57f56fb2c49abb", - "version": "1.1.0" - } - }, { "package": "SSCommonCrypto", "repositoryURL": "https://github.com/daltoniam/common-crypto-spm", @@ -27,6 +18,15 @@ "revision": "6cb1c474e09b0a3aa60bcdc7553b570336d6a61a", "version": "3.0.3" } + }, + { + "package": "SSCZLib", + "repositoryURL": "https://github.com/daltoniam/zlib-spm.git", + "state": { + "branch": null, + "revision": "83ac8d719a2f3aa775dbdf116a57f56fb2c49abb", + "version": "1.1.0" + } } ] }, diff --git a/Socket.IO-Client-Swift.podspec b/Socket.IO-Client-Swift.podspec index 4354192..7e07ef7 100644 --- a/Socket.IO-Client-Swift.podspec +++ b/Socket.IO-Client-Swift.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Socket.IO-Client-Swift" s.module_name = "SocketIO" - s.version = "13.1.2" + s.version = "13.1.3" s.summary = "Socket.IO-client for iOS and OS X" s.description = <<-DESC Socket.IO-client for iOS and OS X. @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.requires_arc = true s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", - :tag => 'v13.1.2', + :tag => 'v13.1.3', :submodules => true } s.pod_target_xcconfig = { diff --git a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj index 0157206..3d611e0 100644 --- a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj +++ b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C65763817782DFAC67BE05C /* SocketManager.swift */; }; + 1C6573B22DC9423CDFC32F05 /* SocketRawView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C657533E849FC3E4342C602 /* SocketRawView.swift */; }; 1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */; }; 1C686BE21F869AFD007D8627 /* SocketIOClientConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */; }; 1C686BE31F869AFD007D8627 /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */; }; @@ -61,6 +62,7 @@ /* Begin PBXFileReference section */ 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManagerSpec.swift; sourceTree = ""; }; + 1C657533E849FC3E4342C602 /* SocketRawView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketRawView.swift; sourceTree = ""; }; 1C65763817782DFAC67BE05C /* SocketManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManager.swift; sourceTree = ""; }; 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketIOClientConfigurationTest.swift; sourceTree = ""; }; 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = ""; }; @@ -300,6 +302,7 @@ DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */, DD52B1D9BC4AE46D38D827DE /* SocketIOStatus.swift */, DD52B57FFEE8560CFFD793B3 /* SocketIOClientConfiguration.swift */, + 1C657533E849FC3E4342C602 /* SocketRawView.swift */, ); name = Client; path = Source/SocketIO/Client; @@ -480,6 +483,7 @@ DD52B9412F660F828B683422 /* SocketParsable.swift in Sources */, 1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */, 1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */, + 1C6573B22DC9423CDFC32F05 /* SocketRawView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/SocketIO/Ack/SocketAckEmitter.swift b/Source/SocketIO/Ack/SocketAckEmitter.swift index a7c80be..417fe94 100644 --- a/Source/SocketIO/Ack/SocketAckEmitter.swift +++ b/Source/SocketIO/Ack/SocketAckEmitter.swift @@ -29,8 +29,20 @@ import Foundation /// /// **NOTE**: You should not store this beyond the life of the event handler. public final class SocketAckEmitter : NSObject { - let socket: SocketIOClient - let ackNum: Int + private unowned let socket: SocketIOClient + private let ackNum: Int + + /// A view into this emitter where emits do not check for binary data. + /// + /// Usage: + /// + /// ```swift + /// ack.rawEmitView.with(myObject) + /// ``` + /// + /// **NOTE**: It is not safe to hold on to this view beyond the life of the socket. + @objc + public private(set) lazy var rawEmitView = SocketRawAckView(socket: socket, ackNum: ackNum) // MARK: Properties @@ -91,13 +103,16 @@ public final class SocketAckEmitter : NSObject { /// ``` public final class OnAckCallback : NSObject { private let ackNumber: Int + private let binary: Bool private let items: [Any] + private weak var socket: SocketIOClient? - init(ackNumber: Int, items: [Any], socket: SocketIOClient) { + init(ackNumber: Int, items: [Any], socket: SocketIOClient, binary: Bool = true) { self.ackNumber = ackNumber self.items = items self.socket = socket + self.binary = binary } deinit { @@ -116,7 +131,7 @@ public final class OnAckCallback : NSObject { guard let socket = self.socket, ackNumber != -1 else { return } socket.ackHandlers.addAck(ackNumber, callback: callback) - socket.emit(items, ack: ackNumber) + socket.emit(items, ack: ackNumber, binary: binary) guard seconds != 0 else { return } diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index a8f12f4..04f35a5 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -67,6 +67,18 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { @objc public private(set) weak var manager: SocketManagerSpec? + /// A view into this socket where emits do not check for binary data. + /// + /// Usage: + /// + /// ```swift + /// socket.rawEmitView.emit("myEvent", myObject) + /// ``` + /// + /// **NOTE**: It is not safe to hold on to this view beyond the life of the socket. + @objc + public private(set) lazy var rawEmitView = SocketRawView(socket: self) + /// The status of this client. @objc public private(set) var status = SocketIOStatus.notConnected { @@ -148,7 +160,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { } } - private func createOnAck(_ items: [Any]) -> OnAckCallback { + func createOnAck(_ items: [Any], binary: Bool = true) -> OnAckCallback { currentAck += 1 return OnAckCallback(ackNumber: currentAck, items: items, socket: self) @@ -216,11 +228,6 @@ 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]) { - guard status == .connected else { - handleClientEvent(.error, data: ["Tried emitting \(event) when not connected"]) - return - } - emit([event] + items) } @@ -277,16 +284,16 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { return createOnAck([event] + items) } - func emit(_ data: [Any], ack: Int? = nil) { + func emit(_ data: [Any], ack: Int? = nil, binary: Bool = true, isAck: Bool = false) { guard status == .connected else { handleClientEvent(.error, data: ["Tried emitting when not connected"]) return } - let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false) + let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: isAck, checkForBinary: binary) let str = packet.packetString - DefaultSocketLogger.Logger.log("Emitting: \(str)", type: logType) + DefaultSocketLogger.Logger.log("Emitting: \(str), Ack: \(isAck)", type: logType) manager?.engine?.send(str, withData: packet.binary) } @@ -298,14 +305,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec { /// - parameter ack: The ack number. /// - parameter with: The data for this ack. open func emitAck(_ ack: Int, with items: [Any]) { - guard status == .connected else { return } - - let packet = SocketPacket.packetFromEmit(items, id: ack, nsp: nsp, ack: true) - let str = packet.packetString - - DefaultSocketLogger.Logger.log("Emitting Ack: \(str)", type: logType) - - manager?.engine?.send(str, withData: packet.binary) + emit(items, ack: ack, binary: true, isAck: true) } /// Called when socket.io has acked one of our emits. Causes the corresponding ack callback to be called. diff --git a/Source/SocketIO/Client/SocketIOClientOption.swift b/Source/SocketIO/Client/SocketIOClientOption.swift index 3e9114f..02d8898 100644 --- a/Source/SocketIO/Client/SocketIOClientOption.swift +++ b/Source/SocketIO/Client/SocketIOClientOption.swift @@ -55,6 +55,8 @@ public enum SocketIOClientOption : ClientOption { /// The queue that all interaction with the client should occur on. This is the queue that event handlers are /// called on. + /// + /// **This should be a serial queue! Concurrent queues are not supported and might cause crashes and races**. case handleQueue(DispatchQueue) /// If passed `true`, the client will log debug information. This should be turned off in production code. diff --git a/Source/SocketIO/Client/SocketIOClientSpec.swift b/Source/SocketIO/Client/SocketIOClientSpec.swift index 739c7e9..5015e44 100644 --- a/Source/SocketIO/Client/SocketIOClientSpec.swift +++ b/Source/SocketIO/Client/SocketIOClientSpec.swift @@ -43,6 +43,17 @@ public protocol SocketIOClientSpec : class { /// **Must** start with a `/`. var nsp: String { get } + /// A view into this socket where emits do not check for binary data. + /// + /// Usage: + /// + /// ```swift + /// socket.rawEmitView.emit("myEvent", myObject) + /// ``` + /// + /// **NOTE**: It is not safe to hold on to this view beyond the life of the socket. + var rawEmitView: SocketRawView { get } + /// The status of this client. var status: SocketIOStatus { get } diff --git a/Source/SocketIO/Client/SocketRawView.swift b/Source/SocketIO/Client/SocketRawView.swift new file mode 100644 index 0000000..73fe080 --- /dev/null +++ b/Source/SocketIO/Client/SocketRawView.swift @@ -0,0 +1,163 @@ +// +// SocketRawView.swift +// Socket.IO-Client-Swift +// +// Created by Erik Little on 3/30/18. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// Class that gives a backwards compatible way to cause an emit not to recursively check for Data objects. +/// +/// Usage: +/// +/// ```swift +/// socket.rawEmitView.emit("myEvent", myObject) +/// ``` +public final class SocketRawView : NSObject { + private unowned let socket: SocketIOClient + + init(socket: SocketIOClient) { + self.socket = socket + } + + /// 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. + public func emit(_ event: String, _ items: SocketData...) { + do { + try emit(event, with: items.map({ try $0.socketRepresentation() })) + } catch let err { + DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", + type: "SocketIOClient") + + socket.handleClientEvent(.error, data: [event, items, err]) + } + } + + /// 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. + @objc + public func emit(_ event: String, with items: [Any]) { + socket.emit([event] + items, binary: false) + } + + /// Sends a message to the server, requesting an ack. + /// + /// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack. + /// Check that your server's api will ack the event being sent. + /// + /// 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]` + /// + /// Example: + /// + /// ```swift + /// socket.emitWithAck("myEvent", 1).timingOut(after: 1) {data in + /// ... + /// } + /// ``` + /// + /// - parameter event: The event to send. + /// - parameter items: The items to send with this event. May be left out. + /// - returns: An `OnAckCallback`. You must call the `timingOut(after:)` method before the event will be sent. + public func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback { + do { + return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() })) + } catch let err { + DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", + type: "SocketIOClient") + + socket.handleClientEvent(.error, data: [event, items, err]) + + return OnAckCallback(ackNumber: -1, items: [], socket: socket) + } + } + + /// Same as emitWithAck, but for Objective-C + /// + /// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack. + /// Check that your server's api will ack the event being sent. + /// + /// Example: + /// + /// ```swift + /// socket.emitWithAck("myEvent", with: [1]).timingOut(after: 1) {data in + /// ... + /// } + /// ``` + /// + /// - parameter event: The event to send. + /// - parameter items: The items to send with this event. Use `[]` to send nothing. + /// - returns: An `OnAckCallback`. You must call the `timingOut(after:)` method before the event will be sent. + @objc + public func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback { + return socket.createOnAck([event] + items, binary: false) + } +} + +/// Class that gives a backwards compatible way to cause an emit not to recursively check for Data objects. +/// +/// Usage: +/// +/// ```swift +/// ack.rawEmitView.with(myObject) +/// ``` +public final class SocketRawAckView : NSObject { + private unowned let socket: SocketIOClient + private let ackNum: Int + + init(socket: SocketIOClient, ackNum: Int) { + self.socket = socket + self.ackNum = ackNum + } + + /// Call to ack receiving this event. + /// + /// 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 `[ackNum, items, theError]` + /// + /// - parameter items: A variable number of items to send when acking. + public func with(_ items: SocketData...) { + guard ackNum != -1 else { return } + + do { + socket.emit(try items.map({ try $0.socketRepresentation() }), ack: ackNum, binary: false, isAck: true) + } catch let err { + socket.handleClientEvent(.error, data: [ackNum, items, err]) + } + } + + /// Call to ack receiving this event. + /// + /// - parameter items: An array of items to send when acking. Use `[]` to send nothing. + @objc + public func with(_ items: [Any]) { + guard ackNum != -1 else { return } + + socket.emit(items, ack: ackNum, binary: false, isAck: true) + } +} diff --git a/Source/SocketIO/Engine/SocketEngine.swift b/Source/SocketIO/Engine/SocketEngine.swift index fc1c1ad..4904ee5 100644 --- a/Source/SocketIO/Engine/SocketEngine.swift +++ b/Source/SocketIO/Engine/SocketEngine.swift @@ -28,8 +28,7 @@ import Starscream /// The class that handles the engine.io protocol and transports. /// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods. -public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket, - ConfigSettable { +open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket, ConfigSettable { // MARK: Properties private static let logType = "SocketEngine" @@ -164,7 +163,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// - parameter client: The client for this engine. /// - parameter url: The url for this engine. /// - parameter options: The options for this engine. - public convenience init(client: SocketEngineClient, url: URL, options: [String: Any]?) { + public required convenience init(client: SocketEngineClient, url: URL, options: [String: Any]?) { self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? []) } @@ -214,7 +213,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } /// Starts the connection to the server. - public func connect() { + open func connect() { engineQueue.async { self._connect() } @@ -318,7 +317,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } /// Called when an error happens during execution. Causes a disconnection. - public func didError(reason: String) { + open func didError(reason: String) { DefaultSocketLogger.Logger.error("\(reason)", type: SocketEngine.logType) client?.engineDidError(reason: reason) disconnect(reason: reason) @@ -327,7 +326,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// Disconnects from the server. /// /// - parameter reason: The reason for the disconnection. This is communicated up to the client. - public func disconnect(reason: String) { + open func disconnect(reason: String) { engineQueue.async { self._disconnect(reason: reason) } @@ -359,7 +358,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// WebSocket mode. /// /// **You shouldn't call this directly** - public func doFastUpgrade() { + open func doFastUpgrade() { if waitingForPoll { DefaultSocketLogger.Logger.error("Outstanding poll when switched to WebSockets," + "we'll probably disconnect soon. You should report this.", type: SocketEngine.logType) @@ -392,7 +391,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// the engine is attempting to upgrade to WebSocket it does not do any POSTing. /// /// **You shouldn't call this directly** - public func flushWaitingForPostToWebSocket() { + open func flushWaitingForPostToWebSocket() { guard let ws = self.ws else { return } for msg in postWait { @@ -474,7 +473,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// Parses raw binary received from engine.io. /// /// - parameter data: The data to parse. - public func parseEngineData(_ data: Data) { + open func parseEngineData(_ data: Data) { DefaultSocketLogger.Logger.log("Got binary data: \(data)", type: SocketEngine.logType) client?.parseEngineBinaryData(data.subdata(in: 1.. SocketPacket { - let (parsedData, binary) = deconstructData(items) + static func packetFromEmit(_ items: [Any], id: Int, nsp: String, ack: Bool, checkForBinary: Bool = true) -> SocketPacket { + if checkForBinary { + let (parsedData, binary) = deconstructData(items) - return SocketPacket(type: findType(binary.count, ack: ack), data: parsedData, id: id, nsp: nsp, - binary: binary) + return SocketPacket(type: findType(binary.count, ack: ack), data: parsedData, id: id, nsp: nsp, + binary: binary) + } else { + return SocketPacket(type: findType(0, ack: ack), data: items, id: id, nsp: nsp) + } } } diff --git a/Tests/TestSocketIO/SocketMangerTest.swift b/Tests/TestSocketIO/SocketMangerTest.swift index 8b83cf8..22da481 100644 --- a/Tests/TestSocketIO/SocketMangerTest.swift +++ b/Tests/TestSocketIO/SocketMangerTest.swift @@ -79,13 +79,15 @@ class SocketMangerTest : XCTestCase { .handleQueue(queue), .forceNew(true), .reconnects(false), - .reconnectWait(5) + .reconnectWait(5), + .reconnectAttempts(5) ]) XCTAssertEqual(manager.handleQueue, queue) XCTAssertTrue(manager.forceNew) XCTAssertFalse(manager.reconnects) XCTAssertEqual(manager.reconnectWait, 5) + XCTAssertEqual(manager.reconnectAttempts, 5) } func testManagerRemovesSocket() { diff --git a/Tests/TestSocketIOObjc/SocketObjectiveCTest.m b/Tests/TestSocketIOObjc/SocketObjectiveCTest.m index 7e18359..1ad3475 100644 --- a/Tests/TestSocketIOObjc/SocketObjectiveCTest.m +++ b/Tests/TestSocketIOObjc/SocketObjectiveCTest.m @@ -26,6 +26,7 @@ - (void)testOnSyntax { [self.socket on:@"someCallback" callback:^(NSArray* data, SocketAckEmitter* ack) { [ack with:@[@1]]; + [[ack rawEmitView] with:@[@"hello"]]; }]; } @@ -66,6 +67,10 @@ [self.socket emit:@"testEmit" with:@[@YES]]; } +- (void)testRawEmitSyntax { + [[self.socket rawEmitView] emit:@"myEvent" with:@[@1]]; +} + - (void)testEmitWithAckSyntax { [[self.socket emitWithAck:@"testAckEmit" with:@[@YES]] timingOutAfter:0 callback:^(NSArray* data) { }]; }