From 9a2b59ad78541e32d2de67b6b171c4a9b7ac2122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Fossli?= Date: Tue, 4 Apr 2017 11:03:42 +0200 Subject: [PATCH 01/24] Update README.md --- README.md | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index a891b13..f366683 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ [![Build Status](https://travis-ci.org/socketio/socket.io-client-swift.svg?branch=master)](https://travis-ci.org/socketio/socket.io-client-swift) -#Socket.IO-Client-Swift +# Socket.IO-Client-Swift Socket.IO-client for iOS/OS X. -##Example +## Example ```swift import SocketIO @@ -26,7 +26,7 @@ socket.on("currentAmount") {data, ack in socket.connect() ``` -##Objective-C Example +## Objective-C Example ```objective-c @import SocketIO; NSURL* url = [[NSURL alloc] initWithString:@"http://localhost:8080"]; @@ -50,14 +50,14 @@ SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{ ``` -##Features +## Features - Supports socket.io 1.0+ - Supports binary - Supports Polling and WebSockets - Supports TLS/SSL - Can be used from Objective-C -##Installation +## Installation Requires Swift 3/Xcode 8.x If you need swift 2.3 use the swift2.3 tag (Pre-Swift 3 support is no longer maintained) @@ -70,13 +70,11 @@ If you need Swift 1.2 use v2.4.5 (Pre-Swift 2 support is no longer maintained) If you need Swift 1.1 use v1.5.2. (Pre-Swift 1.2 support is no longer maintained) -Manually (iOS 7+) ------------------ +### Manually (iOS 7+) 1. Copy the Source folder into your Xcode project. (Make sure you add the files to your target(s)) 2. If you plan on using this from Objective-C, read [this](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html) on exposing Swift code to Objective-C. -Swift Package Manager ---------------------- +### Swift Package Manager Add the project as a dependency to your Package.swift: ```swift import PackageDescription @@ -91,8 +89,7 @@ let package = Package( Then import `import SocketIO`. -Carthage ------------------ +### Carthage Add this line to your `Cartfile`: ``` github "socketio/socket.io-client-swift" ~> 8.3.3 # Or latest version @@ -100,8 +97,7 @@ github "socketio/socket.io-client-swift" ~> 8.3.3 # Or latest version Run `carthage update --platform ios,macosx`. -CocoaPods 1.0.0 or later ------------------- +### CocoaPods 1.0.0 or later Create `Podfile` and add `pod 'Socket.IO-Client-Swift'`: ```ruby @@ -131,8 +127,7 @@ Objective-C: @import SocketIO; ``` -CocoaSeeds ------------------ +### CocoaSeeds Add this line to your `Seedfile`: @@ -143,15 +138,14 @@ github "socketio/socket.io-client-swift", "v8.3.3", :files => "Source/*.swift" # Run `seed install`. -##API -Constructors ------------ +## API + +### Constructors `init(var socketURL: NSURL, config: SocketIOClientConfiguration = [])` - Creates a new SocketIOClient. If your socket.io server is secure, you need to specify `https` in your socketURL. `convenience init(socketURL: NSURL, options: NSDictionary?)` - Same as above, but meant for Objective-C. See Options on how convert between SocketIOClientOptions and dictionary keys. -Options -------- +### Options All options are a case of SocketIOClientOption. To get the Objective-C Option, convert the name to lowerCamelCase. ```swift @@ -176,8 +170,7 @@ case security(SSLSecurity) // Allows you to set which certs are valid. Useful fo case selfSigned(Bool) // Sets WebSocket.selfSignedSSL. Use this if you're using self-signed certs. case voipEnabled(Bool) // Only use this option if you're using the client with VoIP services. Changes the way the WebSocket is created. Default is false ``` -Methods -------- +### Methods 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. @@ -195,18 +188,17 @@ Methods 15. `off(id id: NSUUID)` - Removes the event that corresponds to id. 16. `removeAllHandlers()` - Removes all handlers. -Client Events ------- +### Client Events 1. `connect` - Emitted when on a successful connection. 2. `disconnect` - Emitted when the connection is closed. 3. `error` - Emitted on an error. 4. `reconnect` - Emitted when the connection is starting to reconnect. 5. `reconnectAttempt` - Emitted when attempting to reconnect. -##Detailed Example +## Detailed Example A more detailed example can be found [here](https://github.com/nuclearace/socket.io-client-swift-example) An example using the Swift Package Manager can be found [here](https://github.com/nuclearace/socket.io-client-swift-spm-example) -##License +## License MIT From e29c9043b25758f7812c335427dfd668c9e1d4b5 Mon Sep 17 00:00:00 2001 From: musicabbage Date: Thu, 13 Apr 2017 12:08:38 +0800 Subject: [PATCH 02/24] =?UTF-8?q?remove=20engine=E2=80=99s=20listener=20be?= =?UTF-8?q?fore=20assign=20new=20instance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/SocketEngine.swift | 5 +++++ Source/SocketIOClient.swift | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 3bf4ae6..51e9523 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -243,6 +243,11 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } private func createWebsocketAndConnect() { + + if let oldWs = ws { + oldWs.delegate = nil + } + ws = WebSocket(url: urlWebSocketWithSid as URL) if cookies != nil { diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 0085d60..3660bda 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -120,6 +120,10 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable private func addEngine() -> SocketEngineSpec { DefaultSocketLogger.Logger.log("Adding engine", type: logType, args: "") + if let oldEngine = engine { + oldEngine.client = nil + } + engine = SocketEngine(client: self, url: socketURL, config: config) return engine! From 907b1b3ae2481369ba22c7b8cec98a5a454def40 Mon Sep 17 00:00:00 2001 From: musicabbage Date: Fri, 14 Apr 2017 14:57:46 +0800 Subject: [PATCH 03/24] Removed if-statement for review notes https://github.com/socketio/socket.io-client-swift/pull/651#pullrequestreview-32616528 --- Source/SocketEngine.swift | 5 +---- Source/SocketIOClient.swift | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 51e9523..758bc43 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -244,10 +244,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll private func createWebsocketAndConnect() { - if let oldWs = ws { - oldWs.delegate = nil - } - + ws?.delegate = nil ws = WebSocket(url: urlWebSocketWithSid as URL) if cookies != nil { diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 3660bda..a96ceda 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -120,10 +120,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable private func addEngine() -> SocketEngineSpec { DefaultSocketLogger.Logger.log("Adding engine", type: logType, args: "") - if let oldEngine = engine { - oldEngine.client = nil - } - + engine?.client = nil engine = SocketEngine(client: self, url: socketURL, config: config) return engine! From 7777c76daee0bca0788ea5254d5f0fa79261f60c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 May 2017 18:43:46 -0400 Subject: [PATCH 04/24] refactor protocol --- Source/SocketIOClient.swift | 2 +- Source/SocketParsable.swift | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index a96ceda..31f0c37 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -24,7 +24,7 @@ import Foundation -public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable { +public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { public let socketURL: URL public private(set) var engine: SocketEngineSpec? diff --git a/Source/SocketParsable.swift b/Source/SocketParsable.swift index 7c9ce21..c6c9e6a 100644 --- a/Source/SocketParsable.swift +++ b/Source/SocketParsable.swift @@ -27,7 +27,7 @@ protocol SocketParsable : SocketIOClientSpec { func parseSocketMessage(_ message: String) } -extension SocketParsable { +extension SocketParsable where Self: SocketIOClientSpec { private func isCorrectNamespace(_ nsp: String) -> Bool { return nsp == self.nsp } @@ -107,8 +107,6 @@ extension SocketParsable { } } - - var dataArray = message[message.characters.index(reader.currentIndex, offsetBy: 1).. Date: Mon, 1 May 2017 18:45:53 -0400 Subject: [PATCH 05/24] Parsable doesn't have to be a client --- Source/SocketParsable.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/SocketParsable.swift b/Source/SocketParsable.swift index c6c9e6a..28b431d 100644 --- a/Source/SocketParsable.swift +++ b/Source/SocketParsable.swift @@ -22,7 +22,7 @@ import Foundation -protocol SocketParsable : SocketIOClientSpec { +protocol SocketParsable { func parseBinaryData(_ data: Data) func parseSocketMessage(_ message: String) } From e5eec3e97fad45396909e4134fe7684178499773 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 3 May 2017 22:21:33 -0400 Subject: [PATCH 06/24] Fix #657 --- Source/SocketEngine.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 20f0030..02b1d81 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -191,7 +191,8 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll return } - let reqPolling = NSMutableURLRequest(url: urlPolling) + var reqPolling = URLRequest(url: urlPolling, cachePolicy: .reloadIgnoringLocalCacheData, + timeoutInterval: 60.0) if cookies != nil { let headers = HTTPCookie.requestHeaderFields(with: cookies!) @@ -204,7 +205,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } } - doLongPoll(for: reqPolling as URLRequest) + doLongPoll(for: reqPolling) } private func createURLs() -> (URL, URL) { From 7e494f4bcb135be5b4f57c6538e590ced8391688 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 21:20:34 -0400 Subject: [PATCH 07/24] add ignore for appcode --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 9f4b1d3..069348b 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ DerivedData *.xcuserstate Socket.IO-Test-Server/node_modules/* + +.idea/ From ed049e888d5d83c784540c1980a4d259614a823c Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 3 May 2017 22:48:25 -0400 Subject: [PATCH 08/24] Make engine single queued Fix polling allow building of refactor branch remove self reference Some refactoring --- .travis.yml | 1 + Source/SocketEngine.swift | 113 +++++++++++++++------------- Source/SocketEnginePollable.swift | 119 ++++++++++++++---------------- Source/SocketEngineSpec.swift | 4 +- 4 files changed, 119 insertions(+), 118 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1c99082..cd54215 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ branches: only: - master - development + - refactor-engine before_install: - brew update - brew outdated xctool || brew upgrade xctool diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 02b1d81..cd1e8d0 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -22,12 +22,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch import Foundation public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket { - public let emitQueue = DispatchQueue(label: "com.socketio.engineEmitQueue", attributes: []) - public let handleQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: []) - public let parseQueue = DispatchQueue(label: "com.socketio.engineParseQueue", attributes: []) + public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: []) public var connectParams: [String: Any]? { didSet { @@ -101,7 +100,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll forceWebsockets = force case let .path(path): socketPath = path - + if !socketPath.hasSuffix("/") { socketPath += "/" } @@ -119,12 +118,12 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } super.init() - + sessionDelegate = sessionDelegate ?? self - + (urlPolling, urlWebSocket) = createURLs() } - + public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?) { self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? []) } @@ -139,7 +138,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll do { let dict = try msg.toNSDictionary() guard let error = dict["message"] as? String else { return } - + /* 0: Unknown transport 1: Unknown sid @@ -155,7 +154,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll private func handleBase64(message: String) { // binary in base64 string let noPrefix = message[message.index(message.startIndex, offsetBy: 2).. pongsMissedMax { client?.engineDidClose(reason: "Ping timeout") - + return } guard let pingInterval = pingInterval else { return } - + pongsMissed += 1 write("", withType: .ping, withData: []) - - let time = DispatchTime.now() + Double(Int64(pingInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC) - DispatchQueue.main.asyncAfter(deadline: time) {[weak self] in self?.sendPing() } + + engineQueue.asyncAfter(deadline: DispatchTime.now() + Double(pingInterval)) {[weak self] in self?.sendPing() } } // Moves from long-polling to websockets @@ -501,16 +508,16 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// Write a message, independent of transport. public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) { - emitQueue.async { + engineQueue.async { guard self.connected else { return } if self.websocket { DefaultSocketLogger.Logger.log("Writing ws: %@ has data: %@", - type: self.logType, args: msg, data.count != 0) + type: self.logType, args: msg, data.count != 0) self.sendWebSocketMessage(msg, withType: type, withData: data) } else if !self.probing { DefaultSocketLogger.Logger.log("Writing poll: %@ has data: %@", - type: self.logType, args: msg, data.count != 0) + type: self.logType, args: msg, data.count != 0) self.sendPollMessage(msg, withType: type, withData: data) } else { self.probeWait.append((msg, type, data)) @@ -535,7 +542,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll if closed { client?.engineDidClose(reason: "Disconnect") - + return } @@ -557,7 +564,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll extension SocketEngine { public func URLSession(session: URLSession, didBecomeInvalidWithError error: NSError?) { DefaultSocketLogger.Logger.error("Engine URLSession became invalid", type: "SocketEngine") - + didError(reason: "Engine URLSession became invalid") } } diff --git a/Source/SocketEnginePollable.swift b/Source/SocketEnginePollable.swift index b050975..4bb4905 100644 --- a/Source/SocketEnginePollable.swift +++ b/Source/SocketEnginePollable.swift @@ -27,7 +27,7 @@ import Foundation /// Protocol that is used to implement socket.io polling support public protocol SocketEnginePollable : SocketEngineSpec { var invalidated: Bool { get } - /// Holds strings waiting to be sent over polling. + /// Holds strings waiting to be sent over polling. /// You shouldn't need to mess with this. var postWait: [String] { get set } var session: URLSession? { get } @@ -37,7 +37,7 @@ public protocol SocketEnginePollable : SocketEngineSpec { /// Because socket.io doesn't let you send two post request at the same time /// we have to keep track if there's an outstanding post var waitingForPost: Bool { get set } - + func doPoll() func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) func stopPolling() @@ -47,95 +47,94 @@ public protocol SocketEnginePollable : SocketEngineSpec { extension SocketEnginePollable { private func addHeaders(for req: URLRequest) -> URLRequest { var req = req - + if cookies != nil { let headers = HTTPCookie.requestHeaderFields(with: cookies!) req.allHTTPHeaderFields = headers } - + if extraHeaders != nil { for (headerName, value) in extraHeaders! { req.setValue(value, forHTTPHeaderField: headerName) } } - + return req } - + func createRequestForPostWithPostWait() -> URLRequest { defer { postWait.removeAll(keepingCapacity: true) } var postStr = "" - + for packet in postWait { let len = packet.characters.count - + postStr += "\(len):\(packet)" } - + DefaultSocketLogger.Logger.log("Created POST string: %@", type: "SocketEnginePolling", args: postStr) - + var req = URLRequest(url: urlPollingWithSid) let postData = postStr.data(using: .utf8, allowLossyConversion: false)! - + req = addHeaders(for: req) - + req.httpMethod = "POST" req.setValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type") req.httpBody = postData req.setValue(String(postData.count), forHTTPHeaderField: "Content-Length") - - return req as URLRequest + + return req } - + public func doPoll() { if websocket || waitingForPoll || !connected || closed { return } - - waitingForPoll = true - + var req = URLRequest(url: urlPollingWithSid) - req = addHeaders(for: req) + doLongPoll(for: req ) } - + func doRequest(for req: URLRequest, callbackWith callback: @escaping (Data?, URLResponse?, Error?) -> Void) { if !polling || closed || invalidated || fastUpgrade { return } - - DefaultSocketLogger.Logger.log("Doing polling request", type: "SocketEnginePolling") - + + DefaultSocketLogger.Logger.log("Doing polling %@ %@", type: "SocketEnginePolling", + args: req.httpMethod ?? "", req) + session?.dataTask(with: req, completionHandler: callback).resume() } - + func doLongPoll(for req: URLRequest) { + waitingForPoll = true + doRequest(for: req) {[weak self] data, res, err in guard let this = self, this.polling else { return } - + if err != nil || data == nil { DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling") - + if this.polling { this.didError(reason: err?.localizedDescription ?? "Error") } - + return } - + DefaultSocketLogger.Logger.log("Got polling response", type: "SocketEnginePolling") - + if let str = String(data: data!, encoding: String.Encoding.utf8) { - this.parseQueue.async { - this.parsePollingMessage(str) - } + this.parsePollingMessage(str) } - + this.waitingForPoll = false - + if this.fastUpgrade { this.doFastUpgrade() } else if !this.closed && this.polling { @@ -143,7 +142,7 @@ extension SocketEnginePollable { } } } - + private func flushWaitingForPost() { if postWait.count == 0 || !connected { return @@ -151,79 +150,75 @@ extension SocketEnginePollable { flushWaitingForPostToWebSocket() return } - + let req = createRequestForPostWithPostWait() - + waitingForPost = true - + DefaultSocketLogger.Logger.log("POSTing", type: "SocketEnginePolling") - + doRequest(for: req) {[weak self] data, res, err in guard let this = self else { return } - + if err != nil { DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling") - + if this.polling { this.didError(reason: err?.localizedDescription ?? "Error") } - + return } - + this.waitingForPost = false - - this.emitQueue.async { - if !this.fastUpgrade { - this.flushWaitingForPost() - this.doPoll() - } + + if !this.fastUpgrade { + this.flushWaitingForPost() + this.doPoll() } } } - + func parsePollingMessage(_ str: String) { guard str.characters.count != 1 else { return } - + var reader = SocketStringReader(message: str) - + while reader.hasNext { if let n = Int(reader.readUntilOccurence(of: ":")) { - let str = reader.read(count: n) - - handleQueue.async { self.parseEngineMessage(str, fromPolling: true) } + parseEngineMessage(reader.read(count: n), fromPolling: true) } else { - handleQueue.async { self.parseEngineMessage(str, fromPolling: true) } + parseEngineMessage(str, fromPolling: true) break } } } - + /// Send polling message. /// Only call on emitQueue public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) { DefaultSocketLogger.Logger.log("Sending poll: %@ as type: %@", type: "SocketEnginePolling", args: message, type.rawValue) let fixedMessage: String - + if doubleEncodeUTF8 { fixedMessage = doubleEncodeUTF8(message) } else { fixedMessage = message } - + postWait.append(String(type.rawValue) + fixedMessage) - + for data in datas { if case let .right(bin) = createBinaryDataForSend(using: data) { postWait.append(bin) } } - + if !waitingForPost { flushWaitingForPost() } } - + public func stopPolling() { waitingForPoll = false waitingForPost = false diff --git a/Source/SocketEngineSpec.swift b/Source/SocketEngineSpec.swift index f862889..46a7947 100644 --- a/Source/SocketEngineSpec.swift +++ b/Source/SocketEngineSpec.swift @@ -32,15 +32,13 @@ import Foundation var connectParams: [String: Any]? { get set } var doubleEncodeUTF8: Bool { get } var cookies: [HTTPCookie]? { get } + var engineQueue: DispatchQueue { get } var extraHeaders: [String: String]? { get } var fastUpgrade: Bool { get } var forcePolling: Bool { get } var forceWebsockets: Bool { get } - var parseQueue: DispatchQueue { get } var polling: Bool { get } var probing: Bool { get } - var emitQueue: DispatchQueue { get } - var handleQueue: DispatchQueue { get } var sid: String { get } var socketPath: String { get } var urlPolling: URL { get } From 84dd3078d80d4a84f6ab41af4c70bcbc3bf78c28 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 21:07:34 -0400 Subject: [PATCH 09/24] Make client single queued Shouldn't need to protoct ack generation now that client is single queued --- Source/SocketAckEmitter.swift | 36 ++++----- Source/SocketIOClient.swift | 135 +++++++++++++++----------------- Source/SocketIOClientSpec.swift | 7 +- 3 files changed, 84 insertions(+), 94 deletions(-) diff --git a/Source/SocketAckEmitter.swift b/Source/SocketAckEmitter.swift index 4af43e7..9dead5c 100644 --- a/Source/SocketAckEmitter.swift +++ b/Source/SocketAckEmitter.swift @@ -22,6 +22,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch import Foundation public final class SocketAckEmitter : NSObject { @@ -31,57 +32,52 @@ public final class SocketAckEmitter : NSObject { public var expected: Bool { return ackNum != -1 } - + init(socket: SocketIOClient, ackNum: Int) { self.socket = socket self.ackNum = ackNum } - + public func with(_ items: SocketData...) { guard ackNum != -1 else { return } - + socket.emitAck(ackNum, with: items) } - + public func with(_ items: [Any]) { guard ackNum != -1 else { return } - + socket.emitAck(ackNum, with: items) } - + } public final class OnAckCallback : NSObject { private let ackNumber: Int private let items: [Any] private weak var socket: SocketIOClient? - + init(ackNumber: Int, items: [Any], socket: SocketIOClient) { self.ackNumber = ackNumber self.items = items self.socket = socket } - + deinit { DefaultSocketLogger.Logger.log("OnAckCallback for \(ackNumber) being released", type: "OnAckCallback") } - + public func timingOut(after seconds: Int, callback: @escaping AckCallback) { guard let socket = self.socket else { return } - - socket.ackQueue.sync() { - socket.ackHandlers.addAck(ackNumber, callback: callback) - } - + + socket.ackHandlers.addAck(ackNumber, callback: callback) socket._emit(items, ack: ackNumber) - + guard seconds != 0 else { return } - - let time = DispatchTime.now() + Double(UInt64(seconds) * NSEC_PER_SEC) / Double(NSEC_PER_SEC) - - socket.handleQueue.asyncAfter(deadline: time) { + + socket.handleQueue.asyncAfter(deadline: DispatchTime.now() + Double(seconds)) { socket.ackHandlers.timeoutAck(self.ackNumber, onQueue: socket.handleQueue) } } - + } diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 31f0c37..f23b42b 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -22,6 +22,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch import Foundation public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { @@ -41,43 +42,38 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } public var forceNew = false + public var handleQueue = DispatchQueue.main public var nsp = "/" public var config: SocketIOClientConfiguration public var reconnects = true public var reconnectWait = 10 private let logType = "SocketIOClient" - private let parseQueue = DispatchQueue(label: "com.socketio.parseQueue") private var anyHandler: ((SocketAnyEvent) -> Void)? private var currentReconnectAttempt = 0 private var handlers = [SocketEventHandler]() private var reconnecting = false - private let ackSemaphore = DispatchSemaphore(value: 1) private(set) var currentAck = -1 - private(set) var handleQueue = DispatchQueue.main private(set) var reconnectAttempts = -1 - - let ackQueue = DispatchQueue(label: "com.socketio.ackQueue") - let emitQueue = DispatchQueue(label: "com.socketio.emitQueue") var ackHandlers = SocketAckManager() var waitingPackets = [SocketPacket]() - + public var sid: String? { return engine?.sid } - + /// Type safe way to create a new SocketIOClient. opts can be omitted public init(socketURL: URL, config: SocketIOClientConfiguration = []) { self.config = config self.socketURL = socketURL - + if socketURL.absoluteString.hasPrefix("https://") { self.config.insert(.secure(true)) } - + for option in config { switch option { case let .reconnects(reconnects): @@ -102,10 +98,10 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } self.config.insert(.path("/socket.io/"), replacing: false) - + super.init() } - + /// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity. /// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set)` public convenience init(socketURL: NSURL, config: NSDictionary?) { @@ -148,30 +144,25 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } else { engine?.connect() } - + guard timeoutAfter != 0 else { return } let time = DispatchTime.now() + Double(UInt64(timeoutAfter) * NSEC_PER_SEC) / Double(NSEC_PER_SEC) handleQueue.asyncAfter(deadline: time) {[weak self] in guard let this = self, this.status != .connected && this.status != .disconnected else { return } - + this.status = .disconnected this.engine?.disconnect(reason: "Connect timeout") - + handler?() } } - private func nextAck() -> Int { - ackSemaphore.wait() - defer { ackSemaphore.signal() } - currentAck += 1 - return currentAck - } - private func createOnAck(_ items: [Any]) -> OnAckCallback { - return OnAckCallback(ackNumber: nextAck(), items: items, socket: self) + currentAck += 1 + + return OnAckCallback(ackNumber: currentAck, items: items, socket: self) } func didConnect() { @@ -214,7 +205,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl handleEvent("error", data: ["Tried emitting \(event) when not connected"], isInternalMessage: true) return } - + _emit([event] + items) } @@ -230,40 +221,40 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } func _emit(_ data: [Any], ack: Int? = nil) { - emitQueue.async { - guard self.status == .connected else { - self.handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true) - return - } - - let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: self.nsp, ack: false) - let str = packet.packetString - - DefaultSocketLogger.Logger.log("Emitting: %@", type: self.logType, args: str) - - self.engine?.send(str, withData: packet.binary) + guard status == .connected else { + handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true) + return } + + let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false) + let str = packet.packetString + + DefaultSocketLogger.Logger.log("Emitting: %@", type: logType, args: str) + + engine?.send(str, withData: packet.binary) } // If the server wants to know that the client received data func emitAck(_ ack: Int, with items: [Any]) { - emitQueue.async { - guard self.status == .connected else { return } - - let packet = SocketPacket.packetFromEmit(items, id: ack, nsp: self.nsp, ack: true) - let str = packet.packetString - - DefaultSocketLogger.Logger.log("Emitting Ack: %@", type: self.logType, args: str) - - self.engine?.send(str, withData: packet.binary) - } + 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: %@", type: logType, args: str) + + engine?.send(str, withData: packet.binary) } public func engineDidClose(reason: String) { - parseQueue.async { - self.waitingPackets.removeAll() + handleQueue.async { + self._engineDidClose(reason: reason) } - + } + + private func _engineDidClose(reason: String) { + waitingPackets.removeAll() + if status != .disconnected { status = .notConnected } @@ -276,13 +267,19 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } } - /// error public func engineDidError(reason: String) { + handleQueue.async { + self._engineDidError(reason: reason) + } + } + + /// error + private func _engineDidError(reason: String) { DefaultSocketLogger.Logger.error("%@", type: logType, args: reason) handleEvent("error", data: [reason], isInternalMessage: true) } - + public func engineDidOpen(reason: String) { DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient") } @@ -293,9 +290,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl DefaultSocketLogger.Logger.log("Handling ack: %@ with data: %@", type: logType, args: ack, data) - handleQueue.async() { - self.ackHandlers.executeAck(ack, with: data, onQueue: self.handleQueue) - } + ackHandlers.executeAck(ack, with: data, onQueue: handleQueue) } /// Causes an event to be handled. Only use if you know what you're doing. @@ -304,12 +299,10 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data) - handleQueue.async { - self.anyHandler?(SocketAnyEvent(event: event, items: data)) + anyHandler?(SocketAnyEvent(event: event, items: data)) - for handler in self.handlers where handler.event == event { - handler.executeCallback(with: data, withAck: ack, withSocket: self) - } + for handler in handlers where handler.event == event { + handler.executeCallback(with: data, withAck: ack, withSocket: self) } } @@ -384,17 +377,17 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl public func parseEngineMessage(_ msg: String) { DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg) - parseQueue.async { self.parseSocketMessage(msg) } + handleQueue.async { self.parseSocketMessage(msg) } } public func parseEngineBinaryData(_ data: Data) { - parseQueue.async { self.parseBinaryData(data) } + handleQueue.async { self.parseBinaryData(data) } } /// Tries to reconnect to the server. public func reconnect() { guard !reconnecting else { return } - + engine?.disconnect(reason: "manual reconnect") } @@ -409,7 +402,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl DefaultSocketLogger.Logger.log("Starting reconnect", type: logType) handleEvent("reconnect", data: [reason], isInternalMessage: true) - + _tryReconnect() } @@ -425,26 +418,24 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl currentReconnectAttempt += 1 connect() - - let deadline = DispatchTime.now() + Double(Int64(UInt64(reconnectWait) * NSEC_PER_SEC)) / Double(NSEC_PER_SEC) - - DispatchQueue.main.asyncAfter(deadline: deadline, execute: _tryReconnect) + + handleQueue.asyncAfter(deadline: DispatchTime.now() + Double(reconnectWait), execute: _tryReconnect) } - + // Test properties - + var testHandlers: [SocketEventHandler] { return handlers } - + func setTestable() { status = .connected } - + func setTestEngine(_ engine: SocketEngineSpec?) { self.engine = engine } - + func emitTest(event: String, _ data: Any...) { _emit([event] + data) } diff --git a/Source/SocketIOClientSpec.swift b/Source/SocketIOClientSpec.swift index e91c840..539c4ec 100644 --- a/Source/SocketIOClientSpec.swift +++ b/Source/SocketIOClientSpec.swift @@ -22,10 +22,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch + protocol SocketIOClientSpec : class { + var handleQueue: DispatchQueue { get set } var nsp: String { get set } var waitingPackets: [SocketPacket] { get set } - + func didConnect() func didDisconnect(reason: String) func didError(reason: String) @@ -37,7 +40,7 @@ protocol SocketIOClientSpec : class { extension SocketIOClientSpec { func didError(reason: String) { DefaultSocketLogger.Logger.error("%@", type: "SocketIOClient", args: reason) - + handleEvent("error", data: [reason], isInternalMessage: true, withAck: -1) } } From abdffb9a4f1831dee17bd382fe6de269d8c201eb Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 21:19:52 -0400 Subject: [PATCH 10/24] Open client --- Source/SocketIOClient.swift | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index f23b42b..6494656 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -25,7 +25,7 @@ import Dispatch import Foundation -public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { +open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { public let socketURL: URL public private(set) var engine: SocketEngineSpec? @@ -123,13 +123,13 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Connect to the server. - public func connect() { + open func connect() { connect(timeoutAfter: 0, withHandler: nil) } /// Connect to the server. If we aren't connected after timeoutAfter, call withHandler /// 0 Never times out - public func connect(timeoutAfter: Int, withHandler handler: (() -> Void)?) { + open func connect(timeoutAfter: Int, withHandler handler: (() -> Void)?) { assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)") guard status != .connected else { @@ -188,19 +188,19 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Disconnects the socket. - public func disconnect() { + open func disconnect() { DefaultSocketLogger.Logger.log("Closing socket", type: logType) didDisconnect(reason: "Disconnect") } /// Send a message to the server - public func emit(_ event: String, _ items: SocketData...) { + open func emit(_ event: String, _ items: SocketData...) { emit(event, with: items) } /// Same as emit, but meant for Objective-C - public func emit(_ event: String, with items: [Any]) { + open func emit(_ event: String, with items: [Any]) { guard status == .connected else { handleEvent("error", data: ["Tried emitting \(event) when not connected"], isInternalMessage: true) return @@ -211,12 +211,12 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add /// an ack. - public func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback { + open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback { return emitWithAck(event, with: items) } /// Same as emitWithAck, but for Objective-C - public func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback { + open func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback { return createOnAck([event] + items) } @@ -246,7 +246,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl engine?.send(str, withData: packet.binary) } - public func engineDidClose(reason: String) { + open func engineDidClose(reason: String) { handleQueue.async { self._engineDidClose(reason: reason) } @@ -267,7 +267,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } } - public func engineDidError(reason: String) { + open func engineDidError(reason: String) { handleQueue.async { self._engineDidError(reason: reason) } @@ -280,7 +280,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl handleEvent("error", data: [reason], isInternalMessage: true) } - public func engineDidOpen(reason: String) { + open func engineDidOpen(reason: String) { DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient") } @@ -294,7 +294,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Causes an event to be handled. Only use if you know what you're doing. - public func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) { + open func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) { guard status == .connected || isInternalMessage else { return } DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data) @@ -307,7 +307,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Leaves nsp and goes back to / - public func leaveNamespace() { + open func leaveNamespace() { if nsp != "/" { engine?.send("1\(nsp)", withData: []) nsp = "/" @@ -315,7 +315,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Joins namespace - public func joinNamespace(_ namespace: String) { + open func joinNamespace(_ namespace: String) { nsp = namespace if nsp != "/" { @@ -325,14 +325,14 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Removes handler(s) based on name - public func off(_ event: String) { + open func off(_ event: String) { DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event) handlers = handlers.filter({ $0.event != event }) } /// Removes a handler with the specified UUID gotten from an `on` or `once` - public func off(id: UUID) { + open func off(id: UUID) { DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id) handlers = handlers.filter({ $0.id != id }) @@ -341,7 +341,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// Adds a handler for an event. /// Returns: A unique id for the handler @discardableResult - public func on(_ event: String, callback: @escaping NormalCallback) -> UUID { + open func on(_ event: String, callback: @escaping NormalCallback) -> UUID { DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event) let handler = SocketEventHandler(event: event, id: UUID(), callback: callback) @@ -353,7 +353,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// Adds a single-use handler for an event. /// Returns: A unique id for the handler @discardableResult - public func once(_ event: String, callback: @escaping NormalCallback) -> UUID { + open func once(_ event: String, callback: @escaping NormalCallback) -> UUID { DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event) let id = UUID() @@ -370,7 +370,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Adds a handler that will be called on every event. - public func onAny(_ handler: @escaping (SocketAnyEvent) -> Void) { + open func onAny(_ handler: @escaping (SocketAnyEvent) -> Void) { anyHandler = handler } @@ -385,7 +385,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Tries to reconnect to the server. - public func reconnect() { + open func reconnect() { guard !reconnecting else { return } engine?.disconnect(reason: "manual reconnect") @@ -393,7 +393,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// Removes all handlers. /// Can be used after disconnecting to break any potential remaining retain cycles. - public func removeAllHandlers() { + open func removeAllHandlers() { handlers.removeAll(keepingCapacity: false) } From 9edd322a70a09de6bfc0085fa3ff4766c99f710b Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 22:09:59 -0400 Subject: [PATCH 11/24] remove refactor build --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cd54215..1c99082 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ branches: only: - master - development - - refactor-engine before_install: - brew update - brew outdated xctool || brew upgrade xctool From 23c76417d206b865e13b3e76297b9cf308d521f2 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 22:35:39 -0400 Subject: [PATCH 12/24] Fix #667 Make no ack an enum case --- SocketIO-MacTests/SocketAckManagerTest.swift | 31 ++++++++++++++++++-- Source/SocketAckManager.swift | 21 ++++++++----- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/SocketIO-MacTests/SocketAckManagerTest.swift b/SocketIO-MacTests/SocketAckManagerTest.swift index 764ad34..455c5b9 100644 --- a/SocketIO-MacTests/SocketAckManagerTest.swift +++ b/SocketIO-MacTests/SocketAckManagerTest.swift @@ -9,18 +9,43 @@ import XCTest @testable import SocketIO -class SocketAckManagerTest: XCTestCase { +class SocketAckManagerTest : XCTestCase { var ackManager = SocketAckManager() func testAddAcks() { - let callbackExpection = self.expectation(description: "callbackExpection") + let callbackExpection = expectation(description: "callbackExpection") let itemsArray = ["Hi", "ho"] + func callback(_ items: [Any]) { callbackExpection.fulfill() } + ackManager.addAck(1, callback: callback) ackManager.executeAck(1, with: itemsArray, onQueue: DispatchQueue.main) - + waitForExpectations(timeout: 3.0, handler: nil) } + + func testManagerTimeoutAck() { + let callbackExpection = expectation(description: "Manager should timeout ack with noAck status") + let itemsArray = ["Hi", "ho"] + + func callback(_ items: [Any]) { + XCTAssertEqual(items.count, 1, "Timed out ack should have one value") + guard let timeoutReason = items[0] as? String else { + XCTFail("Timeout reason should be a string") + + return + } + + XCTAssertEqual(timeoutReason, SocketAckStatus.noAck.rawValue) + + callbackExpection.fulfill() + } + + ackManager.addAck(1, callback: callback) + ackManager.timeoutAck(1, onQueue: DispatchQueue.main) + + waitForExpectations(timeout: 0.2, handler: nil) + } } diff --git a/Source/SocketAckManager.swift b/Source/SocketAckManager.swift index eea183b..b5d4cdc 100644 --- a/Source/SocketAckManager.swift +++ b/Source/SocketAckManager.swift @@ -22,19 +22,24 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch import Foundation +public enum SocketAckStatus : String { + case noAck = "NO ACK" +} + private struct SocketAck : Hashable { let ack: Int var callback: AckCallback! var hashValue: Int { return ack.hashValue } - + init(ack: Int) { self.ack = ack } - + init(ack: Int, callback: @escaping AckCallback) { self.ack = ack self.callback = callback @@ -52,28 +57,28 @@ private func ==(lhs: SocketAck, rhs: SocketAck) -> Bool { struct SocketAckManager { private var acks = Set(minimumCapacity: 1) private let ackSemaphore = DispatchSemaphore(value: 1) - + mutating func addAck(_ ack: Int, callback: @escaping AckCallback) { acks.insert(SocketAck(ack: ack, callback: callback)) } - + /// Should be called on handle queue mutating func executeAck(_ ack: Int, with items: [Any], onQueue: DispatchQueue) { ackSemaphore.wait() defer { ackSemaphore.signal() } let ack = acks.remove(SocketAck(ack: ack)) - + onQueue.async() { ack?.callback(items) } } - + /// Should be called on handle queue mutating func timeoutAck(_ ack: Int, onQueue: DispatchQueue) { ackSemaphore.wait() defer { ackSemaphore.signal() } let ack = acks.remove(SocketAck(ack: ack)) - + onQueue.async() { - ack?.callback?(["NO ACK"]) + ack?.callback?([SocketAckStatus.noAck.rawValue]) } } } From e78200ee34e16d0388b5a5a6b4094d7ab70f0e1e Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 23:05:55 -0400 Subject: [PATCH 13/24] Document ack types --- Source/SocketAckEmitter.swift | 27 +++++++++++++++++++++++++++ Source/SocketAckManager.swift | 2 ++ 2 files changed, 29 insertions(+) diff --git a/Source/SocketAckEmitter.swift b/Source/SocketAckEmitter.swift index 9dead5c..7a38272 100644 --- a/Source/SocketAckEmitter.swift +++ b/Source/SocketAckEmitter.swift @@ -25,10 +25,14 @@ import Dispatch import Foundation +/// A class that represents a waiting ack call. +/// +/// **NOTE**: You should not store this beyond the life of the event handler. public final class SocketAckEmitter : NSObject { let socket: SocketIOClient let ackNum: Int + /// If true, this handler is expecting to be acked. Call `with(_: SocketData...)` to ack. public var expected: Bool { return ackNum != -1 } @@ -38,12 +42,20 @@ public final class SocketAckEmitter : NSObject { self.ackNum = ackNum } + // MARK: Methods + + /// Call to ack receiving this event. + /// + /// - parameter items: A variable number of items to send when acking. public func with(_ items: SocketData...) { guard ackNum != -1 else { return } socket.emitAck(ackNum, with: items) } + /// Call to ack receiving this event. + /// + /// - parameter items: An array of items to send when acking. Use `[]` to send nothing. public func with(_ items: [Any]) { guard ackNum != -1 else { return } @@ -52,6 +64,14 @@ public final class SocketAckEmitter : NSObject { } +/// A class that represents an emit that will request an ack that has not yet been sent. +/// Call `timingOut(after:callback:)` to complete the emit +/// Example: +/// ```swift +/// socket.emitWithAck("myEvent").timingOut(after: 1) {data in +/// ... +/// } +/// ``` public final class OnAckCallback : NSObject { private let ackNumber: Int private let items: [Any] @@ -67,6 +87,13 @@ public final class OnAckCallback : NSObject { DefaultSocketLogger.Logger.log("OnAckCallback for \(ackNumber) being released", type: "OnAckCallback") } + // MARK: Methods + + /// Completes an emitWithAck. If this isn't called, the emit never happens. + /// + /// - parameter after: The number of seconds before this emit times out if an ack hasn't been received. + /// - parameter callback: The callback called when an ack is received, or when a timeout happens. + /// To check for timeout, use `SocketAckStatus`'s `noAck` case. public func timingOut(after seconds: Int, callback: @escaping AckCallback) { guard let socket = self.socket else { return } diff --git a/Source/SocketAckManager.swift b/Source/SocketAckManager.swift index b5d4cdc..44b563f 100644 --- a/Source/SocketAckManager.swift +++ b/Source/SocketAckManager.swift @@ -25,7 +25,9 @@ import Dispatch import Foundation +/// The status of an ack. public enum SocketAckStatus : String { + /// The ack timed out. case noAck = "NO ACK" } From 08c6186fe4a39ebc5776860cddfb2c647d45b2f8 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 23:10:32 -0400 Subject: [PATCH 14/24] Move operators inside type --- Source/SocketAckManager.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/SocketAckManager.swift b/Source/SocketAckManager.swift index 44b563f..67b50aa 100644 --- a/Source/SocketAckManager.swift +++ b/Source/SocketAckManager.swift @@ -46,14 +46,14 @@ private struct SocketAck : Hashable { self.ack = ack self.callback = callback } -} -private func <(lhs: SocketAck, rhs: SocketAck) -> Bool { - return lhs.ack < rhs.ack -} + fileprivate static func <(lhs: SocketAck, rhs: SocketAck) -> Bool { + return lhs.ack < rhs.ack + } -private func ==(lhs: SocketAck, rhs: SocketAck) -> Bool { - return lhs.ack == rhs.ack + fileprivate static func ==(lhs: SocketAck, rhs: SocketAck) -> Bool { + return lhs.ack == rhs.ack + } } struct SocketAckManager { From a8ee018a1601ba06e8c36f452c374fee081b91cd Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 23:14:48 -0400 Subject: [PATCH 15/24] Document SocketAnyEvent --- Source/SocketAnyEvent.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/SocketAnyEvent.swift b/Source/SocketAnyEvent.swift index 3647e96..f27bb1c 100644 --- a/Source/SocketAnyEvent.swift +++ b/Source/SocketAnyEvent.swift @@ -24,13 +24,21 @@ import Foundation +/// Represents some event that was received. public final class SocketAnyEvent : NSObject { + // MARK: Properties + + /// The event name. public let event: String + + /// The data items for this event. public let items: [Any]? + + /// The description of this event. override public var description: String { return "SocketAnyEvent: Event: \(event) items: \(String(describing: items))" } - + init(event: String, items: [Any]?) { self.event = event self.items = items From 1ff8e11a1f093c3692584bd1e0735e8edadc6949 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 23:31:30 -0400 Subject: [PATCH 16/24] Document SocketIOClientSwift add docs Start documenting engine More engine documentation Document engine document SocketEngineClient Document SocketEnginePollable and SocketEnginePacketType Document SocketEngineWebsocket Document SocketIOClient Document SocketIOClientStatus Document SocketLogger Document some typealiases Document SocketIOClientOption Document SocketIOClientConfiguration --- .gitignore | 2 + Source/SocketAckEmitter.swift | 3 + Source/SocketClientManager.swift | 45 +- Source/SocketEngine.swift | 112 +- Source/SocketEngineClient.swift | 24 +- Source/SocketEnginePacketType.swift | 24 +- Source/SocketEnginePollable.swift | 51 +- Source/SocketEngineSpec.swift | 101 +- Source/SocketEngineWebsocket.swift | 30 +- Source/SocketIOClient.swift | 143 +- Source/SocketIOClientConfiguration.swift | 81 +- Source/SocketIOClientOption.swift | 75 +- Source/SocketIOClientStatus.swift | 16 +- Source/SocketLogger.swift | 29 +- Source/SocketTypes.swift | 4 + docs/Classes.html | 470 +++++ docs/Classes/OnAckCallback.html | 271 +++ docs/Classes/SSLCert.html | 293 +++ docs/Classes/SSLSecurity.html | 386 ++++ docs/Classes/SocketAckEmitter.html | 338 ++++ docs/Classes/SocketAnyEvent.html | 287 +++ docs/Classes/SocketClientManager.html | 475 +++++ docs/Classes/SocketEngine.html | 1466 ++++++++++++++ docs/Classes/SocketIOClient.html | 1699 +++++++++++++++++ docs/Classes/WebSocket.html | 911 +++++++++ docs/Classes/WebSocket/CloseCode.html | 373 ++++ docs/Enums.html | 316 +++ docs/Enums/SocketAckStatus.html | 226 +++ docs/Enums/SocketEnginePacketType.html | 412 ++++ docs/Enums/SocketIOClientOption.html | 932 +++++++++ docs/Enums/SocketIOClientStatus.html | 319 ++++ docs/Global Variables.html | 249 +++ docs/Protocols.html | 447 +++++ docs/Protocols/SSLTrustValidator.html | 212 ++ docs/Protocols/SocketEngineClient.html | 436 +++++ docs/Protocols/SocketEnginePollable.html | 499 +++++ docs/Protocols/SocketEngineSpec.html | 1118 +++++++++++ docs/Protocols/SocketEngineWebsocket.html | 352 ++++ docs/Protocols/SocketLogger.html | 400 ++++ docs/Protocols/WebSocketDelegate.html | 269 +++ docs/Protocols/WebSocketPongDelegate.html | 212 ++ docs/Structs.html | 220 +++ docs/Structs/SocketIOClientConfiguration.html | 647 +++++++ docs/Typealiases.html | 246 +++ docs/badge.svg | 1 + docs/css/highlight.css | 200 ++ docs/css/jazzy.css | 368 ++++ docs/img/carat.png | Bin 0 -> 274 bytes docs/img/dash.png | Bin 0 -> 1338 bytes docs/img/gh.png | Bin 0 -> 1571 bytes docs/img/spinner.gif | Bin 0 -> 1849 bytes docs/index.html | 376 ++++ docs/js/jazzy.js | 43 + docs/js/jazzy.search.js | 62 + docs/js/jquery.min.js | 4 + docs/js/lunr.min.js | 6 + docs/js/typeahead.jquery.js | 1538 +++++++++++++++ docs/search.json | 1 + 58 files changed, 17706 insertions(+), 114 deletions(-) create mode 100644 docs/Classes.html create mode 100644 docs/Classes/OnAckCallback.html create mode 100644 docs/Classes/SSLCert.html create mode 100644 docs/Classes/SSLSecurity.html create mode 100644 docs/Classes/SocketAckEmitter.html create mode 100644 docs/Classes/SocketAnyEvent.html create mode 100644 docs/Classes/SocketClientManager.html create mode 100644 docs/Classes/SocketEngine.html create mode 100644 docs/Classes/SocketIOClient.html create mode 100644 docs/Classes/WebSocket.html create mode 100644 docs/Classes/WebSocket/CloseCode.html create mode 100644 docs/Enums.html create mode 100644 docs/Enums/SocketAckStatus.html create mode 100644 docs/Enums/SocketEnginePacketType.html create mode 100644 docs/Enums/SocketIOClientOption.html create mode 100644 docs/Enums/SocketIOClientStatus.html create mode 100644 docs/Global Variables.html create mode 100644 docs/Protocols.html create mode 100644 docs/Protocols/SSLTrustValidator.html create mode 100644 docs/Protocols/SocketEngineClient.html create mode 100644 docs/Protocols/SocketEnginePollable.html create mode 100644 docs/Protocols/SocketEngineSpec.html create mode 100644 docs/Protocols/SocketEngineWebsocket.html create mode 100644 docs/Protocols/SocketLogger.html create mode 100644 docs/Protocols/WebSocketDelegate.html create mode 100644 docs/Protocols/WebSocketPongDelegate.html create mode 100644 docs/Structs.html create mode 100644 docs/Structs/SocketIOClientConfiguration.html create mode 100644 docs/Typealiases.html create mode 100644 docs/badge.svg create mode 100644 docs/css/highlight.css create mode 100644 docs/css/jazzy.css create mode 100755 docs/img/carat.png create mode 100755 docs/img/dash.png create mode 100755 docs/img/gh.png create mode 100644 docs/img/spinner.gif create mode 100644 docs/index.html create mode 100755 docs/js/jazzy.js create mode 100644 docs/js/jazzy.search.js create mode 100755 docs/js/jquery.min.js create mode 100755 docs/js/lunr.min.js create mode 100644 docs/js/typeahead.jquery.js create mode 100644 docs/search.json diff --git a/.gitignore b/.gitignore index 069348b..aec6c75 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,5 @@ DerivedData Socket.IO-Test-Server/node_modules/* .idea/ +docs/docsets/ +docs/undocumented.json diff --git a/Source/SocketAckEmitter.swift b/Source/SocketAckEmitter.swift index 7a38272..6c5fe15 100644 --- a/Source/SocketAckEmitter.swift +++ b/Source/SocketAckEmitter.swift @@ -32,6 +32,8 @@ public final class SocketAckEmitter : NSObject { let socket: SocketIOClient let ackNum: Int + // MARK: Properties + /// If true, this handler is expecting to be acked. Call `with(_: SocketData...)` to ack. public var expected: Bool { return ackNum != -1 @@ -67,6 +69,7 @@ public final class SocketAckEmitter : NSObject { /// A class that represents an emit that will request an ack that has not yet been sent. /// Call `timingOut(after:callback:)` to complete the emit /// Example: +/// /// ```swift /// socket.emitWithAck("myEvent").timingOut(after: 1) {data in /// ... diff --git a/Source/SocketClientManager.swift b/Source/SocketClientManager.swift index e230272..3813cdc 100644 --- a/Source/SocketClientManager.swift +++ b/Source/SocketClientManager.swift @@ -26,14 +26,14 @@ import Foundation /** Experimental socket manager. - + API subject to change. - + Can be used to persist sockets across ViewControllers. - + Sockets are strongly stored, so be sure to remove them once they are no longer needed. - + Example usage: ``` let manager = SocketClientManager.sharedManager @@ -44,38 +44,59 @@ import Foundation ``` */ open class SocketClientManager : NSObject { + // MARK: Properties. + + /// The shared manager. open static let sharedManager = SocketClientManager() - + private var sockets = [String: SocketIOClient]() - + + /// Gets a socket by its name. + /// + /// - returns: The socket, if one had the given name. open subscript(string: String) -> SocketIOClient? { get { return sockets[string] } - + set(socket) { sockets[string] = socket } } - + + // MARK: Methods. + + /// Adds a socket. + /// + /// - parameter socket: The socket to add. + /// - parameter labeledAs: The label for this socket. open func addSocket(_ socket: SocketIOClient, labeledAs label: String) { sockets[label] = socket } - + + /// Removes a socket by a given name. + /// + /// - parameter withLabel: The label of the socket to remove. + /// - returns: The socket for the given label, if one was present. open func removeSocket(withLabel label: String) -> SocketIOClient? { return sockets.removeValue(forKey: label) } + /// Removes a socket. + /// + /// - parameter socket: The socket to remove. + /// - returns: The socket if it was in the manager. open func removeSocket(_ socket: SocketIOClient) -> SocketIOClient? { var returnSocket: SocketIOClient? - + for (label, dictSocket) in sockets where dictSocket === socket { returnSocket = sockets.removeValue(forKey: label) } - + return returnSocket } - + + /// Removes all the sockets in the manager. open func removeSockets() { sockets.removeAll() } diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index cd1e8d0..c3114d1 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -25,38 +25,96 @@ import Dispatch import Foundation +/// 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 { - public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: []) + // MARK: Properties + /// The queue that all engine actions take place on. + public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue") + + /// The connect parameters sent during a connect. public var connectParams: [String: Any]? { didSet { (urlPolling, urlWebSocket) = createURLs() } } + /// A queue of engine.io messages waiting for POSTing + /// + /// **You should not touch this directly** public var postWait = [String]() + + /// `true` if there is an outstanding poll. Trying to poll before the first is done will cause socket.io to + /// disconnect us. + /// + /// **Do not touch this directly** public var waitingForPoll = false + + /// `true` if there is an outstanding post. Trying to post before the first is done will cause socket.io to + /// disconnect us. + /// + /// **Do not touch this directly** public var waitingForPost = false + /// `true` if this engine is closed. public private(set) var closed = false + + /// `true` if this engine is connected. Connected means that the initial poll connect has succeeded. public private(set) var connected = false + + /// An array of HTTPCookies that are sent during the connection. public private(set) var cookies: [HTTPCookie]? + + /// Set to `true` if using the node.js version of socket.io. The node.js version of socket.io + /// handles utf8 incorrectly. public private(set) var doubleEncodeUTF8 = true + + /// A dictionary of extra http headers that will be set during connection. public private(set) var extraHeaders: [String: String]? + + /// When `true`, the engine is in the process of switching to WebSockets. + /// + /// **Do not touch this directly** public private(set) var fastUpgrade = false + + /// When `true`, the engine will only use HTTP long-polling as a transport. public private(set) var forcePolling = false + + /// When `true`, the engine will only use WebSockets as a transport. public private(set) var forceWebsockets = false + + /// `true` If engine's session has been invalidated. public private(set) var invalidated = false + + /// If `true`, the engine is currently in HTTP long-polling mode. public private(set) var polling = true + + /// If `true`, the engine is currently seeing whether it can upgrade to WebSockets. public private(set) var probing = false + + /// The URLSession that will be used for polling. public private(set) var session: URLSession? + + /// The session id for this engine. public private(set) var sid = "" + + /// The path to engine.io. public private(set) var socketPath = "/engine.io/" + + /// The url for polling. public private(set) var urlPolling = URL(string: "http://localhost/")! + + /// The url for WebSockets. public private(set) var urlWebSocket = URL(string: "http://localhost/")! + + /// If `true`, then the engine is currently in WebSockets mode. public private(set) var websocket = false + + /// The WebSocket for this engine. public private(set) var ws: WebSocket? + /// The client for this engine. public weak var client: SocketEngineClient? private weak var sessionDelegate: URLSessionDelegate? @@ -79,6 +137,13 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll private var selfSigned = false private var voipEnabled = false + // MARK: Initializers + + /// Creates a new engine. + /// + /// - parameter client: The client for this engine. + /// - parameter url: The url for this engine. + /// - parameter config: An array of configuration options for this engine. public init(client: SocketEngineClient, url: URL, config: SocketIOClientConfiguration) { self.client = client self.url = url @@ -124,6 +189,11 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll (urlPolling, urlWebSocket) = createURLs() } + /// Creates a new engine. + /// + /// - 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: NSDictionary?) { self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? []) } @@ -134,6 +204,8 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll stopPolling() } + // MARK: Methods + private func checkAndHandleEngineError(_ msg: String) { do { let dict = try msg.toNSDictionary() @@ -171,7 +243,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll client?.engineDidClose(reason: reason) } - /// Starts the connection to the server + /// Starts the connection to the server. public func connect() { engineQueue.async { self._connect() @@ -273,12 +345,16 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll ws?.connect() } + /// Called when an error happens during execution. Causes a disconnection. public func didError(reason: String) { DefaultSocketLogger.Logger.error("%@", type: logType, args: reason) client?.engineDidError(reason: reason) disconnect(reason: reason) } + /// Disconnects from the server. + /// + /// - parameter reason: The reason for the disconnection. This is communicated up to the client. public func disconnect(reason: String) { engineQueue.async { self._disconnect(reason: reason) @@ -311,6 +387,10 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll closeOutEngine(reason: reason) } + /// Called to switch from HTTP long-polling to WebSockets. After calling this method the engine will be in + /// WebSocket mode. + /// + /// **You shouldn't call this directly** public func doFastUpgrade() { if waitingForPoll { DefaultSocketLogger.Logger.error("Outstanding poll when switched to WebSockets," + @@ -339,8 +419,10 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } } - // We had packets waiting for send when we upgraded - // Send them raw + /// Causes any packets that were waiting for POSTing to be sent through the WebSocket. This happens because when + /// the engine is attempting to upgrade to WebSocket it does not do any POSTing. + /// + /// **You shouldn't call this directly** public func flushWaitingForPostToWebSocket() { guard let ws = self.ws else { return } @@ -415,12 +497,20 @@ 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) { DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data) client?.parseEngineBinaryData(data.subdata(in: 1.. Either { if websocket { var byteArray = [UInt8](repeating: 0x4, count: 1) let mutData = NSMutableData(bytes: &byteArray, length: 1) - + mutData.append(data) - + return .left(mutData as Data) } else { let str = "b4" + data.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)) - + return .right(str) } } - + func doubleEncodeUTF8(_ string: String) -> String { if let latin1 = string.data(using: String.Encoding.utf8), let utf8 = NSString(data: latin1, encoding: String.Encoding.isoLatin1.rawValue) { @@ -96,7 +173,7 @@ extension SocketEngineSpec { return string } } - + func fixDoubleUTF8(_ string: String) -> String { if let utf8 = string.data(using: String.Encoding.isoLatin1), let latin1 = NSString(data: utf8, encoding: String.Encoding.utf8.rawValue) { @@ -105,7 +182,7 @@ extension SocketEngineSpec { return string } } - + /// Send an engine message (4) func send(_ msg: String, withData datas: [Data]) { write(msg, withType: .message, withData: datas) diff --git a/Source/SocketEngineWebsocket.swift b/Source/SocketEngineWebsocket.swift index 3c37b2b..64265c4 100644 --- a/Source/SocketEngineWebsocket.swift +++ b/Source/SocketEngineWebsocket.swift @@ -27,6 +27,13 @@ import Foundation /// Protocol that is used to implement socket.io WebSocket support public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate { + /// Sends an engine.io message through the WebSocket transport. + /// + /// You shouldn't call this directly, instead call the `write` method on `SocketEngine`. + /// + /// - 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]) } @@ -37,25 +44,34 @@ extension SocketEngineWebsocket { sendWebSocketMessage("probe", withType: .ping, withData: []) } } - - /// Send message on WebSockets - /// Only call on emitQueue + + /// Sends an engine.io message through the WebSocket transport. + /// + /// You shouldn't call this directly, instead call the `write` method on `SocketEngine`. + /// + /// - 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]) { DefaultSocketLogger.Logger.log("Sending ws: %@ as type: %@", type: "SocketEngine", args: str, type.rawValue) - + ws?.write(string: "\(type.rawValue)\(str)") - + for data in datas { if case let .left(bin) = createBinaryDataForSend(using: data) { ws?.write(data: bin) } } } - + + // MARK: Starscream delegate methods + + /// Delegate method for when a message is received. public func websocketDidReceiveMessage(socket: WebSocket, text: String) { parseEngineMessage(text, fromPolling: false) } - + + /// Delegate method for when binary is received. public func websocketDidReceiveData(socket: WebSocket, data: Data) { parseEngineData(data) } diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 6494656..7892909 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -25,10 +25,19 @@ import Dispatch import Foundation +/// The main class for SocketIOClientSwift. +/// +/// Represents a socket.io-client. Most interaction with socket.io will be through this class. open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { + // MARK: Properties + + /// The URL of the socket.io server. This is set in the initializer. public let socketURL: URL + /// The engine for this client. public private(set) var engine: SocketEngineSpec? + + /// The status of this client. public private(set) var status = SocketIOClientStatus.notConnected { didSet { switch status { @@ -41,13 +50,30 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } } + /// If `true` then every time `connect` is called, a new engine will be created. public var forceNew = false + + /// The queue that all interaction with the client should occur on. This is the queue that event handlers are + /// called on. public var handleQueue = DispatchQueue.main + + /// The namespace for this client. public var nsp = "/" + + /// The configuration for this client. public var config: SocketIOClientConfiguration + + /// If `true`, this client will try and reconnect on any disconnects. public var reconnects = true + + /// The number of seconds to wait before attempting to reconnect. public var reconnectWait = 10 + /// The session id of this client. + public var sid: String? { + return engine?.sid + } + private let logType = "SocketIOClient" private var anyHandler: ((SocketAnyEvent) -> Void)? @@ -61,11 +87,12 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So var ackHandlers = SocketAckManager() var waitingPackets = [SocketPacket]() - public var sid: String? { - return engine?.sid - } + // MARK: Initializers - /// Type safe way to create a new SocketIOClient. opts can be omitted + /// Type safe way to create a new SocketIOClient. `opts` can be omitted. + /// + /// - parameter socketURL: The url of the socket.io server. + /// - parameter config: The config for this socket. public init(socketURL: URL, config: SocketIOClientConfiguration = []) { self.config = config self.socketURL = socketURL @@ -104,6 +131,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So /// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity. /// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set)` + /// + /// - parameter socketURL: The url of the socket.io server. + /// - parameter config: The config for this socket. public convenience init(socketURL: NSURL, config: NSDictionary?) { self.init(socketURL: socketURL as URL, config: config?.toSocketConfiguration() ?? []) } @@ -113,6 +143,8 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So engine?.disconnect(reason: "Client Deinit") } + // MARK: Methods + private func addEngine() -> SocketEngineSpec { DefaultSocketLogger.Logger.log("Adding engine", type: logType, args: "") @@ -127,8 +159,11 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So connect(timeoutAfter: 0, withHandler: nil) } - /// Connect to the server. If we aren't connected after timeoutAfter, call withHandler - /// 0 Never times out + /// Connect to the server. If we aren't connected after `timeoutAfter` seconds, then `withHandler` is called. + /// + /// - parameter timeoutAfter: The number of seconds after which if we are not connected we assume the connection + /// has failed. Pass 0 to never timeout. + /// - parameter withHandler: The handler to call when the client fails to connect. open func connect(timeoutAfter: Int, withHandler handler: (() -> Void)?) { assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)") @@ -194,12 +229,18 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So didDisconnect(reason: "Disconnect") } - /// Send a message to the server + /// Send an event to the server, with optional data items. + /// + /// - 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...) { emit(event, with: items) } /// Same as emit, but meant for Objective-C + /// + /// - parameter event: The event to send. + /// - parameter with: The items to send with this event. May be left out. open func emit(_ event: String, with items: [Any]) { guard status == .connected else { handleEvent("error", data: ["Tried emitting \(event) when not connected"], isInternalMessage: true) @@ -209,13 +250,42 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So _emit([event] + items) } - /// Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add - /// an ack. + /// 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. + /// + /// 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. open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback { return emitWithAck(event, with: items) } /// 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 with: 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. open func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback { return createOnAck([event] + items) } @@ -246,6 +316,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So engine?.send(str, withData: packet.binary) } + /// Called when the engine closes. + /// + /// - parameter reason: The reason that the engine closed. open func engineDidClose(reason: String) { handleQueue.async { self._engineDidClose(reason: reason) @@ -267,19 +340,24 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } } + /// Called when the engine errors. + /// + /// - parameter reason: The reason the engine errored. open func engineDidError(reason: String) { handleQueue.async { self._engineDidError(reason: reason) } } - /// error private func _engineDidError(reason: String) { DefaultSocketLogger.Logger.error("%@", type: logType, args: reason) handleEvent("error", data: [reason], isInternalMessage: true) } + /// Called when the engine opens. + /// + /// - parameter reason: The reason the engine opened. open func engineDidOpen(reason: String) { DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient") } @@ -293,7 +371,12 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So ackHandlers.executeAck(ack, with: data, onQueue: handleQueue) } - /// Causes an event to be handled. Only use if you know what you're doing. + /// Causes an event to be handled, and any event handlers for that event to be called. + /// + /// - parameter event: The event that is to be handled. + /// - parameter data: the data associated with this event. + /// - parameter isInternalMessage: If `true` event handlers for this event will be called regardless of status. + /// - parameter withAck: The ack number for this event. May be left out. open func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) { guard status == .connected || isInternalMessage else { return } @@ -306,7 +389,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } } - /// Leaves nsp and goes back to / + /// Leaves nsp and goes back to the default namespace. open func leaveNamespace() { if nsp != "/" { engine?.send("1\(nsp)", withData: []) @@ -314,7 +397,11 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } } - /// Joins namespace + /// Joins `namespace`. + /// + /// **Do not use this to join the default namespace.** Instead call `leaveNamespace`. + /// + /// - parameter namespace: The namespace to join. open func joinNamespace(_ namespace: String) { nsp = namespace @@ -324,7 +411,11 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } } - /// Removes handler(s) based on name + /// Removes handler(s) based on an event name. + /// + /// If you wish to remove a specific event, call the `off(if:)` with the UUID received from its `on` call. + /// + /// - parameter event: The event to remove handlers for. open func off(_ event: String) { DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event) @@ -332,6 +423,10 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } /// Removes a handler with the specified UUID gotten from an `on` or `once` + /// + /// If you want to remove all events for an event, call the off `off(_:)` method with the event name. + /// + /// - parameter id: The UUID of the handler you wish to remove. open func off(id: UUID) { DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id) @@ -339,7 +434,10 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } /// Adds a handler for an event. - /// Returns: A unique id for the handler + /// + /// - parameter event: The event name for this handler. + /// - parameter callback: The callback that will execute when this event is received. + /// - returns: A unique id for the handler that can be used to remove it. @discardableResult open func on(_ event: String, callback: @escaping NormalCallback) -> UUID { DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event) @@ -351,7 +449,10 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } /// Adds a single-use handler for an event. - /// Returns: A unique id for the handler + /// + /// - parameter event: The event name for this handler. + /// - parameter callback: The callback that will execute when this event is received. + /// - returns: A unique id for the handler that can be used to remove it. @discardableResult open func once(_ event: String, callback: @escaping NormalCallback) -> UUID { DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event) @@ -370,21 +471,31 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } /// Adds a handler that will be called on every event. + /// + /// - parameter handler: The callback that will execute whenever an event is received. open func onAny(_ handler: @escaping (SocketAnyEvent) -> Void) { anyHandler = handler } + /// Called when the engine has a message that must be parsed. + /// + /// - parameter msg: The message that needs parsing. public func parseEngineMessage(_ msg: String) { DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg) handleQueue.async { self.parseSocketMessage(msg) } } + /// Called when the engine receives binary data. + /// + /// - parameter data: The data the engine received. public func parseEngineBinaryData(_ data: Data) { handleQueue.async { self.parseBinaryData(data) } } /// Tries to reconnect to the server. + /// + /// This will cause a `disconnect` event to be emitted, as well as an `reconnectAttempt` event. open func reconnect() { guard !reconnecting else { return } diff --git a/Source/SocketIOClientConfiguration.swift b/Source/SocketIOClientConfiguration.swift index 4fc45ba..290dd5b 100644 --- a/Source/SocketIOClientConfiguration.swift +++ b/Source/SocketIOClientConfiguration.swift @@ -22,39 +22,56 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +/// An array-like type that holds `SocketIOClientOption`s public struct SocketIOClientConfiguration : ExpressibleByArrayLiteral, Collection, MutableCollection { + // MARK: Typealiases + + /// Type of element stored. public typealias Element = SocketIOClientOption + + /// Index type. public typealias Index = Array.Index - public typealias Generator = Array.Iterator + + /// Iterator type. + public typealias Iterator = Array.Iterator + + /// SubSequence type. public typealias SubSequence = Array.SubSequence - + + // MARK: Properties + private var backingArray = [SocketIOClientOption]() - + + /// The start index of this collection. public var startIndex: Index { return backingArray.startIndex } - + + /// The end index of this collection. public var endIndex: Index { return backingArray.endIndex } - + + /// Whether this collection is empty. public var isEmpty: Bool { return backingArray.isEmpty } + /// The number of elements stored in this collection. public var count: Index.Stride { return backingArray.count } - - public var first: Generator.Element? { + + /// The first element in this collection. + public var first: Element? { return backingArray.first } - - public subscript(position: Index) -> Generator.Element { + + public subscript(position: Index) -> Element { get { return backingArray[position] } - + set { backingArray[position] = newValue } @@ -64,45 +81,49 @@ public struct SocketIOClientConfiguration : ExpressibleByArrayLiteral, Collectio get { return backingArray[bounds] } - + set { backingArray[bounds] = newValue } } - + + // MARK: Initializers + + /// Creates a new `SocketIOClientConfiguration` from an array literal. + /// + /// - parameter arrayLiteral: The elements. public init(arrayLiteral elements: Element...) { backingArray = elements } - - public func generate() -> Generator { + + // MARK: Methods + + /// Creates an iterator for this collection. + /// + /// - returns: An iterator over this collection. + public func makeIterator() -> Iterator { return backingArray.makeIterator() } - + + /// - returns: The index after index. public func index(after i: Index) -> Index { return backingArray.index(after: i) } - + + /// Special method that inserts `element` into the collection, replacing any other instances of `element`. + /// + /// - parameter element: The element to insert. + /// - parameter replacing: Whether to replace any occurrences of element to the new item. Default is `true`. public mutating func insert(_ element: Element, replacing replace: Bool = true) { for i in 0.. SubSequence { - return backingArray.prefix(upTo: end) - } - - public func prefix(through position: Index) -> SubSequence { - return backingArray.prefix(through: position) - } - public func suffix(from start: Index) -> SubSequence { - return backingArray.suffix(from: start) - } } diff --git a/Source/SocketIOClientOption.swift b/Source/SocketIOClientOption.swift index dd723f4..119a71c 100644 --- a/Source/SocketIOClientOption.swift +++ b/Source/SocketIOClientOption.swift @@ -28,31 +28,80 @@ protocol ClientOption : CustomStringConvertible, Equatable { func getSocketIOOptionValue() -> Any } +/// The options for a client. public enum SocketIOClientOption : ClientOption { + /// A dictionary of GET parameters that will be included in the connect url. case connectParams([String: Any]) + + /// An array of cookies that will be sent during the initial connection. case cookies([HTTPCookie]) + + /// The node.js socket.io currently does funky things to unicode when doing HTTP long-polling. Passing `true` in + /// this option causes the client to try and fix any bad unicode that might be sent. case doubleEncodeUTF8(Bool) + + /// Any extra HTTP headers that should be sent during the initial connection. case extraHeaders([String: String]) + + /// If passed `true`, will cause the client to always create a new engine. Useful for debugging, + /// or when you want to be sure no state from previous engines is being carried over. case forceNew(Bool) + + /// If passed `true`, the only transport that will be used will be HTTP long-polling. case forcePolling(Bool) + + /// If passed `true`, the only transport that will be used will be WebSockets. case forceWebsockets(Bool) + + /// The queue that all interaction with the client should occur on. This is the queue that event handlers are + /// called on. case handleQueue(DispatchQueue) + + /// If passed `true`, the client will log debug information. This should be turned off in production code. case log(Bool) + + /// Used to pass in a custom logger. case logger(SocketLogger) + + /// The namespace that this client should connect to. Can be changed during use using the `joinNamespace` + /// and `leaveNamespace` methods on `SocketIOClient`. case nsp(String) + + /// A custom path to socket.io. Only use this if the socket.io server is configured to look for this path. case path(String) + + /// If passed `false`, the client will not reconnect when it loses connection. Useful if you want full control + /// over when reconnects happen. case reconnects(Bool) + + /// The number of times to try and reconnect before giving up. Pass `-1` to [never give up](https://www.youtube.com/watch?v=dQw4w9WgXcQ). case reconnectAttempts(Int) + + /// The number of seconds to wait before reconnect attempts. case reconnectWait(Int) + + /// Set `true` if your server is using secure transports. case secure(Bool) + + /// Allows you to set which certs are valid. Useful for SSL pinning. case security(SSLSecurity) + + /// If you're using a self-signed set. Only use for development. case selfSigned(Bool) + + /// Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs. case sessionDelegate(URLSessionDelegate) + + /// If passed `true`, the WebSocket transport will try and use voip logic to keep network connections open in + /// the background. **This option is experimental as socket.io shouldn't be used for background communication.** case voipEnabled(Bool) - + + // MARK: Properties + + /// The description of this option. public var description: String { let description: String - + switch self { case .connectParams: description = "connectParams" @@ -95,13 +144,13 @@ public enum SocketIOClientOption : ClientOption { case .voipEnabled: description = "voipEnabled" } - + return description } - + func getSocketIOOptionValue() -> Any { let value: Any - + switch self { case let .connectParams(params): value = params @@ -144,11 +193,19 @@ public enum SocketIOClientOption : ClientOption { case let .voipEnabled(enabled): value = enabled } - + return value } -} -public func ==(lhs: SocketIOClientOption, rhs: SocketIOClientOption) -> Bool { - return lhs.description == rhs.description + // MARK: Operators + + /// Compares whether two options are the same. + /// + /// - parameter lhs: Left operand to compare. + /// - parameter rhs: Right operand to compare. + /// - returns: `true` if the two are the same option. + public static func ==(lhs: SocketIOClientOption, rhs: SocketIOClientOption) -> Bool { + return lhs.description == rhs.description + } + } diff --git a/Source/SocketIOClientStatus.swift b/Source/SocketIOClientStatus.swift index 27574e6..8caacbc 100644 --- a/Source/SocketIOClientStatus.swift +++ b/Source/SocketIOClientStatus.swift @@ -24,9 +24,17 @@ import Foundation -/// **NotConnected**: initial state -/// -/// **Disconnected**: connected before +/// Represents the state of the client. @objc public enum SocketIOClientStatus : Int { - case notConnected, disconnected, connecting, connected + /// The client has never been connected. Or the client has been reset. + case notConnected + + /// The client was once connected, but not anymore. + case disconnected + + /// The client is in the process of connecting. + case connecting + + /// The client is currently connected. + case connected } diff --git a/Source/SocketLogger.swift b/Source/SocketLogger.swift index 640d344..0b457ae 100644 --- a/Source/SocketLogger.swift +++ b/Source/SocketLogger.swift @@ -24,32 +24,47 @@ import Foundation +/// Represents a class will log client events. public protocol SocketLogger : class { + // MARK: Properties + /// Whether to log or not var log: Bool { get set } - + + // MARK: Methods + /// Normal log messages + /// + /// - parameter message: The message being logged. Can include `%@` that will be replaced with `args` + /// - parameter type: The type of entity that called for logging. + /// - parameter args: Any args that should be inserted into the message. May be left out. func log(_ message: String, type: String, args: Any...) - + /// Error Messages + /// + /// - parameter message: The message being logged. Can include `%@` that will be replaced with `args` + /// - parameter type: The type of entity that called for logging. + /// - parameter args: Any args that should be inserted into the message. May be left out. func error(_ message: String, type: String, args: Any...) } public extension SocketLogger { + /// Default implementation. func log(_ message: String, type: String, args: Any...) { abstractLog("LOG", message: message, type: type, args: args) } - + + /// Default implementation. func error(_ message: String, type: String, args: Any...) { abstractLog("ERROR", message: message, type: type, args: args) } - + private func abstractLog(_ logType: String, message: String, type: String, args: [Any]) { guard log else { return } - + let newArgs = args.map({arg -> CVarArg in String(describing: arg)}) - let messageFormat = String(format: message, arguments: newArgs) - + let messageFormat = String(format: message, arguments: newArgs) + NSLog("\(logType) \(type): %@", messageFormat) } } diff --git a/Source/SocketTypes.swift b/Source/SocketTypes.swift index cc194a7..b4eb203 100644 --- a/Source/SocketTypes.swift +++ b/Source/SocketTypes.swift @@ -24,6 +24,7 @@ import Foundation +/// A marking protocol that says a type can be represented in a socket.io packet. public protocol SocketData {} extension Array : SocketData {} @@ -39,7 +40,10 @@ extension NSString : SocketData {} extension NSNull : SocketData {} extension String : SocketData {} +/// A typealias for an ack callback. public typealias AckCallback = ([Any]) -> Void + +/// A typealias for a normal callback. public typealias NormalCallback = ([Any], SocketAckEmitter) -> Void typealias JSON = [String: Any] diff --git a/docs/Classes.html b/docs/Classes.html new file mode 100644 index 0000000..81bbdef --- /dev/null +++ b/docs/Classes.html @@ -0,0 +1,470 @@ + + + + Classes Reference + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

Classes

+

The following classes are available globally.

+ +
+
+ +
+
+
+ +
+
+
    +
  • +
    + + + + SocketAckEmitter + +
    +
    +
    +
    +
    +
    +

    A class that represents a waiting ack call.

    + +

    NOTE: You should not store this beyond the life of the event handler.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public final class SocketAckEmitter : NSObject
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + OnAckCallback + +
    +
    +
    +
    +
    +
    +

    A class that represents an emit that will request an ack that has not yet been sent. +Call timingOut(after:callback:) to complete the emit +Example:

    +
    socket.emitWithAck("myEvent").timingOut(after: 1) {data in
    +    ...
    +}
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public final class OnAckCallback : NSObject
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + SocketIOClient + +
    +
    +
    +
    +
    +
    +

    The main class for SocketIOClientSwift.

    + +

    Represents a socket.io-client. Most interaction with socket.io will be through this class.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable
    + +
    +
    +
    +
    +
  • +
+
+
+ +
+
+ +
+
+
    +
  • +
    + + + + SocketAnyEvent + +
    +
    +
    +
    +
    +
    +

    Represents some event that was received.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public final class SocketAnyEvent : NSObject
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + SocketClientManager + +
    +
    +
    +
    +
    +
    +

    Experimental socket manager.

    + +

    API subject to change.

    + +

    Can be used to persist sockets across ViewControllers.

    + +

    Sockets are strongly stored, so be sure to remove them once they are no +longer needed.

    + +

    Example usage:

    +
    let manager = SocketClientManager.sharedManager
    +manager["room1"] = socket1
    +manager["room2"] = socket2
    +manager.removeSocket(socket: socket2)
    +manager["room1"]?.emit("hello")
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open class SocketClientManager : NSObject
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/OnAckCallback.html b/docs/Classes/OnAckCallback.html new file mode 100644 index 0000000..9ed3e0d --- /dev/null +++ b/docs/Classes/OnAckCallback.html @@ -0,0 +1,271 @@ + + + + OnAckCallback Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

OnAckCallback

+
+
+
public final class OnAckCallback : NSObject
+ +
+
+

A class that represents an emit that will request an ack that has not yet been sent. +Call timingOut(after:callback:) to complete the emit +Example:

+
socket.emitWithAck("myEvent").timingOut(after: 1) {data in
+    ...
+}
+
+ +
+
+ +
+
+
+ +
    +
  • + +
    +
    +
    +
    +
    +

    Completes an emitWithAck. If this isn’t called, the emit never happens.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func timingOut(after seconds: Int, callback: @escaping AckCallback)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + after + + +
    +

    The number of seconds before this emit times out if an ack hasn’t been received.

    +
    +
    + + callback + + +
    +

    The callback called when an ack is received, or when a timeout happens. + To check for timeout, use SocketAckStatus‘s noAck case.

    +
    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/SSLCert.html b/docs/Classes/SSLCert.html new file mode 100644 index 0000000..253ab75 --- /dev/null +++ b/docs/Classes/SSLCert.html @@ -0,0 +1,293 @@ + + + + SSLCert Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SSLCert

+

Undocumented

+ +
+
+ +
+
+
+
    +
  • +
    + + + + init(data:) + +
    +
    +
    +
    +
    +
    +

    Designated init for certificates

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(data: Data)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + data + + +
    +

    is the binary data of the certificate

    +
    +
    +
    +
    +

    Return Value

    +

    a representation security object to be used with

    +
    +
    +
    +
  • +
  • +
    + + + + init(key:) + +
    +
    +
    +
    +
    +
    +

    Designated init for public keys

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(key: SecKey)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + key + + +
    +

    is the public key to be used

    +
    +
    +
    +
    +

    Return Value

    +

    a representation security object to be used with

    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/SSLSecurity.html b/docs/Classes/SSLSecurity.html new file mode 100644 index 0000000..104f70b --- /dev/null +++ b/docs/Classes/SSLSecurity.html @@ -0,0 +1,386 @@ + + + + SSLSecurity Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SSLSecurity

+

Undocumented

+ +
+
+ +
+
+
+
    +
  • +
    + + + + validatedDN + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + init(usePublicKeys:) + +
    +
    +
    +
    +
    +
    +

    Use certs from main app bundle

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public convenience init(usePublicKeys: Bool = false)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + usePublicKeys + + +
    +

    is to specific if the publicKeys or certificates should be used for SSL pinning validation

    +
    +
    +
    +
    +

    Return Value

    +

    a representation security object to be used with

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Designated init

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(certs: [SSLCert], usePublicKeys: Bool)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + certs + + +
    +

    is the certificates or public keys to use

    +
    +
    + + usePublicKeys + + +
    +

    is to specific if the publicKeys or certificates should be used for SSL pinning validation

    +
    +
    +
    +
    +

    Return Value

    +

    a representation security object to be used with

    +
    +
    +
    +
  • +
  • +
    + + + + isValid(_:domain:) + +
    +
    +
    +
    +
    +
    +

    Valid the trust and domain name.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func isValid(_ trust: SecTrust, domain: String?) -> Bool
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + trust + + +
    +

    is the serverTrust to validate

    +
    +
    + + domain + + +
    +

    is the CN domain to validate

    +
    +
    +
    +
    +

    Return Value

    +

    if the key was successfully validated

    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/SocketAckEmitter.html b/docs/Classes/SocketAckEmitter.html new file mode 100644 index 0000000..919d0c9 --- /dev/null +++ b/docs/Classes/SocketAckEmitter.html @@ -0,0 +1,338 @@ + + + + SocketAckEmitter Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketAckEmitter

+
+
+
public final class SocketAckEmitter : NSObject
+ +
+
+

A class that represents a waiting ack call.

+ +

NOTE: You should not store this beyond the life of the event handler.

+ +
+
+ +
+
+
+ +
    +
  • +
    + + + + expected + +
    +
    +
    +
    +
    +
    +

    If true, this handler is expecting to be acked. Call with(_: SocketData...) to ack.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var expected: Bool
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + with(_:) + +
    +
    +
    +
    +
    +
    +

    Call to ack receiving this event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func with(_ items: SocketData...)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + items + + +
    +

    A variable number of items to send when acking.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + with(_:) + +
    +
    +
    +
    +
    +
    +

    Call to ack receiving this event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func with(_ items: [Any])
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + items + + +
    +

    An array of items to send when acking. Use [] to send nothing.

    +
    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/SocketAnyEvent.html b/docs/Classes/SocketAnyEvent.html new file mode 100644 index 0000000..27286dd --- /dev/null +++ b/docs/Classes/SocketAnyEvent.html @@ -0,0 +1,287 @@ + + + + SocketAnyEvent Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketAnyEvent

+
+
+
public final class SocketAnyEvent : NSObject
+ +
+
+

Represents some event that was received.

+ +
+
+ +
+
+
+ +
    +
  • +
    + + + + event + +
    +
    +
    +
    +
    +
    +

    The event name.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let event: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + items + +
    +
    +
    +
    +
    +
    +

    The data items for this event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let items: [Any]?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + description + +
    +
    +
    +
    +
    +
    +

    The description of this event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    override public var description: String
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/SocketClientManager.html b/docs/Classes/SocketClientManager.html new file mode 100644 index 0000000..4698110 --- /dev/null +++ b/docs/Classes/SocketClientManager.html @@ -0,0 +1,475 @@ + + + + SocketClientManager Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketClientManager

+
+
+
open class SocketClientManager : NSObject
+ +
+
+

Experimental socket manager.

+ +

API subject to change.

+ +

Can be used to persist sockets across ViewControllers.

+ +

Sockets are strongly stored, so be sure to remove them once they are no +longer needed.

+ +

Example usage:

+
let manager = SocketClientManager.sharedManager
+manager["room1"] = socket1
+manager["room2"] = socket2
+manager.removeSocket(socket: socket2)
+manager["room1"]?.emit("hello")
+
+ +
+
+ +
+
+
+ +
    +
  • +
    + + + + subscript(_:) + +
    +
    +
    +
    +
    +
    +

    Gets a socket by its name.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open subscript(string: String) -> SocketIOClient?
    + +
    +
    +
    +

    Return Value

    +

    The socket, if one had the given name.

    +
    +
    +
    +
  • +
  • +
    + + + + sharedManager + +
    +
    +
    +
    +
    +
    +

    The shared manager.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open static let sharedManager = SocketClientManager()
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • + +
    +
    +
    +
    +
    +

    Adds a socket.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func addSocket(_ socket: SocketIOClient, labeledAs label: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + socket + + +
    +

    The socket to add.

    +
    +
    + + labeledAs + + +
    +

    The label for this socket.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Removes a socket by a given name.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func removeSocket(withLabel label: String) -> SocketIOClient?
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + withLabel + + +
    +

    The label of the socket to remove.

    +
    +
    +
    +
    +

    Return Value

    +

    The socket for the given label, if one was present.

    +
    +
    +
    +
  • +
  • +
    + + + + removeSocket(_:) + +
    +
    +
    +
    +
    +
    +

    Removes a socket.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func removeSocket(_ socket: SocketIOClient) -> SocketIOClient?
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + socket + + +
    +

    The socket to remove.

    +
    +
    +
    +
    +

    Return Value

    +

    The socket if it was in the manager.

    +
    +
    +
    +
  • +
  • +
    + + + + removeSockets() + +
    +
    +
    +
    +
    +
    +

    Removes all the sockets in the manager.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func removeSockets()
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/SocketEngine.html b/docs/Classes/SocketEngine.html new file mode 100644 index 0000000..3cbe780 --- /dev/null +++ b/docs/Classes/SocketEngine.html @@ -0,0 +1,1466 @@ + + + + SocketEngine Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketEngine

+
+
+
public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket
+ +
+
+

The class that handles the engine.io protocol and transports. +See SocketEnginePollable and SocketEngineWebsocket for transport specific methods.

+ +
+
+ +
+
+
+ +
    +
  • +
    + + + + engineQueue + +
    +
    +
    +
    +
    +
    +

    The queue that all engine actions take place on.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue")
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + connectParams + +
    +
    +
    +
    +
    +
    +

    The connect parameters sent during a connect.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var connectParams: [String: Any]?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + postWait + +
    +
    +
    +
    +
    +
    +

    A queue of engine.io messages waiting for POSTing

    + +

    You should not touch this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var postWait = [String]()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + waitingForPoll + +
    +
    +
    +
    +
    +
    +

    true if there is an outstanding poll. Trying to poll before the first is done will cause socket.io to +disconnect us.

    + +

    Do not touch this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var waitingForPoll = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + waitingForPost + +
    +
    +
    +
    +
    +
    +

    true if there is an outstanding post. Trying to post before the first is done will cause socket.io to +disconnect us.

    + +

    Do not touch this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var waitingForPost = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + closed + +
    +
    +
    +
    +
    +
    +

    true if this engine is closed.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var closed = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + connected + +
    +
    +
    +
    +
    +
    +

    true if this engine is connected. Connected means that the initial poll connect has succeeded.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var connected = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + cookies + +
    +
    +
    +
    +
    +
    +

    An array of HTTPCookies that are sent during the connection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var cookies: [HTTPCookie]?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + doubleEncodeUTF8 + +
    +
    +
    +
    +
    +
    +

    Set to true if using the node.js version of socket.io. The node.js version of socket.io +handles utf8 incorrectly.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var doubleEncodeUTF8 = true
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + extraHeaders + +
    +
    +
    +
    +
    +
    +

    A dictionary of extra http headers that will be set during connection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var extraHeaders: [String: String]?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + fastUpgrade + +
    +
    +
    +
    +
    +
    +

    When true, the engine is in the process of switching to WebSockets.

    + +

    Do not touch this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var fastUpgrade = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + forcePolling + +
    +
    +
    +
    +
    +
    +

    When true, the engine will only use HTTP long-polling as a transport.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var forcePolling = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + forceWebsockets + +
    +
    +
    +
    +
    +
    +

    When true, the engine will only use WebSockets as a transport.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var forceWebsockets = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + invalidated + +
    +
    +
    +
    +
    +
    +

    true If engine’s session has been invalidated.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var invalidated = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + polling + +
    +
    +
    +
    +
    +
    +

    If true, the engine is currently in HTTP long-polling mode.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var polling = true
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + probing + +
    +
    +
    +
    +
    +
    +

    If true, the engine is currently seeing whether it can upgrade to WebSockets.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var probing = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + session + +
    +
    +
    +
    +
    +
    +

    The URLSession that will be used for polling.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var session: URLSession?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + sid + +
    +
    +
    +
    +
    +
    +

    The session id for this engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var sid = ""
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + socketPath + +
    +
    +
    +
    +
    +
    +

    The path to engine.io.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var socketPath = "/engine.io/"
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + urlPolling + +
    +
    +
    +
    +
    +
    +

    The url for polling.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var urlPolling = URL(string: "http://localhost/")!
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + urlWebSocket + +
    +
    +
    +
    +
    +
    +

    The url for WebSockets.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var urlWebSocket = URL(string: "http://localhost/")!
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + websocket + +
    +
    +
    +
    +
    +
    +

    If true, then the engine is currently in WebSockets mode.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var websocket = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + ws + +
    +
    +
    +
    +
    +
    +

    The WebSocket for this engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var ws: WebSocket?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + client + +
    +
    +
    +
    +
    +
    +

    The client for this engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public weak var client: SocketEngineClient?
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • + +
    +
    +
    +
    +
    +

    Creates a new engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(client: SocketEngineClient, url: URL, config: SocketIOClientConfiguration)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + client + + +
    +

    The client for this engine.

    +
    +
    + + url + + +
    +

    The url for this engine.

    +
    +
    + + config + + +
    +

    An array of configuration options for this engine.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Creates a new engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + client + + +
    +

    The client for this engine.

    +
    +
    + + url + + +
    +

    The url for this engine.

    +
    +
    + + options + + +
    +

    The options for this engine.

    +
    +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + connect() + +
    +
    +
    +
    +
    +
    +

    Starts the connection to the server.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func connect()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + didError(reason:) + +
    +
    +
    +
    +
    +
    +

    Called when an error happens during execution. Causes a disconnection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func didError(reason: String)
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + disconnect(reason:) + +
    +
    +
    +
    +
    +
    +

    Disconnects from the server.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func disconnect(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason for the disconnection. This is communicated up to the client.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + doFastUpgrade() + +
    +
    +
    +
    +
    +
    +

    Called to switch from HTTP long-polling to WebSockets. After calling this method the engine will be in +WebSocket mode.

    + +

    You shouldn’t call this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func doFastUpgrade()
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Causes any packets that were waiting for POSTing to be sent through the WebSocket. This happens because when +the engine is attempting to upgrade to WebSocket it does not do any POSTing.

    + +

    You shouldn’t call this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func flushWaitingForPostToWebSocket()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + parseEngineData(_:) + +
    +
    +
    +
    +
    +
    +

    Parses raw binary received from engine.io.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func parseEngineData(_ data: Data)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + data + + +
    +

    The data to parse.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Parses a raw engine.io packet.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func parseEngineMessage(_ message: String, fromPolling: Bool)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + message + + +
    +

    The message to parse.

    +
    +
    + + fromPolling + + +
    +

    Whether this message is from long-polling. + If true we might have to fix utf8 encoding.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Writes a message to engine.io, independent of transport.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data])
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + msg + + +
    +

    The message to send.

    +
    +
    + + withType + + +
    +

    The type of this message.

    +
    +
    + + withData + + +
    +

    Any data that this message has.

    +
    +
    +
    +
    +
    +
  • +
+
+
+ + +
+
+ +
    +
  • + +
    +
    +
    +
    +
    +

    Delegate called when the session becomes invalid.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func URLSession(session: URLSession, didBecomeInvalidWithError error: NSError?)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/SocketIOClient.html b/docs/Classes/SocketIOClient.html new file mode 100644 index 0000000..fdcaf4a --- /dev/null +++ b/docs/Classes/SocketIOClient.html @@ -0,0 +1,1699 @@ + + + + SocketIOClient Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketIOClient

+
+
+
open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable
+ +
+
+

The main class for SocketIOClientSwift.

+ +

Represents a socket.io-client. Most interaction with socket.io will be through this class.

+ +
+
+ +
+
+
+ +
    +
  • +
    + + + + socketURL + +
    +
    +
    +
    +
    +
    +

    The URL of the socket.io server. This is set in the initializer.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let socketURL: URL
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + engine + +
    +
    +
    +
    +
    +
    +

    The engine for this client.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var engine: SocketEngineSpec?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + status + +
    +
    +
    +
    +
    +
    +

    The status of this client.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public private(set) var status = SocketIOClientStatus.notConnected
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + forceNew + +
    +
    +
    +
    +
    +
    +

    If true then every time connect is called, a new engine will be created.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var forceNew = false
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + handleQueue + +
    +
    +
    +
    +
    +
    +

    The queue that all interaction with the client should occur on. This is the queue that event handlers are +called on.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var handleQueue = DispatchQueue.main
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + nsp + +
    +
    +
    +
    +
    +
    +

    The namespace for this client.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var nsp = "/"
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + config + +
    +
    +
    +
    +
    +
    +

    The configuration for this client.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var config: SocketIOClientConfiguration
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + reconnects + +
    +
    +
    +
    +
    +
    +

    If true, this client will try and reconnect on any disconnects.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var reconnects = true
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + reconnectWait + +
    +
    +
    +
    +
    +
    +

    The number of seconds to wait before attempting to reconnect.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var reconnectWait = 10
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + sid + +
    +
    +
    +
    +
    +
    +

    The session id of this client.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var sid: String?
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • + +
    +
    +
    +
    +
    +

    Type safe way to create a new SocketIOClient. opts can be omitted.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(socketURL: URL, config: SocketIOClientConfiguration = [])
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + socketURL + + +
    +

    The url of the socket.io server.

    +
    +
    + + config + + +
    +

    The config for this socket.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity. +If using Swift it’s recommended to use init(socketURL: NSURL, options: Set<SocketIOClientOption>)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public convenience init(socketURL: NSURL, config: NSDictionary?)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + socketURL + + +
    +

    The url of the socket.io server.

    +
    +
    + + config + + +
    +

    The config for this socket.

    +
    +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + connect() + +
    +
    +
    +
    +
    +
    +

    Connect to the server.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func connect()
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Connect to the server. If we aren’t connected after timeoutAfter seconds, then withHandler is called.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func connect(timeoutAfter: Int, withHandler handler: (() -> Void)?)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + timeoutAfter + + +
    +

    The number of seconds after which if we are not connected we assume the connection + has failed. Pass 0 to never timeout.

    +
    +
    + + withHandler + + +
    +

    The handler to call when the client fails to connect.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + disconnect() + +
    +
    +
    +
    +
    +
    +

    Disconnects the socket.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func disconnect()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + emit(_:_:) + +
    +
    +
    +
    +
    +
    +

    Send an event to the server, with optional data items.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func emit(_ event: String, _ items: SocketData...)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + event + + +
    +

    The event to send.

    +
    +
    + + items + + +
    +

    The items to send with this event. May be left out.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + emit(_:with:) + +
    +
    +
    +
    +
    +
    +

    Same as emit, but meant for Objective-C

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func emit(_ event: String, with items: [Any])
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + event + + +
    +

    The event to send.

    +
    +
    + + with + + +
    +

    The items to send with this event. May be left out.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + emitWithAck(_:_:) + +
    +
    +
    +
    +
    +
    +

    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.

    + +

    Example:

    +
    socket.emitWithAck("myEvent", 1).timingOut(after: 1) {data in
    +    ...
    +}
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + event + + +
    +

    The event to send.

    +
    +
    + + items + + +
    +

    The items to send with this event. May be left out.

    +
    +
    +
    +
    +

    Return Value

    +

    An OnAckCallback. You must call the timingOut(after:) method before the event will be sent.

    +
    +
    +
    +
  • +
  • +
    + + + + emitWithAck(_:with:) + +
    +
    +
    +
    +
    +
    +

    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:

    +
    socket.emitWithAck("myEvent", with: [1]).timingOut(after: 1) {data in
    +    ...
    +}
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + event + + +
    +

    The event to send.

    +
    +
    + + with + + +
    +

    The items to send with this event. Use [] to send nothing.

    +
    +
    +
    +
    +

    Return Value

    +

    An OnAckCallback. You must call the timingOut(after:) method before the event will be sent.

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine closes.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func engineDidClose(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason that the engine closed.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine errors.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func engineDidError(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason the engine errored.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine opens.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func engineDidOpen(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason the engine opened.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Causes an event to be handled, and any event handlers for that event to be called.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + +
    + + event + + +
    +

    The event that is to be handled.

    +
    +
    + + data + + +
    +

    the data associated with this event.

    +
    +
    + + isInternalMessage + + +
    +

    If true event handlers for this event will be called regardless of status.

    +
    +
    + + withAck + + +
    +

    The ack number for this event. May be left out.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + leaveNamespace() + +
    +
    +
    +
    +
    +
    +

    Leaves nsp and goes back to the default namespace.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func leaveNamespace()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + joinNamespace(_:) + +
    +
    +
    +
    +
    +
    +

    Joins namespace.

    + +

    Do not use this to join the default namespace. Instead call leaveNamespace.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func joinNamespace(_ namespace: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + namespace + + +
    +

    The namespace to join.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + off(_:) + +
    +
    +
    +
    +
    +
    +

    Removes handler(s) based on an event name.

    + +

    If you wish to remove a specific event, call the off(if:) with the UUID received from its on call.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func off(_ event: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + event + + +
    +

    The event to remove handlers for.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + off(id:) + +
    +
    +
    +
    +
    +
    +

    Removes a handler with the specified UUID gotten from an on or once

    + +

    If you want to remove all events for an event, call the off off(_:) method with the event name.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func off(id: UUID)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + id + + +
    +

    The UUID of the handler you wish to remove.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + on(_:callback:) + +
    +
    +
    +
    +
    +
    +

    Adds a handler for an event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func on(_ event: String, callback: @escaping NormalCallback) -> UUID
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + event + + +
    +

    The event name for this handler.

    +
    +
    + + callback + + +
    +

    The callback that will execute when this event is received.

    +
    +
    +
    +
    +

    Return Value

    +

    A unique id for the handler that can be used to remove it.

    +
    +
    +
    +
  • +
  • +
    + + + + once(_:callback:) + +
    +
    +
    +
    +
    +
    +

    Adds a single-use handler for an event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func once(_ event: String, callback: @escaping NormalCallback) -> UUID
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + event + + +
    +

    The event name for this handler.

    +
    +
    + + callback + + +
    +

    The callback that will execute when this event is received.

    +
    +
    +
    +
    +

    Return Value

    +

    A unique id for the handler that can be used to remove it.

    +
    +
    +
    +
  • +
  • +
    + + + + onAny(_:) + +
    +
    +
    +
    +
    +
    +

    Adds a handler that will be called on every event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func onAny(_ handler: @escaping (SocketAnyEvent) -> Void)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + handler + + +
    +

    The callback that will execute whenever an event is received.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine has a message that must be parsed.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func parseEngineMessage(_ msg: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + msg + + +
    +

    The message that needs parsing.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine receives binary data.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func parseEngineBinaryData(_ data: Data)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + data + + +
    +

    The data the engine received.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + reconnect() + +
    +
    +
    +
    +
    +
    +

    Tries to reconnect to the server.

    + +

    This will cause a disconnect event to be emitted, as well as an reconnectAttempt event.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func reconnect()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + removeAllHandlers() + +
    +
    +
    +
    +
    +
    +

    Removes all handlers. +Can be used after disconnecting to break any potential remaining retain cycles.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func removeAllHandlers()
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/WebSocket.html b/docs/Classes/WebSocket.html new file mode 100644 index 0000000..b8e4fc2 --- /dev/null +++ b/docs/Classes/WebSocket.html @@ -0,0 +1,911 @@ + + + + WebSocket Class Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

WebSocket

+

Undocumented

+ +
+
+ +
+
+
+ +
+
+ +
    +
  • +
    + + + + delegate + +
    +
    +
    +
    +
    +
    +

    Responds to callback about new messages coming in over the WebSocket +and also connection/disconnect messages.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public weak var delegate: WebSocketDelegate?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + pongDelegate + +
    +
    +
    +
    +
    +
    +

    Receives a callback for each pong message recived.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public weak var pongDelegate: WebSocketPongDelegate?
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + onConnect + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + onDisconnect + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + onText + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + onData + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + onPong + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + headers + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + voipEnabled + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + security + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + origin + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + timeout + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + isConnected + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + currentURL + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + init(url:protocols:) + +
    +
    +
    +
    +
    +
    +

    Used for setting protocols.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(url: URL, protocols: [String]? = nil)
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    + + + + connect() + +
    +
    +
    +
    +
    +
    +

    Connect to the WebSocket server on a background thread.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func connect()
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Disconnect from the server. I send a Close control frame to the server, then expect the server to respond with a Close control frame and close the socket from its end. I notify my delegate once the socket has been closed. +If you supply a non-nil forceTimeout, I wait at most that long (in seconds) for the server to close the socket. After the timeout expires, I close the socket and notify my delegate. +If you supply a zero (or negative) forceTimeout, I immediately close the socket (without sending a Close control frame) and notify my delegate.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func disconnect(forceTimeout: TimeInterval? = nil, closeCode: UInt16 = CloseCode.normal.rawValue)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + forceTimeout + + +
    +

    Maximum time to wait for the server to close the socket.

    +
    +
    + + closeCode + + +
    +

    The code to send on disconnect. The default is the normal close code for cleanly disconnecting a webSocket.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Write a string to the websocket. This sends it as a text frame. +If you supply a non-nil completion block, I will perform it when the write completes.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func write(string: String, completion: (() -> ())? = nil)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + string + + +
    +

    The string to write.

    +
    +
    + + completion + + +
    +

    The (optional) completion handler.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Write binary data to the websocket. This sends it as a binary frame. +If you supply a non-nil completion block, I will perform it when the write completes.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func write(data: Data, completion: (() -> ())? = nil)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + data + + +
    +

    The data to write.

    +
    +
    + + completion + + +
    +

    The (optional) completion handler.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Write a ping to the websocket. This sends it as a control frame. +Yodel a sound to the planet. This sends it as an astroid. http://youtu.be/Eu5ZJELRiJ8?t=42s

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func write(ping: Data, completion: (() -> ())? = nil)
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + stream(_:handle:) + +
    +
    +
    +
    +
    +
    +

    Delegate for the stream methods. Processes incoming bytes

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    open func stream(_ aStream: Stream, handle eventCode: Stream.Event)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Classes/WebSocket/CloseCode.html b/docs/Classes/WebSocket/CloseCode.html new file mode 100644 index 0000000..b6fd482 --- /dev/null +++ b/docs/Classes/WebSocket/CloseCode.html @@ -0,0 +1,373 @@ + + + + CloseCode Enum Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

CloseCode

+

Undocumented

+ +
+
+ +
+
+
+
    +
  • +
    + + + + normal + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + goingAway + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + protocolError + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
+
+
+ +
+
+ +
+
+
    +
  • +
    + + + + encoding + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
+
+
+ +
+
+
    +
  • +
    + + + + messageTooBig + +
    +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Enums.html b/docs/Enums.html new file mode 100644 index 0000000..f07491b --- /dev/null +++ b/docs/Enums.html @@ -0,0 +1,316 @@ + + + + Enums Reference + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

Enums

+

The following enums are available globally.

+ +
+
+ +
+
+
+
    +
  • +
    + + + + SocketIOClientStatus + +
    +
    +
    +
    +
    +
    +

    Represents the state of the client.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objc public enum SocketIOClientStatus : Int
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + SocketAckStatus + +
    +
    +
    +
    +
    +
    +

    The status of an ack.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum SocketAckStatus : String
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    Represents the type of engine.io packet types.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objc public enum SocketEnginePacketType : Int
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + SocketIOClientOption + +
    +
    +
    +
    +
    +
    +

    The options for a client.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum SocketIOClientOption : ClientOption
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Enums/SocketAckStatus.html b/docs/Enums/SocketAckStatus.html new file mode 100644 index 0000000..2cf38e3 --- /dev/null +++ b/docs/Enums/SocketAckStatus.html @@ -0,0 +1,226 @@ + + + + SocketAckStatus Enum Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketAckStatus

+
+
+
public enum SocketAckStatus : String
+ +
+
+

The status of an ack.

+ +
+
+ +
+
+
+
    +
  • +
    + + + + noAck + +
    +
    +
    +
    +
    +
    +

    The ack timed out.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case noAck = "NO ACK"
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Enums/SocketEnginePacketType.html b/docs/Enums/SocketEnginePacketType.html new file mode 100644 index 0000000..11c055b --- /dev/null +++ b/docs/Enums/SocketEnginePacketType.html @@ -0,0 +1,412 @@ + + + + SocketEnginePacketType Enum Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketEnginePacketType

+
+
+
@objc public enum SocketEnginePacketType : Int
+ +
+
+

Represents the type of engine.io packet types.

+ +
+
+ +
+
+
+
    +
  • +
    + + + + open + +
    +
    +
    +
    +
    +
    +

    Open message.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case open
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + close + +
    +
    +
    +
    +
    +
    +

    Close message.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case close
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + ping + +
    +
    +
    +
    +
    +
    +

    Ping message.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case ping
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + pong + +
    +
    +
    +
    +
    +
    +

    Pong message.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case pong
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + message + +
    +
    +
    +
    +
    +
    +

    Regular message.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case message
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + upgrade + +
    +
    +
    +
    +
    +
    +

    Upgrade message.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case upgrade
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + noop + +
    +
    +
    +
    +
    +
    +

    NOOP.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case noop
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Enums/SocketIOClientOption.html b/docs/Enums/SocketIOClientOption.html new file mode 100644 index 0000000..e2cd06e --- /dev/null +++ b/docs/Enums/SocketIOClientOption.html @@ -0,0 +1,932 @@ + + + + SocketIOClientOption Enum Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketIOClientOption

+
+
+
public enum SocketIOClientOption : ClientOption
+ +
+
+

The options for a client.

+ +
+
+ +
+
+
+
    +
  • +
    + + + + connectParams + +
    +
    +
    +
    +
    +
    +

    A dictionary of GET parameters that will be included in the connect url.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case connectParams([String: Any])
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + cookies + +
    +
    +
    +
    +
    +
    +

    An array of cookies that will be sent during the initial connection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case cookies([HTTPCookie])
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + doubleEncodeUTF8 + +
    +
    +
    +
    +
    +
    +

    The node.js socket.io currently does funky things to unicode when doing HTTP long-polling. Passing true in +this option causes the client to try and fix any bad unicode that might be sent.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case doubleEncodeUTF8(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + extraHeaders + +
    +
    +
    +
    +
    +
    +

    Any extra HTTP headers that should be sent during the initial connection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case extraHeaders([String: String])
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + forceNew + +
    +
    +
    +
    +
    +
    +

    If passed true, will cause the client to always create a new engine. Useful for debugging, +or when you want to be sure no state from previous engines is being carried over.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case forceNew(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + forcePolling + +
    +
    +
    +
    +
    +
    +

    If passed true, the only transport that will be used will be HTTP long-polling.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case forcePolling(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + forceWebsockets + +
    +
    +
    +
    +
    +
    +

    If passed true, the only transport that will be used will be WebSockets.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case forceWebsockets(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + handleQueue + +
    +
    +
    +
    +
    +
    +

    The queue that all interaction with the client should occur on. This is the queue that event handlers are +called on.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case handleQueue(DispatchQueue)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + log + +
    +
    +
    +
    +
    +
    +

    If passed true, the client will log debug information. This should be turned off in production code.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case log(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + logger + +
    +
    +
    +
    +
    +
    +

    Used to pass in a custom logger.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case logger(SocketLogger)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + nsp + +
    +
    +
    +
    +
    +
    +

    The namespace that this client should connect to. Can be changed during use using the joinNamespace +and leaveNamespace methods on SocketIOClient.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case nsp(String)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + path + +
    +
    +
    +
    +
    +
    +

    A custom path to socket.io. Only use this if the socket.io server is configured to look for this path.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case path(String)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + reconnects + +
    +
    +
    +
    +
    +
    +

    If passed false, the client will not reconnect when it loses connection. Useful if you want full control +over when reconnects happen.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case reconnects(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + reconnectAttempts + +
    +
    +
    +
    +
    +
    +

    The number of times to try and reconnect before giving up. Pass -1 to never give up.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case reconnectAttempts(Int)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + reconnectWait + +
    +
    +
    +
    +
    +
    +

    The number of seconds to wait before reconnect attempts.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case reconnectWait(Int)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + secure + +
    +
    +
    +
    +
    +
    +

    Set true if your server is using secure transports.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case secure(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + security + +
    +
    +
    +
    +
    +
    +

    Allows you to set which certs are valid. Useful for SSL pinning.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case security(SSLSecurity)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + selfSigned + +
    +
    +
    +
    +
    +
    +

    If you’re using a self-signed set. Only use for development.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case selfSigned(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + sessionDelegate + +
    +
    +
    +
    +
    +
    +

    Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case sessionDelegate(URLSessionDelegate)
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + voipEnabled + +
    +
    +
    +
    +
    +
    +

    If passed true, the WebSocket transport will try and use voip logic to keep network connections open in +the background. This option is experimental as socket.io shouldn’t be used for background communication.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case voipEnabled(Bool)
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + description + +
    +
    +
    +
    +
    +
    +

    The description of this option.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var description: String
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + ==(_:_:) + +
    +
    +
    +
    +
    +
    +

    Compares whether two options are the same.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public static func ==(lhs: SocketIOClientOption, rhs: SocketIOClientOption) -> Bool
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + lhs + + +
    +

    Left operand to compare.

    +
    +
    + + rhs + + +
    +

    Right operand to compare.

    +
    +
    +
    +
    +

    Return Value

    +

    true if the two are the same option.

    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Enums/SocketIOClientStatus.html b/docs/Enums/SocketIOClientStatus.html new file mode 100644 index 0000000..94012e7 --- /dev/null +++ b/docs/Enums/SocketIOClientStatus.html @@ -0,0 +1,319 @@ + + + + SocketIOClientStatus Enum Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketIOClientStatus

+
+
+
@objc public enum SocketIOClientStatus : Int
+ +
+
+

Represents the state of the client.

+ +
+
+ +
+
+
+
    +
  • +
    + + + + notConnected + +
    +
    +
    +
    +
    +
    +

    The client has never been connected. Or the client has been reset.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case notConnected
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + disconnected + +
    +
    +
    +
    +
    +
    +

    The client was once connected, but not anymore.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case disconnected
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + connecting + +
    +
    +
    +
    +
    +
    +

    The client is in the process of connecting.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case connecting
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + connected + +
    +
    +
    +
    +
    +
    +

    The client is currently connected.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case connected
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Global Variables.html b/docs/Global Variables.html new file mode 100644 index 0000000..77a366d --- /dev/null +++ b/docs/Global Variables.html @@ -0,0 +1,249 @@ + + + + Global Variables Reference + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ + +
+ + + + diff --git a/docs/Protocols.html b/docs/Protocols.html new file mode 100644 index 0000000..7fd064e --- /dev/null +++ b/docs/Protocols.html @@ -0,0 +1,447 @@ + + + + Protocols Reference + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

Protocols

+

The following protocols are available globally.

+ +
+
+ +
+
+
+ +
+
+
    +
  • +
    + + + + SocketEnginePollable + +
    +
    +
    +
    +
    +
    +

    Protocol that is used to implement socket.io polling support

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol SocketEnginePollable : SocketEngineSpec
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + SocketEngineSpec + +
    +
    +
    +
    +
    +
    +

    Specifies a SocketEngine.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objc public protocol SocketEngineSpec
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + SocketData + +
    +
    +
    +
    +
    +
    +

    A marking protocol that says a type can be represented in a socket.io packet.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol SocketData
    + +
    +
    +
    +
    +
  • +
+
+
+
    +
  • +
    + + + + SocketLogger + +
    +
    +
    +
    +
    +
    +

    Represents a class will log client events.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol SocketLogger : class
    + +
    +
    +
    +
    +
  • +
+
+
+ +
+
+
    +
  • +
    + + + + SocketEngineClient + +
    +
    +
    +
    +
    +
    +

    Declares that a type will be a delegate to an engine.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @objc public protocol SocketEngineClient
    + +
    +
    +
    +
    +
  • +
+
+
+ +
+
+
+ +
+
+ + + + diff --git a/docs/Protocols/SSLTrustValidator.html b/docs/Protocols/SSLTrustValidator.html new file mode 100644 index 0000000..20cf777 --- /dev/null +++ b/docs/Protocols/SSLTrustValidator.html @@ -0,0 +1,212 @@ + + + + SSLTrustValidator Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SSLTrustValidator

+

Undocumented

+ +
+
+ +
+
+
+ +
+
+
+ +
+
+ + + + diff --git a/docs/Protocols/SocketEngineClient.html b/docs/Protocols/SocketEngineClient.html new file mode 100644 index 0000000..14b067d --- /dev/null +++ b/docs/Protocols/SocketEngineClient.html @@ -0,0 +1,436 @@ + + + + SocketEngineClient Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketEngineClient

+
+
+
@objc public protocol SocketEngineClient
+ +
+
+

Declares that a type will be a delegate to an engine.

+ +
+
+ +
+
+
+ +
    +
  • + +
    +
    +
    +
    +
    +

    Called when the engine errors.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func engineDidError(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason the engine errored.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine closes.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func engineDidClose(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason that the engine closed.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine opens.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func engineDidOpen(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason the engine opened.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine has a message that must be parsed.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func parseEngineMessage(_ msg: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + msg + + +
    +

    The message that needs parsing.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Called when the engine receives binary data.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func parseEngineBinaryData(_ data: Data)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + data + + +
    +

    The data the engine received.

    +
    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Protocols/SocketEnginePollable.html b/docs/Protocols/SocketEnginePollable.html new file mode 100644 index 0000000..37b9ea4 --- /dev/null +++ b/docs/Protocols/SocketEnginePollable.html @@ -0,0 +1,499 @@ + + + + SocketEnginePollable Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketEnginePollable

+
+
+
public protocol SocketEnginePollable : SocketEngineSpec
+ +
+
+

Protocol that is used to implement socket.io polling support

+ +
+
+ +
+
+
+
    +
  • +
    + + + + invalidated + +
    +
    +
    +
    +
    +
    +

    MARK: Properties +true If engine’s session has been invalidated.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var invalidated: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + postWait + +
    +
    +
    +
    +
    +
    +

    A queue of engine.io messages waiting for POSTing

    + +

    You should not touch this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var postWait: [String]
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + session + +
    +
    +
    +
    +
    +
    +

    The URLSession that will be used for polling.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var session: URLSession?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + waitingForPoll + +
    +
    +
    +
    +
    +
    +

    true if there is an outstanding poll. Trying to poll before the first is done will cause socket.io to +disconnect us.

    + +

    Do not touch this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var waitingForPoll: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + waitingForPost + +
    +
    +
    +
    +
    +
    +

    true if there is an outstanding post. Trying to post before the first is done will cause socket.io to +disconnect us.

    + +

    Do not touch this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var waitingForPost: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + doPoll() + + + Default implementation + +
    +
    +
    +
    +
    +
    +

    Call to send a long-polling request.

    + +

    You shouldn’t need to call this directly, the engine should automatically maintain a long-poll request.

    + +
    +

    Default Implementation

    +
    +

    Call to send a long-polling request.

    + +

    You shouldn’t need to call this directly, the engine should automatically maintain a long-poll request.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func doPoll()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + sendPollMessage(_:withType:withData:) + + + Default implementation + +
    +
    +
    +
    +
    +
    +

    Sends an engine.io message through the polling transport.

    + +

    You shouldn’t call this directly, instead call the write method on SocketEngine.

    + +
    +

    Default Implementation

    +
    +

    Sends an engine.io message through the polling transport.

    + +

    You shouldn’t call this directly, instead call the write method on SocketEngine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data])
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + message + + +
    +

    The message to send.

    +
    +
    + + withType + + +
    +

    The type of message to send.

    +
    +
    + + withData + + +
    +

    The data associated with this message.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + stopPolling() + + + Default implementation + +
    +
    +
    +
    +
    +
    +

    Call to stop polling and invalidate the URLSession.

    + +
    +

    Default Implementation

    +
    +

    Call to stop polling and invalidate the URLSession.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func stopPolling()
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Protocols/SocketEngineSpec.html b/docs/Protocols/SocketEngineSpec.html new file mode 100644 index 0000000..29e25f7 --- /dev/null +++ b/docs/Protocols/SocketEngineSpec.html @@ -0,0 +1,1118 @@ + + + + SocketEngineSpec Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketEngineSpec

+
+
+
@objc public protocol SocketEngineSpec
+ +
+
+

Specifies a SocketEngine.

+ +
+
+ +
+
+
+
    +
  • +
    + + + + client + +
    +
    +
    +
    +
    +
    +

    The client for this engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    weak var client: SocketEngineClient?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + closed + +
    +
    +
    +
    +
    +
    +

    true if this engine is closed.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var closed: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + connected + +
    +
    +
    +
    +
    +
    +

    true if this engine is connected. Connected means that the initial poll connect has succeeded.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var connected: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + connectParams + +
    +
    +
    +
    +
    +
    +

    The connect parameters sent during a connect.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var connectParams: [String: Any]?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + doubleEncodeUTF8 + +
    +
    +
    +
    +
    +
    +

    Set to true if using the node.js version of socket.io. The node.js version of socket.io +handles utf8 incorrectly.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var doubleEncodeUTF8: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + cookies + +
    +
    +
    +
    +
    +
    +

    An array of HTTPCookies that are sent during the connection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var cookies: [HTTPCookie]?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + engineQueue + +
    +
    +
    +
    +
    +
    +

    The queue that all engine actions take place on.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var engineQueue: DispatchQueue
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + extraHeaders + +
    +
    +
    +
    +
    +
    +

    A dictionary of extra http headers that will be set during connection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var extraHeaders: [String: String]?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + fastUpgrade + +
    +
    +
    +
    +
    +
    +

    When true, the engine is in the process of switching to WebSockets.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var fastUpgrade: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + forcePolling + +
    +
    +
    +
    +
    +
    +

    When true, the engine will only use HTTP long-polling as a transport.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var forcePolling: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + forceWebsockets + +
    +
    +
    +
    +
    +
    +

    When true, the engine will only use WebSockets as a transport.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var forceWebsockets: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + polling + +
    +
    +
    +
    +
    +
    +

    If true, the engine is currently in HTTP long-polling mode.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var polling: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + probing + +
    +
    +
    +
    +
    +
    +

    If true, the engine is currently seeing whether it can upgrade to WebSockets.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var probing: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + sid + +
    +
    +
    +
    +
    +
    +

    The session id for this engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var sid: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + socketPath + +
    +
    +
    +
    +
    +
    +

    The path to engine.io.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var socketPath: String
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + urlPolling + +
    +
    +
    +
    +
    +
    +

    The url for polling.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var urlPolling: URL
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + urlWebSocket + +
    +
    +
    +
    +
    +
    +

    The url for WebSockets.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var urlWebSocket: URL
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + websocket + +
    +
    +
    +
    +
    +
    +

    If true, then the engine is currently in WebSockets mode.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var websocket: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + ws + +
    +
    +
    +
    +
    +
    +

    The WebSocket for this engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var ws: WebSocket?
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Creates a new engine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    init(client: SocketEngineClient, url: URL, options: NSDictionary?)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + client + + +
    +

    The client for this engine.

    +
    +
    + + url + + +
    +

    The url for this engine.

    +
    +
    + + options + + +
    +

    The options for this engine.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + connect() + +
    +
    +
    +
    +
    +
    +

    Starts the connection to the server.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func connect()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + didError(reason:) + +
    +
    +
    +
    +
    +
    +

    Called when an error happens during execution. Causes a disconnection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didError(reason: String)
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + disconnect(reason:) + +
    +
    +
    +
    +
    +
    +

    Disconnects from the server.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func disconnect(reason: String)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + reason + + +
    +

    The reason for the disconnection. This is communicated up to the client.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + doFastUpgrade() + +
    +
    +
    +
    +
    +
    +

    Called to switch from HTTP long-polling to WebSockets. After calling this method the engine will be in +WebSocket mode.

    + +

    You shouldn’t call this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func doFastUpgrade()
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Causes any packets that were waiting for POSTing to be sent through the WebSocket. This happens because when +the engine is attempting to upgrade to WebSocket it does not do any POSTing.

    + +

    You shouldn’t call this directly

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func flushWaitingForPostToWebSocket()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + parseEngineData(_:) + +
    +
    +
    +
    +
    +
    +

    Parses raw binary received from engine.io.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func parseEngineData(_ data: Data)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + data + + +
    +

    The data to parse.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Parses a raw engine.io packet.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func parseEngineMessage(_ message: String, fromPolling: Bool)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + message + + +
    +

    The message to parse.

    +
    +
    + + fromPolling + + +
    +

    Whether this message is from long-polling. + If true we might have to fix utf8 encoding.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Writes a message to engine.io, independent of transport.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data])
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + msg + + +
    +

    The message to send.

    +
    +
    + + withType + + +
    +

    The type of this message.

    +
    +
    + + withData + + +
    +

    Any data that this message has.

    +
    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Protocols/SocketEngineWebsocket.html b/docs/Protocols/SocketEngineWebsocket.html new file mode 100644 index 0000000..c9a42a2 --- /dev/null +++ b/docs/Protocols/SocketEngineWebsocket.html @@ -0,0 +1,352 @@ + + + + SocketEngineWebsocket Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketEngineWebsocket

+
+
+
public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate
+ +
+
+

Protocol that is used to implement socket.io WebSocket support

+ +
+
+ +
+
+
+
    +
  • +
    + + + + sendWebSocketMessage(_:withType:withData:) + + + Default implementation + +
    +
    +
    +
    +
    +
    +

    Sends an engine.io message through the WebSocket transport.

    + +

    You shouldn’t call this directly, instead call the write method on SocketEngine.

    + +
    +

    Default Implementation

    +
    +

    Sends an engine.io message through the WebSocket transport.

    + +

    You shouldn’t call this directly, instead call the write method on SocketEngine.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data])
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + message + + +
    +

    The message to send.

    +
    +
    + + withType + + +
    +

    The type of message to send.

    +
    +
    + + withData + + +
    +

    The data associated with this message.

    +
    +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + websocketDidReceiveMessage(socket:text:) + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Delegate method for when a message is received.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func websocketDidReceiveMessage(socket: WebSocket, text: String)
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + websocketDidReceiveData(socket:data:) + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Delegate method for when binary is received.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func websocketDidReceiveData(socket: WebSocket, data: Data)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Protocols/SocketLogger.html b/docs/Protocols/SocketLogger.html new file mode 100644 index 0000000..2471000 --- /dev/null +++ b/docs/Protocols/SocketLogger.html @@ -0,0 +1,400 @@ + + + + SocketLogger Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketLogger

+
+
+
public protocol SocketLogger : class
+ +
+
+

Represents a class will log client events.

+ +
+
+ +
+
+
+ +
    +
  • +
    + + + + log + +
    +
    +
    +
    +
    +
    +

    Whether to log or not

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var log: Bool
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + log(_:type:args:) + + + Default implementation + +
    +
    +
    +
    +
    +
    +

    Normal log messages

    + +
    +

    Default Implementation

    +
    +

    Default implementation.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func log(_ message: String, type: String, args: Any...)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + message + + +
    +

    The message being logged. Can include %@ that will be replaced with args

    +
    +
    + + type + + +
    +

    The type of entity that called for logging.

    +
    +
    + + args + + +
    +

    Any args that should be inserted into the message. May be left out.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + error(_:type:args:) + + + Default implementation + +
    +
    +
    +
    +
    +
    +

    Error Messages

    + +
    +

    Default Implementation

    +
    +

    Default implementation.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func error(_ message: String, type: String, args: Any...)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + message + + +
    +

    The message being logged. Can include %@ that will be replaced with args

    +
    +
    + + type + + +
    +

    The type of entity that called for logging.

    +
    +
    + + args + + +
    +

    Any args that should be inserted into the message. May be left out.

    +
    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Protocols/WebSocketDelegate.html b/docs/Protocols/WebSocketDelegate.html new file mode 100644 index 0000000..8f64537 --- /dev/null +++ b/docs/Protocols/WebSocketDelegate.html @@ -0,0 +1,269 @@ + + + + WebSocketDelegate Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ + +
+ + + + diff --git a/docs/Protocols/WebSocketPongDelegate.html b/docs/Protocols/WebSocketPongDelegate.html new file mode 100644 index 0000000..13eba03 --- /dev/null +++ b/docs/Protocols/WebSocketPongDelegate.html @@ -0,0 +1,212 @@ + + + + WebSocketPongDelegate Protocol Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ + +
+ + + + diff --git a/docs/Structs.html b/docs/Structs.html new file mode 100644 index 0000000..2a904f0 --- /dev/null +++ b/docs/Structs.html @@ -0,0 +1,220 @@ + + + + Structs Reference + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

Structs

+

The following structs are available globally.

+ +
+
+ +
+
+
+ +
+
+
+ +
+
+ + + + diff --git a/docs/Structs/SocketIOClientConfiguration.html b/docs/Structs/SocketIOClientConfiguration.html new file mode 100644 index 0000000..705ceec --- /dev/null +++ b/docs/Structs/SocketIOClientConfiguration.html @@ -0,0 +1,647 @@ + + + + SocketIOClientConfiguration Struct Reference + + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

SocketIOClientConfiguration

+
+
+
public struct SocketIOClientConfiguration : ExpressibleByArrayLiteral, Collection, MutableCollection
+ +
+
+

An array-like type that holds SocketIOClientOptions

+ +
+
+ +
+
+
+ +
    +
  • +
    + + + + Iterator + +
    +
    +
    +
    +
    +
    +

    Iterator type.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias Iterator = Array<SocketIOClientOption>.Iterator
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Element + +
    +
    +
    +
    +
    +
    +

    Type of element stored.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias Element = SocketIOClientOption
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + SubSequence + +
    +
    +
    +
    +
    +
    +

    SubSequence type.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias SubSequence =  Array<SocketIOClientOption>.SubSequence
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Index + +
    +
    +
    +
    +
    +
    +

    Index type.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias Index = Array<SocketIOClientOption>.Index
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + startIndex + +
    +
    +
    +
    +
    +
    +

    The start index of this collection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var startIndex: Index
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + endIndex + +
    +
    +
    +
    +
    +
    +

    The end index of this collection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var endIndex: Index
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + isEmpty + +
    +
    +
    +
    +
    +
    +

    Whether this collection is empty.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var isEmpty: Bool
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + count + +
    +
    +
    +
    +
    +
    +

    The number of elements stored in this collection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var count: Index.Stride
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + first + +
    +
    +
    +
    +
    +
    +

    The first element in this collection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var first: Element?
    + +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + init(arrayLiteral:) + +
    +
    +
    +
    +
    +
    +

    Creates a new SocketIOClientConfiguration from an array literal.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(arrayLiteral elements: Element...)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + arrayLiteral + + +
    +

    The elements.

    +
    +
    +
    +
    +
    +
  • +
+
+
+ +
    +
  • +
    + + + + makeIterator() + +
    +
    +
    +
    +
    +
    +

    Creates an iterator for this collection.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func makeIterator() -> Iterator
    + +
    +
    +
    +

    Return Value

    +

    An iterator over this collection.

    +
    +
    +
    +
  • +
  • +
    + + + + index(after:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func index(after i: Index) -> Index
    + +
    +
    +
    +

    Return Value

    +

    The index after index.

    +
    +
    +
    +
  • +
  • +
    + + + + insert(_:replacing:) + +
    +
    +
    +
    +
    +
    +

    Special method that inserts element into the collection, replacing any other instances of element.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public mutating func insert(_ element: Element, replacing replace: Bool = true)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + element + + +
    +

    The element to insert.

    +
    +
    + + replacing + + +
    +

    Whether to replace any occurrences of element to the new item. Default is true.

    +
    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/Typealiases.html b/docs/Typealiases.html new file mode 100644 index 0000000..fcf1642 --- /dev/null +++ b/docs/Typealiases.html @@ -0,0 +1,246 @@ + + + + Typealiases Reference + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+

Typealiases

+

The following typealiases are available globally.

+ +
+
+ +
+
+
+
    +
  • +
    + + + + NormalCallback + +
    +
    +
    +
    +
    +
    +

    A typealias for a normal callback.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias NormalCallback = ([Any], SocketAckEmitter) -> Void
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + AckCallback + +
    +
    +
    +
    +
    +
    +

    A typealias for an ack callback.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias AckCallback = ([Any]) -> Void
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + + + diff --git a/docs/badge.svg b/docs/badge.svg new file mode 100644 index 0000000..8821c73 --- /dev/null +++ b/docs/badge.svg @@ -0,0 +1 @@ +documentationdocumentation84%84% \ No newline at end of file diff --git a/docs/css/highlight.css b/docs/css/highlight.css new file mode 100644 index 0000000..d0db0e1 --- /dev/null +++ b/docs/css/highlight.css @@ -0,0 +1,200 @@ +/* Credit to https://gist.github.com/wataru420/2048287 */ +.highlight { + /* Comment */ + /* Error */ + /* Keyword */ + /* Operator */ + /* Comment.Multiline */ + /* Comment.Preproc */ + /* Comment.Single */ + /* Comment.Special */ + /* Generic.Deleted */ + /* Generic.Deleted.Specific */ + /* Generic.Emph */ + /* Generic.Error */ + /* Generic.Heading */ + /* Generic.Inserted */ + /* Generic.Inserted.Specific */ + /* Generic.Output */ + /* Generic.Prompt */ + /* Generic.Strong */ + /* Generic.Subheading */ + /* Generic.Traceback */ + /* Keyword.Constant */ + /* Keyword.Declaration */ + /* Keyword.Pseudo */ + /* Keyword.Reserved */ + /* Keyword.Type */ + /* Literal.Number */ + /* Literal.String */ + /* Name.Attribute */ + /* Name.Builtin */ + /* Name.Class */ + /* Name.Constant */ + /* Name.Entity */ + /* Name.Exception */ + /* Name.Function */ + /* Name.Namespace */ + /* Name.Tag */ + /* Name.Variable */ + /* Operator.Word */ + /* Text.Whitespace */ + /* Literal.Number.Float */ + /* Literal.Number.Hex */ + /* Literal.Number.Integer */ + /* Literal.Number.Oct */ + /* Literal.String.Backtick */ + /* Literal.String.Char */ + /* Literal.String.Doc */ + /* Literal.String.Double */ + /* Literal.String.Escape */ + /* Literal.String.Heredoc */ + /* Literal.String.Interpol */ + /* Literal.String.Other */ + /* Literal.String.Regex */ + /* Literal.String.Single */ + /* Literal.String.Symbol */ + /* Name.Builtin.Pseudo */ + /* Name.Variable.Class */ + /* Name.Variable.Global */ + /* Name.Variable.Instance */ + /* Literal.Number.Integer.Long */ } + .highlight .c { + color: #999988; + font-style: italic; } + .highlight .err { + color: #a61717; + background-color: #e3d2d2; } + .highlight .k { + color: #000000; + font-weight: bold; } + .highlight .o { + color: #000000; + font-weight: bold; } + .highlight .cm { + color: #999988; + font-style: italic; } + .highlight .cp { + color: #999999; + font-weight: bold; } + .highlight .c1 { + color: #999988; + font-style: italic; } + .highlight .cs { + color: #999999; + font-weight: bold; + font-style: italic; } + .highlight .gd { + color: #000000; + background-color: #ffdddd; } + .highlight .gd .x { + color: #000000; + background-color: #ffaaaa; } + .highlight .ge { + color: #000000; + font-style: italic; } + .highlight .gr { + color: #aa0000; } + .highlight .gh { + color: #999999; } + .highlight .gi { + color: #000000; + background-color: #ddffdd; } + .highlight .gi .x { + color: #000000; + background-color: #aaffaa; } + .highlight .go { + color: #888888; } + .highlight .gp { + color: #555555; } + .highlight .gs { + font-weight: bold; } + .highlight .gu { + color: #aaaaaa; } + .highlight .gt { + color: #aa0000; } + .highlight .kc { + color: #000000; + font-weight: bold; } + .highlight .kd { + color: #000000; + font-weight: bold; } + .highlight .kp { + color: #000000; + font-weight: bold; } + .highlight .kr { + color: #000000; + font-weight: bold; } + .highlight .kt { + color: #445588; } + .highlight .m { + color: #009999; } + .highlight .s { + color: #d14; } + .highlight .na { + color: #008080; } + .highlight .nb { + color: #0086B3; } + .highlight .nc { + color: #445588; + font-weight: bold; } + .highlight .no { + color: #008080; } + .highlight .ni { + color: #800080; } + .highlight .ne { + color: #990000; + font-weight: bold; } + .highlight .nf { + color: #990000; } + .highlight .nn { + color: #555555; } + .highlight .nt { + color: #000080; } + .highlight .nv { + color: #008080; } + .highlight .ow { + color: #000000; + font-weight: bold; } + .highlight .w { + color: #bbbbbb; } + .highlight .mf { + color: #009999; } + .highlight .mh { + color: #009999; } + .highlight .mi { + color: #009999; } + .highlight .mo { + color: #009999; } + .highlight .sb { + color: #d14; } + .highlight .sc { + color: #d14; } + .highlight .sd { + color: #d14; } + .highlight .s2 { + color: #d14; } + .highlight .se { + color: #d14; } + .highlight .sh { + color: #d14; } + .highlight .si { + color: #d14; } + .highlight .sx { + color: #d14; } + .highlight .sr { + color: #009926; } + .highlight .s1 { + color: #d14; } + .highlight .ss { + color: #990073; } + .highlight .bp { + color: #999999; } + .highlight .vc { + color: #008080; } + .highlight .vg { + color: #008080; } + .highlight .vi { + color: #008080; } + .highlight .il { + color: #009999; } diff --git a/docs/css/jazzy.css b/docs/css/jazzy.css new file mode 100644 index 0000000..c83db5b --- /dev/null +++ b/docs/css/jazzy.css @@ -0,0 +1,368 @@ +*, *:before, *:after { + box-sizing: inherit; } + +body { + margin: 0; + background: #fff; + color: #333; + font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; + letter-spacing: .2px; + -webkit-font-smoothing: antialiased; + box-sizing: border-box; } + +h1 { + font-size: 2rem; + font-weight: 700; + margin: 1.275em 0 0.6em; } + +h2 { + font-size: 1.75rem; + font-weight: 700; + margin: 1.275em 0 0.3em; } + +h3 { + font-size: 1.5rem; + font-weight: 700; + margin: 1em 0 0.3em; } + +h4 { + font-size: 1.25rem; + font-weight: 700; + margin: 1.275em 0 0.85em; } + +h5 { + font-size: 1rem; + font-weight: 700; + margin: 1.275em 0 0.85em; } + +h6 { + font-size: 1rem; + font-weight: 700; + margin: 1.275em 0 0.85em; + color: #777; } + +p { + margin: 0 0 1em; } + +ul, ol { + padding: 0 0 0 2em; + margin: 0 0 0.85em; } + +blockquote { + margin: 0 0 0.85em; + padding: 0 15px; + color: #858585; + border-left: 4px solid #e5e5e5; } + +img { + max-width: 100%; } + +a { + color: #4183c4; + text-decoration: none; } + a:hover, a:focus { + outline: 0; + text-decoration: underline; } + +table { + background: #fff; + width: 100%; + border-collapse: collapse; + border-spacing: 0; + overflow: auto; + margin: 0 0 0.85em; } + +tr:nth-child(2n) { + background-color: #fbfbfb; } + +th, td { + padding: 6px 13px; + border: 1px solid #ddd; } + +pre { + margin: 0 0 1.275em; + padding: .85em 1em; + overflow: auto; + background: #f7f7f7; + font-size: .85em; + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } + +code { + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } + +p > code, li > code { + background: #f7f7f7; + padding: .2em; } + p > code:before, p > code:after, li > code:before, li > code:after { + letter-spacing: -.2em; + content: "\00a0"; } + +pre code { + padding: 0; + white-space: pre; } + +.content-wrapper { + display: flex; + flex-direction: column; } + @media (min-width: 768px) { + .content-wrapper { + flex-direction: row; } } + +.header { + display: flex; + padding: 8px; + font-size: 0.875em; + background: #444; + color: #999; } + +.header-col { + margin: 0; + padding: 0 8px; } + +.header-col--primary { + flex: 1; } + +.header-link { + color: #fff; } + +.header-icon { + padding-right: 6px; + vertical-align: -4px; + height: 16px; } + +.breadcrumbs { + font-size: 0.875em; + padding: 8px 16px; + margin: 0; + background: #fbfbfb; + border-bottom: 1px solid #ddd; } + +.carat { + height: 10px; + margin: 0 5px; } + +.navigation { + order: 2; } + @media (min-width: 768px) { + .navigation { + order: 1; + width: 25%; + max-width: 300px; + padding-bottom: 64px; + overflow: hidden; + word-wrap: normal; + background: #fbfbfb; + border-right: 1px solid #ddd; } } + +.nav-groups { + list-style-type: none; + padding-left: 0; } + +.nav-group-name { + border-bottom: 1px solid #ddd; + padding: 8px 0 8px 16px; } + +.nav-group-name-link { + color: #333; } + +.nav-group-tasks { + margin: 8px 0; + padding: 0 0 0 8px; } + +.nav-group-task { + font-size: 1em; + list-style-type: none; + white-space: nowrap; } + +.nav-group-task-link { + color: #808080; } + +.main-content { + order: 1; } + @media (min-width: 768px) { + .main-content { + order: 2; + flex: 1; + padding-bottom: 60px; } } + +.section { + padding: 0 32px; + border-bottom: 1px solid #ddd; } + +.section-content { + max-width: 834px; + margin: 0 auto; + padding: 16px 0; } + +.section-name { + color: #666; + display: block; } + +.declaration .highlight { + overflow-x: initial; + padding: 8px 0; + margin: 0; + background-color: transparent; + border: none; } + +.task-group-section { + border-top: 1px solid #ddd; } + +.task-group { + padding-top: 0px; } + +.task-name-container a[name]:before { + content: ""; + display: block; } + +.item-container { + padding: 0; } + +.item { + padding-top: 8px; + width: 100%; + list-style-type: none; } + .item a[name]:before { + content: ""; + display: block; } + .item .token { + padding-left: 3px; + margin-left: 0px; + font-size: 1rem; } + .item .declaration-note { + font-size: .85em; + color: #808080; + font-style: italic; } + +.pointer-container { + border-bottom: 1px solid #ddd; + left: -23px; + padding-bottom: 13px; + position: relative; + width: 110%; } + +.pointer { + left: 21px; + top: 7px; + display: block; + position: absolute; + width: 12px; + height: 12px; + border-left: 1px solid #ddd; + border-top: 1px solid #ddd; + background: #fff; + transform: rotate(45deg); } + +.height-container { + display: none; + position: relative; + width: 100%; + overflow: hidden; } + .height-container .section { + background: #fff; + border: 1px solid #ddd; + border-top-width: 0; + padding-top: 10px; + padding-bottom: 5px; + padding: 8px 16px; } + +.aside, .language { + padding: 6px 12px; + margin: 12px 0; + border-left: 5px solid #dddddd; + overflow-y: hidden; } + .aside .aside-title, .language .aside-title { + font-size: 9px; + letter-spacing: 2px; + text-transform: uppercase; + padding-bottom: 0; + margin: 0; + color: #aaa; + -webkit-user-select: none; } + .aside p:last-child, .language p:last-child { + margin-bottom: 0; } + +.language { + border-left: 5px solid #cde9f4; } + .language .aside-title { + color: #4183c4; } + +.aside-warning { + border-left: 5px solid #ff6666; } + .aside-warning .aside-title { + color: #ff0000; } + +.graybox { + border-collapse: collapse; + width: 100%; } + .graybox p { + margin: 0; + word-break: break-word; + min-width: 50px; } + .graybox td { + border: 1px solid #ddd; + padding: 5px 25px 5px 10px; + vertical-align: middle; } + .graybox tr td:first-of-type { + text-align: right; + padding: 7px; + vertical-align: top; + word-break: normal; + width: 40px; } + +.slightly-smaller { + font-size: 0.9em; } + +.footer { + padding: 8px 16px; + background: #444; + color: #ddd; + font-size: 0.8em; } + .footer p { + margin: 8px 0; } + .footer a { + color: #fff; } + +html.dash .header, html.dash .breadcrumbs, html.dash .navigation { + display: none; } +html.dash .height-container { + display: block; } + +form[role=search] input { + font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 24px; + padding: 0 10px; + margin: 0; + border: none; + border-radius: 1em; } + .loading form[role=search] input { + background: white url(../img/spinner.gif) center right 4px no-repeat; } +form[role=search] .tt-menu { + margin: 0; + min-width: 300px; + background: #fbfbfb; + color: #333; + border: 1px solid #ddd; } +form[role=search] .tt-highlight { + font-weight: bold; } +form[role=search] .tt-suggestion { + font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 0 8px; } + form[role=search] .tt-suggestion span { + display: table-cell; + white-space: nowrap; } + form[role=search] .tt-suggestion .doc-parent-name { + width: 100%; + text-align: right; + font-weight: normal; + font-size: 0.9em; + padding-left: 16px; } +form[role=search] .tt-suggestion:hover, +form[role=search] .tt-suggestion.tt-cursor { + cursor: pointer; + background-color: #4183c4; + color: #fff; } +form[role=search] .tt-suggestion:hover .doc-parent-name, +form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { + color: #fff; } diff --git a/docs/img/carat.png b/docs/img/carat.png new file mode 100755 index 0000000000000000000000000000000000000000..29d2f7fd4955fca6bc6fb740e0373a2c358c398e GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRo!3HEV4DF?Wlw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6JlqAi{-jv*Ddl5#RKJQ5NTUZgiPI4RUKGIKU?u8L&ndhX1t za+0CMVUnT(Gnb}ei=c~x==tMH^F1_tBocXwcoSWoO-SZY-o>!8%^=Bms)(~h;m_U( zXNixk28L}0LS5-jKyq@#2gyS|J&f#pGCLkTc<@2s1dqeyqJ*Rc0tSIETAgmODY;(s z2y|Mcp&2}7rpBprBBB~1qM1`N+}4SoxYVPqsXi&l`rxZp{(w0iSy$Nv5*Vy!RapG^ S^0y4=eg;ohKbLh*2~7a!Pg}VF literal 0 HcmV?d00001 diff --git a/docs/img/dash.png b/docs/img/dash.png new file mode 100755 index 0000000000000000000000000000000000000000..6f694c7a012b417908da3687a0a39aa182e91c74 GIT binary patch literal 1338 zcmaJ>U2NM_6t){^r>#wcfL0VSTvuX@)$vd4#5N6WVkc|1rR}naMb)(7I5(};#!el# zbtCASsp?W-qE8zSJoFVdA%-T$WL8RI_B? zd+t5o`T5Q{p6=<|U$?VqCxRe#u}(PwSIl{LRKstfSbPYV7pzFiI$~t4QN;vEC}X4n z7RxDpAOV!j*w8ni4MAK3S~6v&;)g`l$axh<$7|>E5RD*h?RH*K2Y`j8L7%1v@%vZi za7@bt@uOUvisvQJuXPqpaHQCkREqd6M>0WG?6AwXR*T65ziuw$&~q$MS$o zfPyh>s<0l}mI@eh_hd(oB8*1tHZ@ojWl%QM;T+Jdm>k66jW?rZ#Atx!qns4-g&E4v z(=;FQ%W^avW?3J{L@2IeV>_(Ca)Lk1vm70uX*$9Rewm8!AxRF0BcZTNSFka?U@5u^ zDtpMY2lVtCmQm<8@|YxHuf`Qs(;a!QQ=g4=WngL}AQLr> z9JWrdsBIHKHXF!fSydodRsaOc@jgNkSU^x9kY&;UP<}3pZ{joC5f_Tevd>4eG~;)Y z=eZ~qp=5#aaUn*E3OES^BApKTU&mCAU>iEyt^S9?)&v0^j*SWDqjRZr20>6rTPSJ& zlzz0f);`}+^~w}lP1PK7Ew3f7ot#*uJ@>1Yo3J0TdsRKpA+*n9JnDXDrM~YvF`;uS|vAh|-QdmRf4AqG=`U z#v1n_Lxg8;&z#YCU2K`_W{-A zUf_|V)B9U(WZ~PP>)O(JZ|Vc-*qP&Q{c~BE~6izDPQq)#Nu*KOf(n^(VHY9;fiINM65``pc+9*v(mL$bwfCjbc%v9V{8r9iX|O%>Nr%pLD2qT{mty}c=LVleeamv znz3SOSm@kP8jThvOOq(56Yzh*fz(booe!uZij=BJC6+_lbvQ~B8nA2>kXdv_RDtRY z`5QXWWEySCe6vbTs^#f?J!WC*{1~RgVx!nJTJjQyO{dRANgx|FnymtGbD9%JmCh9^y)##j7{Dcqfn*1ta$rG89pJF6w-S7Z037$rr|y0;1Onp_ zGFJdT6Q!1C0AdVB0WOmpuV=AgAQ550Tn+-mivTtYPJmz*#75#_n9oV%!#rSOfmAfy zki%C~=fTp1{O#BLpJ|0jj#m6#|LRWit-vq3PE1z9ZqyvET4sX$-Icqy7t z<=aq5ff86AuBZBu6EjJsYWM0uejufWFTwPA7Su}0Bm$7KFb!q{Um_8~A{LUG#1l(l zSehUda@kU8LIRg9fkk2tZ;~ss5~R+mM<==F7hLHpxqLB>>PQS%Vc7b~?q!%T5+h8Q z4G=4Nzyi5WZ?^gkasJ{?Xhm`JC#WG6$1K2jb@=9&D3EgD#3UhGh#*21rJjulVXjCF zvp76q62jt0zzMG5C7DlfMgPl%C^3+~wf|}Lq=}jz|MmIcQjh1Ok6NjD$Em^Iv26D> z8tt_TnM9~^Tt8mflRGPOrrX|HtT3gG4LEuuk{g2Rn}QgJIa?gZo))!!=o_l9bvD%A zZ`aHajl8#~u?!4f7F#*b*->A=R2L)6!>saz?h>#wTXT-I(XmQ zx{84skS>k=i~i`(6k4C7;Zpfx%dCPVjPayMf8pugtGM=~s=Id1l#8MZJ1-73wV#Q3 zR3>v3%}jbQs1f_Z0xo;%=LILlA+nTpKI4ha%xWW}uqHrNao~&T4AY6m`P$_n-6h*g zhoX+e4n%~gl_lhe#s+AMb7d{5WzvYTa%6Q~si@@4{;s(0zU|H&P3fE+t{7X`S#Cj@ zC#vd}^4pcBD*77Ny5=j$h8EL2_t$O38$SQiJ6fPjJMimypr~MB2(&P0aI|h}$64<0 z>_~duqNjaT=DM^6+N{&B_lED;F2wrl?!4Lk*2((x!fmrcsw+=cI^qttuZ9C}-m~5E z-ryYVpL%^xR#&(0YI5hz<(}F7-p)?FPcyJO-zVO>%9ZDXJH8pnY;GJYFDQ>vd#j_* zRrd}L(r=!g+1#nQwsO?kpS`Qq8`NxE+Zy{gf7*_7J*U2V_|NpLo{iasj7VCg_V9&| ShohtYzipXxh2)4xTkMB!bsTr6|ge_{#vAVj^!DyNA-l zJ&$jDFNv;BTZXX@Qk-7+S5ErF>mkOcZ@lQv>F1VyCEMe2Ud@f<|L%#&QJi${E`2lR zqKFaW2Y$aTRxUY&ae$IHsN;Z;rdZ%CjYLTv!tMi234j-ON=CnvK-1QU|MG$YErn{gHZ@0Q6&?xSyply?S$EVNXH;gp?S5kV2-)$ga^gw`(f4Mm_Y(`RbgRkQTHF2@zL}dCiLk$RoZIc{xZL z_J*d5)Kb;#oKCFyfL*NGSs?y;e(QKvPJe1#G)h5*6E(?L9$nt?UaQJfP^$GDL0PU; z?r}C|);JQ4HES3w5VMlY7x6xfJAzDKlHE~>x;D`Fa=WygYot{pfFehH69o9pK|72W zwC6?t^AnATIJa=kewn=ep?Nk(aZ*pZo}51`S=^)jPRb`~l^VE}08>P3OJtQlXx1K8 z8Q}_u=F*fS;=k=?(fIv#+%811NTx8^}rHwvH%LbYmpFl9p1A{Idh@2x$ zuVp7)VD9}Uc(*(C**!QOdS(6B)$5^Tq5p3q*7un&_Z-NKEiEYg$D{Uq&sa>wj|za5 zJ6M~p)z+E6*X${8j6Ci+sqZ}zxeCAo0gZmZuhl+)Q%1U$Br_`NXcA-3yBdYMha+{o z{?q0Q(kaR2n`M29{!pwpgX6+CPQEgIO%x*0#!TC=c-ZPSkLO>OcmQUao5%-3w)U`F zRz?uGCEKQDh!TQPDmyd;iDX$TkMIe)%61q51Y2b-ie4r00!csilXgKL$txqj|6D(# z@(#!nQ}3R1JGeB3B5Tuqdvyg@*!-bq`9`pmasNGvy9^*+cd1Y*g>HK#rl7i79QQAG zl4SL_wW@WY1d+F?j0gFInGhsRrqvV3SKl{oqW+;9!fu|u@J)h4WM!0Cu02l@p60b#5M9c{dKh=_eRw~yl zWT0gw8RePzf%i8X&twiB|LF0bI@CYE{x1PI;Ylr4RJzU#Zc0j!c07g&q7=_eSd(sH z9VKChd?}^52IKcMqolAWiQH;HSp1Ploa$t zQhg|2sK;%Eb!By`)j9G1w?>`Wt6IK3gB}~uoue(MlRiIoZ#d{pgJZ8b{^{HO8)@%= zX)og3`*D5v1g;*Lz8@Sm(Q|&}PUytlb@Q_dzKFOzKK!Z_&?GO4+JO-)iPH=fs{(`& zZ9{oNn~LUZaeN!>i9p*0N^sHye8nw4xSi!REaP@@^Jy66|)Y9_AFoLlrlkg(42 zVq2J??I(+1*BcSKsTyO7LCho{8tVQm1b>*GQ*H~Mn71Lhy`alw%;D@CU^0)5Ng{cHz@LS7QZ o8uGHYt7)tmZjae5ge5$b`e_;HIklOseoIbqeod19BU-8d00{dbSpWb4 literal 0 HcmV?d00001 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..0bf06d3 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,376 @@ + + + + SocketIO Reference + + + + + + + + + + + + + + + +
+

+ + SocketIO Docs + + (84% documented) +

+ +

+

+ +
+

+ + +
+ + + +
+ +
+ +
+
+ +

Build Status

+

Socket.IO-Client-Swift

+ +

Socket.IO-client for iOS/OS X.

+

Example

+
import SocketIO
+
+let socket = SocketIOClient(socketURL: URL(string: "http://localhost:8080")!, config: [.log(true), .forcePolling(true)])
+
+socket.on("connect") {data, ack in
+    print("socket connected")
+}
+
+socket.on("currentAmount") {data, ack in
+    if let cur = data[0] as? Double {
+        socket.emitWithAck("canUpdate", cur).timingOut(after: 0) {data in
+            socket.emit("update", ["amount": cur + 2.50])
+        }
+
+        ack.with("Got your currentAmount", "dude")
+    }
+}
+
+socket.connect()
+
+

Objective-C Example

+
@import SocketIO;
+NSURL* url = [[NSURL alloc] initWithString:@"http://localhost:8080"];
+SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @YES, @"forcePolling": @YES}];
+
+[socket on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) {
+    NSLog(@"socket connected");
+}];
+
+[socket on:@"currentAmount" callback:^(NSArray* data, SocketAckEmitter* ack) {
+    double cur = [[data objectAtIndex:0] floatValue];
+
+    [[socket emitWithAck:@"canUpdate" with:@[@(cur)]] timingOutAfter:0 callback:^(NSArray* data) {
+        [socket emit:@"update" withItems:@[@{@"amount": @(cur + 2.50)}]];
+    }];
+
+    [ack with:@[@"Got your currentAmount, ", @"dude"]];
+}];
+
+[socket connect];
+
+
+

Features

+ +
    +
  • Supports socket.io 1.0+
  • +
  • Supports binary
  • +
  • Supports Polling and WebSockets
  • +
  • Supports TLS/SSL
  • +
  • Can be used from Objective-C
  • +
+

Installation

+ +

Requires Swift 3/Xcode 8.x

+ +

If you need swift 2.3 use the swift2.3 tag (Pre-Swift 3 support is no longer maintained)

+ +

If you need swift 2.2 use 7.x (Pre-Swift 3 support is no longer maintained)

+ +

If you need Swift 2.1 use v5.5.0 (Pre-Swift 2.2 support is no longer maintained)

+ +

If you need Swift 1.2 use v2.4.5 (Pre-Swift 2 support is no longer maintained)

+ +

If you need Swift 1.1 use v1.5.2. (Pre-Swift 1.2 support is no longer maintained)

+

Manually (iOS 7+)

+ +
    +
  1. Copy the Source folder into your Xcode project. (Make sure you add the files to your target(s))
  2. +
  3. If you plan on using this from Objective-C, read this on exposing Swift code to Objective-C.
  4. +
+

Swift Package Manager

+ +

Add the project as a dependency to your Package.swift:

+
import PackageDescription
+
+let package = Package(
+    name: "YourSocketIOProject",
+    dependencies: [
+        .Package(url: "https://github.com/socketio/socket.io-client-swift", majorVersion: 8)
+    ]
+)
+
+ +

Then import import SocketIO.

+

Carthage

+ +

Add this line to your Cartfile:

+
github "socketio/socket.io-client-swift" ~> 8.3.3 # Or latest version
+
+ +

Run carthage update --platform ios,macosx.

+

CocoaPods 1.0.0 or later

+ +

Create Podfile and add pod 'Socket.IO-Client-Swift':

+
use_frameworks!
+
+target 'YourApp' do
+    pod 'Socket.IO-Client-Swift', '~> 8.3.3' # Or latest version
+end
+
+ +

Install pods:

+
$ pod install
+
+ +

Import the module:

+ +

Swift:

+
import SocketIO
+
+ +

Objective-C:

+
@import SocketIO;
+
+

CocoaSeeds

+ +

Add this line to your Seedfile:

+
github "socketio/socket.io-client-swift", "v8.3.3", :files => "Source/*.swift" # Or latest version
+
+ +

Run seed install.

+

API

+

Constructors

+ +

init(var socketURL: NSURL, config: SocketIOClientConfiguration = []) - Creates a new SocketIOClient. If your socket.io server is secure, you need to specify https in your socketURL.

+ +

convenience init(socketURL: NSURL, options: NSDictionary?) - Same as above, but meant for Objective-C. See Options on how convert between SocketIOClientOptions and dictionary keys.

+

Options

+ +

All options are a case of SocketIOClientOption. To get the Objective-C Option, convert the name to lowerCamelCase.

+
case connectParams([String: AnyObject]) // Dictionary whose contents will be passed with the connection.
+case cookies([NSHTTPCookie]) // An array of NSHTTPCookies. Passed during the handshake. Default is nil.
+case doubleEncodeUTF8(Bool) // Whether or not to double encode utf8. If using the node based server this should be true. Default is true.
+case extraHeaders([String: String]) // Adds custom headers to the initial request. Default is nil.
+case forcePolling(Bool) // `true` forces the client to use xhr-polling. Default is `false`
+case forceNew(Bool) // Will a create a new engine for each connect. Useful if you find a bug in the engine related to reconnects
+case forceWebsockets(Bool) // `true` forces the client to use WebSockets. Default is `false`
+case handleQueue(dispatch_queue_t) // The dispatch queue that handlers are run on. Default is the main queue.
+case log(Bool) // If `true` socket will log debug messages. Default is false.
+case logger(SocketLogger) // Custom logger that conforms to SocketLogger. Will use the default logging otherwise.
+case nsp(String) // The namespace to connect to. Must begin with /. Default is `/`
+case path(String) // If the server uses a custom path. ex: `"/swift/"`. Default is `""`
+case reconnects(Bool) // Whether to reconnect on server lose. Default is `true`
+case reconnectAttempts(Int) // How many times to reconnect. Default is `-1` (infinite tries)
+case reconnectWait(Int) // Amount of time to wait between reconnects. Default is `10`
+case sessionDelegate(NSURLSessionDelegate) // Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs. Default is nil.
+case secure(Bool) // If the connection should use TLS. Default is false.
+case security(SSLSecurity) // Allows you to set which certs are valid. Useful for SSL pinning.
+case selfSigned(Bool) // Sets WebSocket.selfSignedSSL. Use this if you're using self-signed certs.
+case voipEnabled(Bool) // Only use this option if you're using the client with VoIP services. Changes the way the WebSocket is created. Default is false
+
+

Methods

+ +
    +
  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. +
  3. once(_ event: String, callback: NormalCallback) -> NSUUID - Adds a handler that will only be executed once. Returns a unique id for the handler.
  4. +
  5. onAny(callback:((event: String, items: AnyObject?)) -> Void) - Adds a handler for all events. It will be called on any received event.
  6. +
  7. emit(_ event: String, _ items: AnyObject...) - Sends a message. Can send multiple items.
  8. +
  9. emit(_ event: String, withItems items: [AnyObject]) - emit for Objective-C
  10. +
  11. emitWithAck(_ event: String, _ items: AnyObject...) -> OnAckCallback - Sends a message that requests an acknowledgement from the server. Returns an object which you can use to add a handler. See example. Note: The message is not sent until you call timingOut(after:) on the returned object.
  12. +
  13. emitWithAck(_ event: String, withItems items: [AnyObject]) -> OnAckCallback - emitWithAck for Objective-C. Note: The message is not sent until you call timingOutAfter on the returned object.
  14. +
  15. connect() - Establishes a connection to the server. A connect event is fired upon successful connection.
  16. +
  17. connect(timeoutAfter timeoutAfter: Int, withTimeoutHandler handler: (() -> Void)?) - Connect to the server. If it isn’t connected after timeoutAfter seconds, the handler is called.
  18. +
  19. disconnect() - Closes the socket. Reopening a disconnected socket is not fully tested.
  20. +
  21. reconnect() - Causes the client to reconnect to the server.
  22. +
  23. joinNamespace(_ namespace: String) - Causes the client to join namespace. Shouldn’t need to be called unless you change namespaces manually.
  24. +
  25. leaveNamespace() - Causes the client to leave the nsp and go back to /
  26. +
  27. off(_ event: String) - Removes all event handlers for event.
  28. +
  29. off(id id: NSUUID) - Removes the event that corresponds to id.
  30. +
  31. removeAllHandlers() - Removes all handlers.
  32. +
+

Client Events

+ +
    +
  1. connect - Emitted when on a successful connection.
  2. +
  3. disconnect - Emitted when the connection is closed.
  4. +
  5. error - Emitted on an error.
  6. +
  7. reconnect - Emitted when the connection is starting to reconnect.
  8. +
  9. reconnectAttempt - Emitted when attempting to reconnect.
  10. +
+

Detailed Example

+ +

A more detailed example can be found here

+ +

An example using the Swift Package Manager can be found here

+

License

+ +

MIT

+ +
+
+ + +
+
+ + + + diff --git a/docs/js/jazzy.js b/docs/js/jazzy.js new file mode 100755 index 0000000..009c80d --- /dev/null +++ b/docs/js/jazzy.js @@ -0,0 +1,43 @@ +window.jazzy = {'docset': false} +if (typeof window.dash != 'undefined') { + document.documentElement.className += ' dash' + window.jazzy.docset = true +} +if (navigator.userAgent.match(/xcode/i)) { + document.documentElement.className += ' xcode' + window.jazzy.docset = true +} + +// On doc load, toggle the URL hash discussion if present +$(document).ready(function() { + if (!window.jazzy.docset) { + var linkToHash = $('a[href="' + window.location.hash +'"]'); + linkToHash.trigger("click"); + } +}); + +// On token click, toggle its discussion and animate token.marginLeft +$(".token").click(function(event) { + if (window.jazzy.docset) { + return; + } + var link = $(this); + var animationDuration = 300; + $content = link.parent().parent().next(); + $content.slideToggle(animationDuration); + + // Keeps the document from jumping to the hash. + var href = $(this).attr('href'); + if (history.pushState) { + history.pushState({}, '', href); + } else { + location.hash = href; + } + event.preventDefault(); +}); + +// Dumb down quotes within code blocks that delimit strings instead of quotations +// https://github.com/realm/jazzy/issues/714 +$("code q").replaceWith(function () { + return ["\"", $(this).contents(), "\""]; +}); diff --git a/docs/js/jazzy.search.js b/docs/js/jazzy.search.js new file mode 100644 index 0000000..54be83c --- /dev/null +++ b/docs/js/jazzy.search.js @@ -0,0 +1,62 @@ +$(function(){ + var searchIndex = lunr(function() { + this.ref('url'); + this.field('name'); + }); + + var $typeahead = $('[data-typeahead]'); + var $form = $typeahead.parents('form'); + var searchURL = $form.attr('action'); + + function displayTemplate(result) { + return result.name; + } + + function suggestionTemplate(result) { + var t = '
'; + t += '' + result.name + ''; + if (result.parent_name) { + t += '' + result.parent_name + ''; + } + t += '
'; + return t; + } + + $typeahead.one('focus', function() { + $form.addClass('loading'); + + $.getJSON(searchURL).then(function(searchData) { + $.each(searchData, function (url, doc) { + searchIndex.add({url: url, name: doc.name}); + }); + + $typeahead.typeahead( + { + highlight: true, + minLength: 3 + }, + { + limit: 10, + display: displayTemplate, + templates: { suggestion: suggestionTemplate }, + source: function(query, sync) { + var results = searchIndex.search(query).map(function(result) { + var doc = searchData[result.ref]; + doc.url = result.ref; + return doc; + }); + sync(results); + } + } + ); + $form.removeClass('loading'); + $typeahead.trigger('focus'); + }); + }); + + var baseURL = searchURL.slice(0, -"search.json".length); + + $typeahead.on('typeahead:select', function(e, result) { + window.location = baseURL + result.url; + }); +}); diff --git a/docs/js/jquery.min.js b/docs/js/jquery.min.js new file mode 100755 index 0000000..ab28a24 --- /dev/null +++ b/docs/js/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; +if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("