diff --git a/README.md b/README.md index 4f1773d..ec44b92 100644 --- a/README.md +++ b/README.md @@ -150,8 +150,8 @@ case Secure(Bool) // If the connection should use TLS. Default is false. ``` Methods ------- -1. `on(event: String, callback: NormalCallback)` - Adds a handler for an event. Items are passed by an array. `ack` can be used to send an ack when one is requested. See example. -2. `once(event: String, callback: NormalCallback)` - Adds a handler that will only be executed once. +1. `on(event: String, callback: NormalCallback) -> NSUUID` - Adds a handler for an event. Items are passed by an array. `ack` can be used to send an ack when one is requested. See example. Returns a unique id for the handler. +2. `once(event: String, callback: NormalCallback) -> NSUUID` - Adds a handler that will only be executed once. Returns a unique id for the handler. 3. `onAny(callback:((event: String, items: AnyObject?)) -> Void)` - Adds a handler for all events. It will be called on any received event. 4. `emit(event: String, _ items: AnyObject...)` - Sends a message. Can send multiple items. 5. `emit(event: String, withItems items: [AnyObject])` - `emit` for Objective-C @@ -164,7 +164,8 @@ Methods 12. `joinNamespace()` - Causes the client to join nsp. Shouldn't need to be called unless you change nsp manually. 13. `leaveNamespace()` - Causes the client to leave the nsp and go back to / 14. `off(event: String)` - Removes all event handlers for event. -15. `removeAllHandlers()` - Removes all handlers. +15. `off(id id: NSUUID)` - Removes the event that corresponds to id. +16. `removeAllHandlers()` - Removes all handlers. Client Events ------ diff --git a/SocketIO-MacTests/SocketSideEffectTest.swift b/SocketIO-MacTests/SocketSideEffectTest.swift index 4f35516..84d391f 100644 --- a/SocketIO-MacTests/SocketSideEffectTest.swift +++ b/SocketIO-MacTests/SocketSideEffectTest.swift @@ -57,6 +57,36 @@ class SocketSideEffectTest: XCTestCase { waitForExpectationsWithTimeout(3, handler: nil) } + func testHandleOnceEvent() { + let expectation = expectationWithDescription("handled event") + socket.once("test") {data, ack in + XCTAssertEqual(data[0] as? String, "hello world") + XCTAssertEqual(self.socket.testHandlers.count, 0) + expectation.fulfill() + } + + socket.parseSocketMessage("2[\"test\",\"hello world\"]") + waitForExpectationsWithTimeout(3, handler: nil) + } + + func testOffWithEvent() { + socket.on("test") {data, ack in } + XCTAssertEqual(socket.testHandlers.count, 1) + socket.on("test") {data, ack in } + XCTAssertEqual(socket.testHandlers.count, 2) + socket.off("test") + XCTAssertEqual(socket.testHandlers.count, 0) + } + + func testOffWithId() { + let handler = socket.on("test") {data, ack in } + XCTAssertEqual(socket.testHandlers.count, 1) + socket.on("test") {data, ack in } + XCTAssertEqual(socket.testHandlers.count, 2) + socket.off(id: handler) + XCTAssertEqual(socket.testHandlers.count, 1) + } + func testHandleBinaryEvent() { let expectation = expectationWithDescription("handled binary event") socket.on("test") {data, ack in diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 51dcb3f..385ecfa 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -389,39 +389,46 @@ public final class SocketIOClient: NSObject, SocketEngineClient { handlers = handlers.filter { $0.event != event } } + /** + Removes a handler with the specified UUID gotten from an `on` or `once` + */ + public func off(id id: NSUUID) { + DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id) + + handlers = handlers.filter { $0.id != id } + } + /** Adds a handler for an event. + Returns: A unique id for the handler */ - public func on(event: String, callback: NormalCallback) { + public func on(event: String, callback: NormalCallback) -> NSUUID { DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event) let handler = SocketEventHandler(event: event, id: NSUUID(), callback: callback) handlers.append(handler) + + return handler.id } /** Adds a single-use handler for an event. + Returns: A unique id for the handler */ - public func once(event: String, callback: NormalCallback) { + public func once(event: String, callback: NormalCallback) -> NSUUID { DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event) let id = NSUUID() let handler = SocketEventHandler(event: event, id: id) {[weak self] data, ack in guard let this = self else {return} - this.handlers = this.handlers.filter {$0.id != id} + this.off(id: id) callback(data, ack) } handlers.append(handler) - } - - /** - Removes all handlers. - Can be used after disconnecting to break any potential remaining retain cycles. - */ - public func removeAllHandlers() { - handlers.removeAll(keepCapacity: false) + + return handler.id } /** @@ -457,6 +464,14 @@ public final class SocketIOClient: NSObject, SocketEngineClient { tryReconnect() } + /** + Removes all handlers. + Can be used after disconnecting to break any potential remaining retain cycles. + */ + public func removeAllHandlers() { + handlers.removeAll(keepCapacity: false) + } + private func tryReconnect() { if reconnectTimer == nil { DefaultSocketLogger.Logger.log("Starting reconnect", type: logType) @@ -495,6 +510,10 @@ public final class SocketIOClient: NSObject, SocketEngineClient { // Test extensions extension SocketIOClient { + var testHandlers: [SocketEventHandler] { + return handlers + } + func setTestable() { status = .Connected }