merge master
This commit is contained in:
commit
a17f2b6e7a
@ -11,7 +11,7 @@ socket.on("connect") {data, ack in
|
||||
|
||||
socket.on("currentAmount") {data, ack in
|
||||
if let cur = data?[0] as? Double {
|
||||
socket.emitWithAck("canUpdate", cur).onAck(0) {data in
|
||||
socket.emitWithAck("canUpdate", cur)(timeout: 0) {data in
|
||||
socket.emit("update", ["amount": cur + 2.50])
|
||||
}
|
||||
|
||||
@ -30,9 +30,9 @@ SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:@"localhost:8
|
||||
[socket on: @"connect" callback: ^(NSArray* data, void (^ack)(NSArray*)) {
|
||||
NSLog(@"connected");
|
||||
[socket emitObjc:@"echo" withItems:@[@"echo test"]];
|
||||
[[socket emitWithAckObjc:@"ackack" withItems:@[@"test"]] onAck:0 withCallback:^(NSArray* data) {
|
||||
NSLog(@"Got data");
|
||||
}];
|
||||
[socket emitWithAckObjc:@"ackack" withItems:@[@1]](10, ^(NSArray* data) {
|
||||
NSLog(@"Got ack");
|
||||
});
|
||||
}];
|
||||
|
||||
```
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "Socket.IO-Client-Swift"
|
||||
s.version = "1.4.4"
|
||||
s.version = "1.5.0"
|
||||
s.summary = "Socket.IO-client for Swift"
|
||||
s.description = <<-DESC
|
||||
Socket.IO-client for Swift.
|
||||
@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
||||
s.author = { "Erik" => "nuclear.ace@gmail.com" }
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.osx.deployment_target = '10.10'
|
||||
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v1.4.4' }
|
||||
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v1.5.0' }
|
||||
s.source_files = "SwiftIO/**/*.swift"
|
||||
s.requires_arc = true
|
||||
# s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
//
|
||||
// SocketAckHandler.swift
|
||||
// Socket.IO-Swift
|
||||
// SocketAckMap.swift
|
||||
// SocketIO-Swift
|
||||
//
|
||||
// Created by Erik Little on 4/3/15.
|
||||
//
|
||||
// Created by Erik Little on 2/14/15.
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
@ -25,45 +25,35 @@
|
||||
import Foundation
|
||||
|
||||
public typealias AckCallback = (NSArray?) -> Void
|
||||
public typealias OnAckCallback = (timeout:UInt64, callback:AckCallback) -> Void
|
||||
|
||||
@objc public class SocketAckHandler {
|
||||
let ackNum:Int!
|
||||
let event:String!
|
||||
var acked = false
|
||||
var callback:AckCallback?
|
||||
weak var socket:SocketIOClient?
|
||||
struct SocketAckMap {
|
||||
private var acks = [Int: AckCallback]()
|
||||
private var waiting = [Int: Bool]()
|
||||
|
||||
|
||||
init(event:String, ackNum:Int = 0, socket:SocketIOClient) {
|
||||
self.ackNum = ackNum
|
||||
self.event = event
|
||||
self.socket = socket
|
||||
mutating func addAck(ack:Int, callback:AckCallback) {
|
||||
waiting[ack] = true
|
||||
acks[ack] = callback
|
||||
}
|
||||
|
||||
public func onAck(timeout:UInt64, withCallback callback:AckCallback) {
|
||||
self.callback = callback
|
||||
mutating func executeAck(ack:Int, items:[AnyObject]?) {
|
||||
let callback = acks[ack]
|
||||
waiting[ack] = false
|
||||
|
||||
|
||||
if timeout != 0 {
|
||||
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeout * NSEC_PER_SEC))
|
||||
dispatch_after(time, dispatch_get_main_queue()) {[weak self] in
|
||||
if self == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !self!.acked {
|
||||
self?.executeAck(["No ACK"])
|
||||
self?.socket?.removeAck(self!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func executeAck(data:NSArray?) {
|
||||
dispatch_async(dispatch_get_main_queue()) {[weak self, cb = self.callback] in
|
||||
self?.acked = true
|
||||
cb?(data)
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
callback?(items)
|
||||
return
|
||||
}
|
||||
|
||||
acks.removeValueForKey(ack)
|
||||
}
|
||||
|
||||
mutating func timeoutAck(ack:Int) {
|
||||
if waiting[ack] != nil && waiting[ack]! {
|
||||
acks[ack]?(["NO ACK"])
|
||||
}
|
||||
|
||||
acks.removeValueForKey(ack)
|
||||
waiting.removeValueForKey(ack)
|
||||
}
|
||||
}
|
||||
@ -175,6 +175,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
self._websocket = true
|
||||
self._polling = false
|
||||
self.fastUpgrade = false
|
||||
self.probing = false
|
||||
self.flushProbeWait()
|
||||
}
|
||||
|
||||
@ -229,7 +230,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
}
|
||||
|
||||
private func flushProbeWait() {
|
||||
// println("flushing probe wait")
|
||||
// NSLog("flushing probe wait")
|
||||
dispatch_async(self.emitQueue) {[weak self] in
|
||||
if self == nil {
|
||||
return
|
||||
@ -240,6 +241,10 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
}
|
||||
|
||||
self?.probeWait.removeAll(keepCapacity: false)
|
||||
|
||||
if self?.postWait.count != 0 {
|
||||
self?.flushWaitingForPostToWebSocket()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,11 +274,14 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
let postData = postStr.dataUsingEncoding(NSUTF8StringEncoding,
|
||||
allowLossyConversion: false)!
|
||||
|
||||
// NSLog("posting: \(postStr)")
|
||||
req.HTTPBody = postData
|
||||
req.setValue(String(postData.length), forHTTPHeaderField: "Content-Length")
|
||||
|
||||
self.waitingForPost = true
|
||||
|
||||
// NSLog("posting: \(postStr)")
|
||||
// NSLog("Posting with WS status of: \(self.websocket)")
|
||||
|
||||
self.session.dataTaskWithRequest(req) {[weak self] data, res, err in
|
||||
if self == nil {
|
||||
return
|
||||
@ -284,9 +292,13 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
|
||||
self?.waitingForPost = false
|
||||
dispatch_async(self!.emitQueue) {
|
||||
self?.flushWaitingForPost()
|
||||
self?.doPoll()
|
||||
return
|
||||
if self!.fastUpgrade {
|
||||
self?.doFastUpgrade()
|
||||
return
|
||||
} else {
|
||||
self?.flushWaitingForPost()
|
||||
self?.doPoll()
|
||||
}
|
||||
}}.resume()
|
||||
}
|
||||
|
||||
@ -518,6 +530,8 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
self.write("", withType: PacketType.PING, withData: nil)
|
||||
}
|
||||
|
||||
/// Send polling message.
|
||||
/// Only call on emitQueue
|
||||
private func sendPollMessage(var msg:String, withType type:PacketType,
|
||||
datas:ContiguousArray<NSData>? = nil) {
|
||||
// println("Sending poll: \(msg) as type: \(type.rawValue)")
|
||||
@ -539,6 +553,8 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/// Send message on WebSockets
|
||||
/// Only call on emitQueue
|
||||
private func sendWebSocketMessage(str:String, withType type:PacketType,
|
||||
datas:ContiguousArray<NSData>? = nil) {
|
||||
// println("Sending ws: \(str) as type: \(type.rawValue)")
|
||||
@ -570,9 +586,9 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
||||
|
||||
private func upgradeTransport() {
|
||||
if self.websocketConnected {
|
||||
// NSLog("Doing fast upgrade")
|
||||
// Do a fast upgrade
|
||||
self.fastUpgrade = true
|
||||
self.probing = false
|
||||
self.sendPollMessage("", withType: PacketType.NOOP)
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,9 +25,7 @@
|
||||
import Foundation
|
||||
|
||||
public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
let reconnectAttempts:Int!
|
||||
private lazy var params = [String: AnyObject]()
|
||||
private var ackHandlers = ContiguousArray<SocketAckHandler>()
|
||||
private var anyHandler:((SocketAnyEvent) -> Void)?
|
||||
private var _closed = false
|
||||
private var _connected = false
|
||||
@ -42,14 +40,15 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
private var _reconnecting = false
|
||||
private var reconnectTimer:NSTimer?
|
||||
|
||||
let reconnectAttempts:Int!
|
||||
var ackHandlers = SocketAckMap()
|
||||
var currentAck = -1
|
||||
var waitingData = ContiguousArray<SocketPacket>()
|
||||
|
||||
public let socketURL:String
|
||||
public let handleQueue = dispatch_queue_create("handleQueue".cStringUsingEncoding(NSUTF8StringEncoding),
|
||||
DISPATCH_QUEUE_SERIAL)
|
||||
public let emitQueue = dispatch_queue_create("emitQueue".cStringUsingEncoding(NSUTF8StringEncoding),
|
||||
DISPATCH_QUEUE_SERIAL)
|
||||
public let handleAckQueue = dispatch_queue_create("handleAckQueue", DISPATCH_QUEUE_SERIAL)
|
||||
public let handleQueue = dispatch_queue_create("handleQueue", DISPATCH_QUEUE_SERIAL)
|
||||
public let emitQueue = dispatch_queue_create("emitQueue", DISPATCH_QUEUE_SERIAL)
|
||||
public var closed:Bool {
|
||||
return self._closed
|
||||
}
|
||||
@ -89,6 +88,26 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
|
||||
// Set options
|
||||
if opts != nil {
|
||||
if let cookies = opts!["cookies"] as? [NSHTTPCookie] {
|
||||
self.cookies = cookies
|
||||
}
|
||||
|
||||
if let polling = opts!["forcePolling"] as? Bool {
|
||||
self.forcePolling = polling
|
||||
}
|
||||
|
||||
if let ws = opts!["forceWebsockets"] as? Bool {
|
||||
self.forceWebsockets = ws
|
||||
}
|
||||
|
||||
if var nsp = opts!["nsp"] as? String {
|
||||
if nsp != "/" && nsp.hasPrefix("/") {
|
||||
nsp.removeAtIndex(nsp.startIndex)
|
||||
}
|
||||
|
||||
self.nsp = nsp
|
||||
}
|
||||
|
||||
if let reconnects = opts!["reconnects"] as? Bool {
|
||||
self.reconnects = reconnects
|
||||
}
|
||||
@ -102,26 +121,6 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
if let reconnectWait = opts!["reconnectWait"] as? Int {
|
||||
self.reconnectWait = abs(reconnectWait)
|
||||
}
|
||||
|
||||
if var nsp = opts!["nsp"] as? String {
|
||||
if nsp != "/" && nsp.hasPrefix("/") {
|
||||
nsp.removeAtIndex(nsp.startIndex)
|
||||
}
|
||||
|
||||
self.nsp = nsp
|
||||
}
|
||||
|
||||
if let polling = opts!["forcePolling"] as? Bool {
|
||||
self.forcePolling = polling
|
||||
}
|
||||
|
||||
if let ws = opts!["forceWebsockets"] as? Bool {
|
||||
self.forceWebsockets = ws
|
||||
}
|
||||
|
||||
if let cookies = opts!["cookies"] as? [NSHTTPCookie] {
|
||||
self.cookies = cookies
|
||||
}
|
||||
} else {
|
||||
self.reconnectAttempts = -1
|
||||
}
|
||||
@ -190,6 +189,29 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
self.engine?.open(opts: params)
|
||||
}
|
||||
|
||||
private func createOnAck(event:String, items:[AnyObject]) -> OnAckCallback {
|
||||
return {[weak self, ack = ++self.currentAck] timeout, callback in
|
||||
if self == nil {
|
||||
return
|
||||
}
|
||||
|
||||
self?.ackHandlers.addAck(ack, callback)
|
||||
|
||||
dispatch_async(self!.emitQueue) {
|
||||
self?._emit(event, items, ack: ack)
|
||||
return
|
||||
}
|
||||
|
||||
if timeout != 0 {
|
||||
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeout * NSEC_PER_SEC))
|
||||
dispatch_after(time, dispatch_get_main_queue()) {
|
||||
self?.ackHandlers.timeoutAck(ack)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func didConnect() {
|
||||
self._closed = false
|
||||
self._connected = true
|
||||
@ -219,6 +241,13 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
self.handleEvent("disconnect", data: [reason], isInternalMessage: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Same as close
|
||||
*/
|
||||
public func disconnect(#fast:Bool) {
|
||||
self.close(fast: fast)
|
||||
}
|
||||
|
||||
/**
|
||||
Send a message to the server
|
||||
*/
|
||||
@ -251,43 +280,23 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
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:AnyObject...) -> SocketAckHandler {
|
||||
public func emitWithAck(event:String, _ items:AnyObject...) -> OnAckCallback {
|
||||
if !self.connected {
|
||||
return SocketAckHandler(event: "fail", socket: self)
|
||||
return createOnAck(event, items: items)
|
||||
}
|
||||
|
||||
self.currentAck++
|
||||
let ackHandler = SocketAckHandler(event: event,
|
||||
ackNum: self.currentAck, socket: self)
|
||||
self.ackHandlers.append(ackHandler)
|
||||
|
||||
dispatch_async(self.emitQueue) {[weak self, ack = self.currentAck] in
|
||||
self?._emit(event, items, ack: ack)
|
||||
return
|
||||
}
|
||||
|
||||
return ackHandler
|
||||
return self.createOnAck(event, items: items)
|
||||
}
|
||||
|
||||
/**
|
||||
Same as emitWithAck, but for Objective-C
|
||||
*/
|
||||
public func emitWithAckObjc(event:String, withItems items:[AnyObject]) -> SocketAckHandler {
|
||||
public func emitWithAckObjc(event:String, withItems items:[AnyObject]) -> OnAckCallback {
|
||||
if !self.connected {
|
||||
return SocketAckHandler(event: "fail", socket: self)
|
||||
return self.createOnAck(event, items: items)
|
||||
}
|
||||
|
||||
self.currentAck++
|
||||
let ackHandler = SocketAckHandler(event: event,
|
||||
ackNum: self.currentAck, socket: self)
|
||||
self.ackHandlers.append(ackHandler)
|
||||
|
||||
dispatch_async(self.emitQueue) {[weak self, ack = self.currentAck] in
|
||||
self?._emit(event, items, ack: ack)
|
||||
return
|
||||
}
|
||||
|
||||
return ackHandler
|
||||
return self.createOnAck(event, items: items)
|
||||
}
|
||||
|
||||
private func _emit(event:String, _ args:[AnyObject], ack:Int? = nil) {
|
||||
@ -331,21 +340,15 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
|
||||
// Called when the socket gets an ack for something it sent
|
||||
func handleAck(ack:Int, data:AnyObject?) {
|
||||
self.ackHandlers = self.ackHandlers.filter {handler in
|
||||
if handler.ackNum != ack {
|
||||
return true
|
||||
} else {
|
||||
if data is NSArray {
|
||||
handler.executeAck(data as? NSArray)
|
||||
} else if data != nil {
|
||||
handler.executeAck([data!])
|
||||
} else {
|
||||
handler.executeAck(nil)
|
||||
}
|
||||
var ackData:[AnyObject]?
|
||||
|
||||
return false
|
||||
}
|
||||
if data is NSArray {
|
||||
ackData = data as? NSArray
|
||||
} else if data != nil {
|
||||
ackData = [data!]
|
||||
}
|
||||
|
||||
self.ackHandlers.executeAck(ack, items: ackData)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -428,10 +431,6 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
||||
}
|
||||
}
|
||||
|
||||
func removeAck(ack:SocketAckHandler) {
|
||||
self.ackHandlers = self.ackHandlers.filter {$0 === ack ? false : true}
|
||||
}
|
||||
|
||||
// We lost connection and should attempt to reestablish
|
||||
func tryReconnect() {
|
||||
if self.reconnectAttempts != -1 && self.currentReconnectAttempt + 1 > self.reconnectAttempts {
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
enum SocketPacketType: Int {
|
||||
enum SocketPacketType:Int {
|
||||
case CONNECT = 0
|
||||
case DISCONNECT = 1
|
||||
case EVENT = 2
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user