Skip to content

Commit 76a572e

Browse files
committed
refactor reconnect
1 parent 6da9463 commit 76a572e

File tree

2 files changed

+49
-81
lines changed

2 files changed

+49
-81
lines changed

Source/SocketIOClient.swift

Lines changed: 48 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,17 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
2828
public let socketURL: NSURL
2929

3030
public private(set) var engine: SocketEngineSpec?
31-
public private(set) var status = SocketIOClientStatus.NotConnected
31+
public private(set) var status = SocketIOClientStatus.NotConnected {
32+
didSet {
33+
switch status {
34+
case .Connected:
35+
reconnecting = false
36+
currentReconnectAttempt = 0
37+
default:
38+
break
39+
}
40+
}
41+
}
3242

3343
public var forceNew = false
3444
public var nsp = "/"
@@ -46,18 +56,16 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
4656
private var anyHandler: ((SocketAnyEvent) -> Void)?
4757
private var currentReconnectAttempt = 0
4858
private var handlers = [SocketEventHandler]()
49-
private var reconnectTimer: NSTimer?
5059
private var ackHandlers = SocketAckManager()
60+
private var reconnecting = false
5161

5262
private(set) var currentAck = -1
5363
private(set) var handleQueue = dispatch_get_main_queue()
5464
private(set) var reconnectAttempts = -1
5565

5666
var waitingPackets = [SocketPacket]()
5767

58-
/**
59-
Type safe way to create a new SocketIOClient. opts can be omitted
60-
*/
68+
/// Type safe way to create a new SocketIOClient. opts can be omitted
6169
public init(socketURL: NSURL, options: Set<SocketIOClientOption> = []) {
6270
self.options = options
6371
self.socketURL = socketURL
@@ -94,10 +102,8 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
94102
super.init()
95103
}
96104

97-
/**
98-
Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity.
99-
If using Swift it's recommended to use `init(socketURL: NSURL, options: Set<SocketIOClientOption>)`
100-
*/
105+
/// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity.
106+
/// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set<SocketIOClientOption>)`
101107
public convenience init(socketURL: NSURL, options: NSDictionary?) {
102108
self.init(socketURL: socketURL, options: options?.toSocketOptionsSet() ?? [])
103109
}
@@ -127,26 +133,17 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
127133
return engine!
128134
}
129135

130-
private func clearReconnectTimer() {
131-
reconnectTimer?.invalidate()
132-
reconnectTimer = nil
133-
}
134-
135136
@available(*, deprecated=5.3, message="Please use disconnect()")
136137
public func close() {
137138
disconnect()
138139
}
139140

140-
/**
141-
Connect to the server.
142-
*/
141+
/// Connect to the server.
143142
public func connect() {
144143
connect(timeoutAfter: 0, withTimeoutHandler: nil)
145144
}
146145

147-
/**
148-
Connect to the server. If we aren't connected after timeoutAfter, call handler
149-
*/
146+
/// Connect to the server. If we aren't connected after timeoutAfter, call handler
150147
public func connect(timeoutAfter timeoutAfter: Int, withTimeoutHandler handler: (() -> Void)?) {
151148
assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)")
152149

@@ -203,8 +200,6 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
203200
func didConnect() {
204201
DefaultSocketLogger.Logger.log("Socket connected", type: logType)
205202
status = .Connected
206-
currentReconnectAttempt = 0
207-
clearReconnectTimer()
208203

209204
// Don't handle as internal because something crazy could happen where
210205
// we disconnect before it's handled
@@ -224,27 +219,21 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
224219
handleEvent("disconnect", data: [reason], isInternalMessage: true)
225220
}
226221

227-
/**
228-
Disconnects the socket. Only reconnect the same socket if you know what you're doing.
229-
Will turn off automatic reconnects.
230-
*/
222+
/// Disconnects the socket. Only reconnect the same socket if you know what you're doing.
223+
/// Will turn off automatic reconnects.
231224
public func disconnect() {
232225
DefaultSocketLogger.Logger.log("Closing socket", type: logType)
233226

234227
reconnects = false
235228
didDisconnect("Disconnect")
236229
}
237230

238-
/**
239-
Send a message to the server
240-
*/
231+
/// Send a message to the server
241232
public func emit(event: String, _ items: AnyObject...) {
242233
emit(event, withItems: items)
243234
}
244235

245-
/**
246-
Same as emit, but meant for Objective-C
247-
*/
236+
/// Same as emit, but meant for Objective-C
248237
public func emit(event: String, withItems items: [AnyObject]) {
249238
guard status == .Connected else {
250239
handleEvent("error", data: ["Tried emitting \(event) when not connected"], isInternalMessage: true)
@@ -301,10 +290,15 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
301290

302291
public func engineDidClose(reason: String) {
303292
waitingPackets.removeAll()
293+
294+
if status != .Closed {
295+
status = .NotConnected
296+
}
304297

305298
if status == .Closed || !reconnects {
306299
didDisconnect(reason)
307-
} else if status != .Reconnecting {
300+
} else if !reconnecting {
301+
reconnecting = true
308302
tryReconnectWithReason(reason)
309303
}
310304
}
@@ -325,9 +319,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
325319
ackHandlers.executeAck(ack, items: data)
326320
}
327321

328-
/**
329-
Causes an event to be handled. Only use if you know what you're doing.
330-
*/
322+
/// Causes an event to be handled. Only use if you know what you're doing.
331323
public func handleEvent(event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int = -1) {
332324
guard status == .Connected || isInternalMessage else {
333325
return
@@ -344,19 +336,15 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
344336
}
345337
}
346338

347-
/**
348-
Leaves nsp and goes back to /
349-
*/
339+
/// Leaves nsp and goes back to /
350340
public func leaveNamespace() {
351341
if nsp != "/" {
352342
engine?.send("1\(nsp)", withData: [])
353343
nsp = "/"
354344
}
355345
}
356346

357-
/**
358-
Joins namespace
359-
*/
347+
/// Joins namespace
360348
public func joinNamespace(namespace: String) {
361349
nsp = namespace
362350

@@ -366,28 +354,22 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
366354
}
367355
}
368356

369-
/**
370-
Removes handler(s)
371-
*/
357+
/// Removes handler(s) based on name
372358
public func off(event: String) {
373359
DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event)
374360

375361
handlers = handlers.filter { $0.event != event }
376362
}
377363

378-
/**
379-
Removes a handler with the specified UUID gotten from an `on` or `once`
380-
*/
364+
/// Removes a handler with the specified UUID gotten from an `on` or `once`
381365
public func off(id id: NSUUID) {
382366
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id)
383367

384368
handlers = handlers.filter { $0.id != id }
385369
}
386370

387-
/**
388-
Adds a handler for an event.
389-
Returns: A unique id for the handler
390-
*/
371+
/// Adds a handler for an event.
372+
/// Returns: A unique id for the handler
391373
public func on(event: String, callback: NormalCallback) -> NSUUID {
392374
DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event)
393375

@@ -397,10 +379,8 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
397379
return handler.id
398380
}
399381

400-
/**
401-
Adds a single-use handler for an event.
402-
Returns: A unique id for the handler
403-
*/
382+
/// Adds a single-use handler for an event.
383+
/// Returns: A unique id for the handler
404384
public func once(event: String, callback: NormalCallback) -> NSUUID {
405385
DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event)
406386

@@ -417,9 +397,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
417397
return handler.id
418398
}
419399

420-
/**
421-
Adds a handler that will be called on every event.
422-
*/
400+
/// Adds a handler that will be called on every event.
423401
public func onAny(handler: (SocketAnyEvent) -> Void) {
424402
anyHandler = handler
425403
}
@@ -443,44 +421,32 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
443421
}
444422
}
445423

446-
/**
447-
Tries to reconnect to the server.
448-
*/
424+
/// Tries to reconnect to the server.
449425
public func reconnect() {
450426
tryReconnectWithReason("manual reconnect")
451427
}
452428

453-
/**
454-
Removes all handlers.
455-
Can be used after disconnecting to break any potential remaining retain cycles.
456-
*/
429+
/// Removes all handlers.
430+
/// Can be used after disconnecting to break any potential remaining retain cycles.
457431
public func removeAllHandlers() {
458432
handlers.removeAll(keepCapacity: false)
459433
}
460434

461435
private func tryReconnectWithReason(reason: String) {
462-
if reconnectTimer == nil {
436+
if reconnecting {
463437
DefaultSocketLogger.Logger.log("Starting reconnect", type: logType)
464438
handleEvent("reconnect", data: [reason], isInternalMessage: true)
465-
466-
status = .Reconnecting
467-
468-
dispatch_async(dispatch_get_main_queue()) {
469-
self.reconnectTimer = NSTimer.scheduledTimerWithTimeInterval(Double(self.reconnectWait),
470-
target: self, selector: "_tryReconnect", userInfo: nil, repeats: true)
471-
}
439+
440+
_tryReconnect()
472441
}
473442
}
474443

475444
@objc private func _tryReconnect() {
476-
if status == .Connected {
477-
clearReconnectTimer()
478-
445+
if !reconnecting {
479446
return
480447
}
481448

482449
if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects {
483-
clearReconnectTimer()
484450
didDisconnect("Reconnect Failed")
485451

486452
return
@@ -492,6 +458,10 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable
492458

493459
currentReconnectAttempt += 1
494460
connect()
461+
462+
let dispatchAfter = dispatch_time(DISPATCH_TIME_NOW, Int64(UInt64(reconnectWait) * NSEC_PER_SEC))
463+
464+
dispatch_after(dispatchAfter, dispatch_get_main_queue(), _tryReconnect)
495465
}
496466
}
497467

Source/SocketIOClientStatus.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import Foundation
2626

2727
@objc public enum SocketIOClientStatus: Int, CustomStringConvertible {
28-
case NotConnected, Closed, Connecting, Connected, Reconnecting
28+
case NotConnected, Closed, Connecting, Connected
2929

3030
public var description: String {
3131
switch self {
@@ -37,8 +37,6 @@ import Foundation
3737
return "Connecting"
3838
case Connected:
3939
return "Connected"
40-
case Reconnecting:
41-
return "Reconnecting"
4240
}
4341
}
4442
}

0 commit comments

Comments
 (0)