Skip to content

Commit 7b9c723

Browse files
authored
fix: use a single instance of PusherWebsocketReactNative (#79)
1 parent 3aac759 commit 7b9c723

File tree

1 file changed

+41
-33
lines changed

1 file changed

+41
-33
lines changed

ios/PusherWebsocketReactNative.swift

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import Foundation
33

44
@objc(PusherWebsocketReactNative)
55
@objcMembers class PusherWebsocketReactNative: RCTEventEmitter, PusherDelegate, Authorizer {
6-
private var pusher: Pusher!
6+
private static var shared: PusherWebsocketReactNative!
7+
private static var pusher: Pusher!
78

89
private var authorizerCompletionHandlers = [String: ([String:String]) -> Void]()
910
private var authorizerCompletionHandlerTimeout = 10 // seconds
@@ -12,6 +13,12 @@ import Foundation
1213
private let authErrorType = "AuthError"
1314
private let pusherEventPrefix = "PusherReactNative"
1415

16+
override init() {
17+
super.init()
18+
19+
PusherWebsocketReactNative.shared = self
20+
}
21+
1522
override func supportedEvents() -> [String]! {
1623
return ["\(pusherEventPrefix):onConnectionStateChange",
1724
"\(pusherEventPrefix):onSubscriptionError",
@@ -26,18 +33,19 @@ import Foundation
2633

2734
private func callback(name:String, body:Any) -> Void {
2835
let pusherEventname = "\(pusherEventPrefix):\(name)"
29-
self.sendEvent(withName:pusherEventname, body:body)
36+
PusherWebsocketReactNative.shared.sendEvent(withName:pusherEventname, body:body)
3037
}
3138

3239
func initialize(_ args:[String: Any], resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
33-
if pusher != nil {
34-
pusher.disconnect()
40+
if PusherWebsocketReactNative.pusher != nil {
41+
PusherWebsocketReactNative.pusher.unsubscribeAll()
42+
PusherWebsocketReactNative.pusher.disconnect()
3543
}
3644
var authMethod:AuthMethod = .noMethod
3745
if args["authEndpoint"] is String {
3846
authMethod = .endpoint(authEndpoint: args["authEndpoint"] as! String)
3947
} else if args["authorizer"] is Bool {
40-
authMethod = .authorizer(authorizer: self)
48+
authMethod = .authorizer(authorizer: PusherWebsocketReactNative.shared)
4149
}
4250
var host:PusherHost = .defaultHost
4351
if args["host"] is String {
@@ -77,23 +85,23 @@ import Foundation
7785
useTLS: useTLS,
7886
activityTimeout: activityTimeout
7987
)
80-
pusher = Pusher(key: args["apiKey"] as! String, options: options)
88+
PusherWebsocketReactNative.pusher = Pusher(key: args["apiKey"] as! String, options: options)
8189
if args["maxReconnectionAttempts"] is Int {
82-
pusher.connection.reconnectAttemptsMax = (args["maxReconnectionAttempts"] as! Int)
90+
PusherWebsocketReactNative.pusher.connection.reconnectAttemptsMax = (args["maxReconnectionAttempts"] as! Int)
8391
}
8492
if args["maxReconnectGapInSeconds"] is TimeInterval {
85-
pusher.connection.maxReconnectGapInSeconds = (args["maxReconnectGapInSeconds"] as! TimeInterval)
93+
PusherWebsocketReactNative.pusher.connection.maxReconnectGapInSeconds = (args["maxReconnectGapInSeconds"] as! TimeInterval)
8694
}
8795
if args["pongTimeout"] is Int {
88-
pusher.connection.pongResponseTimeoutInterval = args["pongTimeout"] as! TimeInterval / 1000.0
96+
PusherWebsocketReactNative.pusher.connection.pongResponseTimeoutInterval = args["pongTimeout"] as! TimeInterval / 1000.0
8997
}
9098

9199
if let authorizerTimeoutInSeconds = args["authorizerTimeoutInSeconds"] as? Int {
92-
self.authorizerCompletionHandlerTimeout = authorizerTimeoutInSeconds
100+
PusherWebsocketReactNative.shared.authorizerCompletionHandlerTimeout = authorizerTimeoutInSeconds
93101
}
94102

95-
pusher.connection.delegate = self
96-
pusher.bind(eventCallback: onEvent)
103+
PusherWebsocketReactNative.pusher.connection.delegate = PusherWebsocketReactNative.shared
104+
PusherWebsocketReactNative.pusher.bind(eventCallback: onEvent)
97105
resolve(nil)
98106
}
99107

@@ -102,7 +110,7 @@ import Foundation
102110
}
103111

104112
public func fetchAuthValue(socketID: String, channelName: String, completionHandler: @escaping (PusherAuth?) -> Void) {
105-
self.callback(name:"onAuthorizer", body: [
113+
PusherWebsocketReactNative.shared.callback(name:"onAuthorizer", body: [
106114
"socketId": socketID,
107115
"channelName": channelName
108116
])
@@ -118,9 +126,9 @@ import Foundation
118126
authorizerCompletionHandlers[key] = authCallback
119127

120128
// the JS thread might not call onAuthorizer – we need to cleanup the completion handler after timeout
121-
let timeout = DispatchTimeInterval.seconds(self.authorizerCompletionHandlerTimeout)
129+
let timeout = DispatchTimeInterval.seconds(PusherWebsocketReactNative.shared.authorizerCompletionHandlerTimeout)
122130
DispatchQueue.main.asyncAfter(deadline: .now() + timeout) {
123-
if let storedAuthHandler = self.authorizerCompletionHandlers.removeValue(forKey: key) {
131+
if let storedAuthHandler = PusherWebsocketReactNative.shared.authorizerCompletionHandlers.removeValue(forKey: key) {
124132
storedAuthHandler(["auth": "<authorizer_timeout>:error"])
125133
}
126134
}
@@ -132,9 +140,9 @@ import Foundation
132140
storedAuthHandler(data)
133141
}
134142
}
135-
143+
136144
public func changedConnectionState(from old: ConnectionState, to new: ConnectionState) {
137-
self.callback(name:"onConnectionStateChange", body:[
145+
PusherWebsocketReactNative.shared.callback(name:"onConnectionStateChange", body:[
138146
"previousState": old.stringValue(),
139147
"currentState": new.stringValue()
140148
])
@@ -156,7 +164,7 @@ import Foundation
156164
type = authErrorType
157165
}
158166

159-
self.callback(name:"onSubscriptionError", body:[
167+
PusherWebsocketReactNative.shared.callback(name:"onSubscriptionError", body:[
160168
"message": (error != nil) ? error!.localizedDescription : ((data != nil) ? data! : error.debugDescription),
161169
"type": type,
162170
"code": code,
@@ -165,7 +173,7 @@ import Foundation
165173
}
166174

167175
public func receivedError(error: PusherError) {
168-
self.callback(
176+
PusherWebsocketReactNative.shared.callback(
169177
name:"onError", body:[
170178
"message": error.message,
171179
"code": error.code ?? -1,
@@ -175,7 +183,7 @@ import Foundation
175183
}
176184

177185
public func failedToDecryptEvent(eventName: String, channelName: String, data: String?) {
178-
self.callback(
186+
PusherWebsocketReactNative.shared.callback(
179187
name:"onDecryptionFailure", body:[
180188
"eventName": eventName,
181189
"reason": data
@@ -184,29 +192,29 @@ import Foundation
184192
}
185193

186194
public func connect(_ resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
187-
pusher.connect()
195+
PusherWebsocketReactNative.pusher.connect()
188196
resolve(nil)
189197
}
190198

191199
public func disconnect(_ resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
192-
pusher.disconnect()
200+
PusherWebsocketReactNative.pusher.disconnect()
193201
resolve(nil)
194202
}
195203

196204
public func getSocketId() -> String? {
197-
return pusher.connection.socketId
205+
return PusherWebsocketReactNative.pusher.connection.socketId
198206
}
199207

200208
func onEvent(event:PusherEvent) {
201209
var userId:String? = nil
202210
var mappedEventName:String? = nil
203211
if event.eventName == "pusher:subscription_succeeded" {
204-
if let channel = pusher.connection.channels.findPresence(name: event.channelName!) {
212+
if let channel = PusherWebsocketReactNative.pusher.connection.channels.findPresence(name: event.channelName!) {
205213
userId = channel.myId
206214
}
207215
mappedEventName = "pusher_internal:subscription_succeeded"
208216
}
209-
self.callback(
217+
PusherWebsocketReactNative.shared.callback(
210218
name:"onEvent",body:[
211219
"channelName": event.channelName,
212220
"eventName": mappedEventName ?? event.eventName,
@@ -219,25 +227,25 @@ import Foundation
219227
func subscribe(_ channelName:String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
220228
if channelName.hasPrefix("presence-") {
221229
let onMemberAdded:(PusherPresenceChannelMember) -> () = { user in
222-
self.callback(name:"onMemberAdded", body: [
230+
PusherWebsocketReactNative.shared.callback(name:"onMemberAdded", body: [
223231
"channelName": channelName,
224232
"user": ["userId": user.userId, "userInfo": user.userInfo ]
225233
])
226234
}
227235
let onMemberRemoved:(PusherPresenceChannelMember) -> () = { user in
228-
self.callback(name:"onMemberRemoved", body: [
236+
PusherWebsocketReactNative.shared.callback(name:"onMemberRemoved", body: [
229237
"channelName": channelName,
230238
"user": ["userId": user.userId, "userInfo": user.userInfo ]
231239
])
232240
}
233-
pusher.subscribeToPresenceChannel(
241+
PusherWebsocketReactNative.pusher.subscribeToPresenceChannel(
234242
channelName: channelName,
235243
onMemberAdded: onMemberAdded,
236244
onMemberRemoved: onMemberRemoved
237245
)
238246
} else {
239247
let onSubscriptionCount:(Int) -> () = { subscriptionCount in
240-
self.callback(
248+
PusherWebsocketReactNative.shared.callback(
241249
name:"onEvent",body:[
242250
"channelName": channelName,
243251
"eventName": "pusher_internal:subscription_count",
@@ -248,19 +256,19 @@ import Foundation
248256
]
249257
)
250258
}
251-
pusher.subscribe(channelName: channelName,
252-
onSubscriptionCountChanged: onSubscriptionCount)
259+
PusherWebsocketReactNative.pusher.subscribe(channelName: channelName,
260+
onSubscriptionCountChanged: onSubscriptionCount)
253261
}
254262
resolve(nil)
255263
}
256264

257265
func unsubscribe(_ channelName:String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
258-
pusher.unsubscribe(channelName)
266+
PusherWebsocketReactNative.pusher.unsubscribe(channelName)
259267
resolve(nil)
260268
}
261269

262270
func trigger(_ channelName:String, eventName:String, data:Any, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
263-
if let channel = pusher.connection.channels.find(name: channelName) {
271+
if let channel = PusherWebsocketReactNative.pusher.connection.channels.find(name: channelName) {
264272
channel.trigger(eventName: eventName, data: data)
265273
}
266274
resolve(nil)

0 commit comments

Comments
 (0)