even more type safe solution, idea from @lightsprint09

This commit is contained in:
Erik 2015-10-18 14:52:46 -04:00
parent a5db43b834
commit b9e05286a2
4 changed files with 138 additions and 67 deletions

View File

@ -32,7 +32,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient {
public private(set) var status = SocketIOClientStatus.NotConnected public private(set) var status = SocketIOClientStatus.NotConnected
public var nsp = "/" public var nsp = "/"
public var opts: SocketOptionsDictionary? public var opts: SocketOptionsSet?
public var reconnects = true public var reconnects = true
public var reconnectWait = 10 public var reconnectWait = 10
public var sid: String? { public var sid: String? {
@ -40,9 +40,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient {
} }
private let emitQueue = dispatch_queue_create("com.socketio.emitQueue", DISPATCH_QUEUE_SERIAL) private let emitQueue = dispatch_queue_create("com.socketio.emitQueue", DISPATCH_QUEUE_SERIAL)
private let handleQueue: dispatch_queue_t!
private let logType = "SocketIOClient" private let logType = "SocketIOClient"
private let reconnectAttempts: Int!
private var anyHandler: ((SocketAnyEvent) -> Void)? private var anyHandler: ((SocketAnyEvent) -> Void)?
private var currentReconnectAttempt = 0 private var currentReconnectAttempt = 0
@ -52,12 +50,14 @@ public final class SocketIOClient: NSObject, SocketEngineClient {
private var ackHandlers = SocketAckManager() private var ackHandlers = SocketAckManager()
private(set) var currentAck = -1 private(set) var currentAck = -1
private(set) var handleQueue = dispatch_get_main_queue()
private(set) var reconnectAttempts = -1
var waitingData = [SocketPacket]() var waitingData = [SocketPacket]()
/** /**
Type safe way to create a new SocketIOClient. opts can be omitted Type safe way to create a new SocketIOClient. opts can be omitted
*/ */
public init(var socketURL: String, opts: SocketOptionsDictionary? = nil) { public init(var socketURL: String, opts: SocketOptionsSet? = nil) {
if socketURL["https://"].matches().count != 0 { if socketURL["https://"].matches().count != 0 {
self.secure = true self.secure = true
} }
@ -68,40 +68,27 @@ public final class SocketIOClient: NSObject, SocketEngineClient {
self.socketURL = socketURL self.socketURL = socketURL
self.opts = opts self.opts = opts
if let connectParams = opts?[.ConnectParams] as? [String: AnyObject] { for option in opts ?? [] {
self.connectParams = connectParams switch option {
} case .ConnectParams(let params):
connectParams = params
if let logger = opts?[.Logger] as? SocketLogger { case .Reconnects(let reconnects):
Logger = logger self.reconnects = reconnects
} case .ReconnectAttempts(let attempts):
reconnectAttempts = attempts
if let log = opts?[.Log] as? Bool { case .ReconnectWait(let wait):
Logger.log = log reconnectWait = wait
} case .Nsp(let nsp):
self.nsp = nsp
if let nsp = opts?[.Nsp] as? String { case .Log(let log):
self.nsp = nsp Logger.log = log
} case .Logger(let logger):
Logger = logger
if let reconnects = opts?[.Reconnects] as? Bool { case .HandleQueue(let queue):
self.reconnects = reconnects handleQueue = queue
} default:
continue
if let reconnectAttempts = opts?[.ReconnectAttempts] as? Int { }
self.reconnectAttempts = reconnectAttempts
} else {
self.reconnectAttempts = -1
}
if let reconnectWait = opts?[.ReconnectWait] as? Int {
self.reconnectWait = abs(reconnectWait)
}
if let handleQueue = opts?[.HandleQueue] as? dispatch_queue_t {
self.handleQueue = handleQueue
} else {
self.handleQueue = dispatch_get_main_queue()
} }
super.init() super.init()
@ -113,7 +100,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient {
*/ */
public convenience init(socketURL: String, opts: NSDictionary?) { public convenience init(socketURL: String, opts: NSDictionary?) {
self.init(socketURL: socketURL, self.init(socketURL: socketURL,
opts: SocketIOClientOptions.NSDictionaryToSocketOptionsDictionary(opts ?? [:])) opts: SocketIOClientOption.NSDictionaryToSocketOptionsSet(opts ?? [:]))
} }
deinit { deinit {
@ -124,7 +111,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient {
Logger.log("Adding engine", type: logType) Logger.log("Adding engine", type: logType)
let newEngine = SocketEngine(client: self, opts: let newEngine = SocketEngine(client: self, opts:
SocketIOClientOptions.SocketOptionsDictionaryToNSDictionary(opts ?? [:])) SocketIOClientOption.SocketOptionsSetToNSDictionary(opts ?? []))
engine = newEngine engine = newEngine
return newEngine return newEngine

View File

@ -1,5 +1,5 @@
// //
// SocketIOClientOptions .swift // SocketIOClientOption .swift
// Socket.IO-Client-Swift // Socket.IO-Client-Swift
// //
// Created by Erik Little on 10/17/15. // Created by Erik Little on 10/17/15.
@ -24,41 +24,125 @@
import Foundation import Foundation
public enum SocketIOClientOptions: String { public enum SocketIOClientOption: CustomStringConvertible, Hashable {
case ConnectParams = "connectParams" case ConnectParams([String: AnyObject])
case Reconnects = "reconnects" case Reconnects(Bool)
case ReconnectAttempts = "reconnectAttempts" case ReconnectAttempts(Int)
case ReconnectWait = "reconnectWait" case ReconnectWait(Int)
case ForcePolling = "forcePolling" case ForcePolling(Bool)
case ForceWebsockets = "forceWebsockets" case ForceWebsockets(Bool)
case Nsp = "nsp" case Nsp(String)
case Cookies = "cookies" case Cookies([NSHTTPCookie])
case Log = "log" case Log(Bool)
case Logger = "logger" case Logger(SocketLogger)
case SessionDelegate = "sessionDelegate" case SessionDelegate(NSURLSessionDelegate)
case Path = "path" case Path(String)
case ExtraHeaders = "extraHeaders" case ExtraHeaders([String: String])
case HandleQueue = "handleQueue" case HandleQueue(dispatch_queue_t)
static func NSDictionaryToSocketOptionsDictionary(dict: NSDictionary) -> SocketOptionsDictionary { public var description: String {
var options = SocketOptionsDictionary() switch self {
case .ConnectParams:
return "connectParams"
case .Reconnects:
return "reconnects"
case .ReconnectAttempts:
return "reconnectAttempts"
case .ReconnectWait:
return "reconnectWait"
case .ForcePolling:
return "forcePolling"
case .ForceWebsockets:
return "forceWebsockets"
case .Nsp:
return "nsp"
case .Cookies:
return "cookies"
case .Log:
return "log"
case .Logger:
return "logger"
case .SessionDelegate:
return "sessionDelegate"
case .Path:
return "path"
case .ExtraHeaders:
return "extraHeaders"
case .HandleQueue:
return "handleQueue"
}
}
public var hashValue: Int {
return description.hashValue
}
static func keyValueToSocketIOClientOption(key: String, value: AnyObject) -> SocketIOClientOption? {
switch key {
case "connectParams" where value is [String: AnyObject]:
return .ConnectParams(value as! [String: AnyObject])
case "reconnects" where value is Bool:
return .Reconnects(value as! Bool)
case "reconnectAttempts" where value is Int:
return .ReconnectAttempts(value as! Int)
case "reconnectWait" where value is Int:
return .ReconnectWait(value as! Int)
case "forcePolling" where value is Bool:
return .ForcePolling(value as! Bool)
case "forceWebsockets" where value is Bool:
return .ForceWebsockets(value as! Bool)
case "nsp" where value is String:
return .Nsp(value as! String)
case "cookies" where value is [NSHTTPCookie]:
return .Cookies(value as! [NSHTTPCookie])
case "log" where value is Bool:
return .Log(value as! Bool)
case "logger" where value is SocketLogger:
return .Logger(value as! SocketLogger)
case "sessionDelegate" where value is NSURLSessionDelegate:
return .SessionDelegate(value as! NSURLSessionDelegate)
case "path" where value is String:
return .Path(value as! String)
case "extraHeaders" where value is [String: String]:
return .ExtraHeaders(value as! [String: String])
case "handleQueue" where value is dispatch_queue_t:
return .HandleQueue(value as! dispatch_queue_t)
default:
return nil
}
}
static func getSocketIOOptionValue(option: SocketIOClientOption) -> AnyObject? {
if let value = Mirror(reflecting: option).children.first!.value as? AnyObject {
return value
} else {
return nil
}
}
static func NSDictionaryToSocketOptionsSet(dict: NSDictionary) -> SocketOptionsSet {
var options = SocketOptionsSet()
for (rawKey, value) in dict { for (rawKey, value) in dict {
if let key = rawKey as? String, opt = SocketIOClientOptions(rawValue: key) { if let key = rawKey as? String, opt = keyValueToSocketIOClientOption(key, value: value) {
options[opt] = value options.insert(opt)
} }
} }
return options return options
} }
static func SocketOptionsDictionaryToNSDictionary(dict: SocketOptionsDictionary) -> NSDictionary { static func SocketOptionsSetToNSDictionary(set: SocketOptionsSet) -> NSDictionary {
let options = NSMutableDictionary() let options = NSMutableDictionary()
for (key, value) in dict { for option in set {
options[key.rawValue] = value options[option.description] = getSocketIOOptionValue(option)
} }
return options return options
} }
} }
public func ==(lhs: SocketIOClientOption, rhs: SocketIOClientOption) -> Bool {
return lhs.description == rhs.description
}

View File

@ -26,7 +26,7 @@ import Foundation
var Logger: SocketLogger = DefaultSocketLogger() var Logger: SocketLogger = DefaultSocketLogger()
public protocol SocketLogger { public protocol SocketLogger: class {
/// Whether to log or not /// Whether to log or not
var log: Bool {get set} var log: Bool {get set}
@ -56,6 +56,6 @@ public extension SocketLogger {
} }
} }
struct DefaultSocketLogger: SocketLogger { class DefaultSocketLogger: SocketLogger {
var log = false var log = false
} }

View File

@ -27,7 +27,7 @@ import Foundation
public typealias AckCallback = ([AnyObject]) -> Void public typealias AckCallback = ([AnyObject]) -> Void
public typealias NormalCallback = ([AnyObject], SocketAckEmitter?) -> Void public typealias NormalCallback = ([AnyObject], SocketAckEmitter?) -> Void
public typealias OnAckCallback = (timeoutAfter: UInt64, callback: AckCallback) -> Void public typealias OnAckCallback = (timeoutAfter: UInt64, callback: AckCallback) -> Void
public typealias SocketOptionsDictionary = [SocketIOClientOptions: AnyObject] public typealias SocketOptionsSet = Set<SocketIOClientOption>
enum Either<E, V> { enum Either<E, V> {
case Left(E) case Left(E)