Skip to content

Commit

Permalink
PhoenixTransport Crash Fix for iOS 18 (#275)
Browse files Browse the repository at this point in the history
* Refactor URLSessionWebSocketTask's receive function to use async instead of completionHandler

* Fix typo

* Cancel receiveMessageTask on disconnect

* Move receiveMessageTask cancellation after finishTasksAndInvalidate
  • Loading branch information
varun-score authored Jan 13, 2025
1 parent 2ea54b4 commit d53927d
Showing 1 changed file with 30 additions and 23 deletions.
53 changes: 30 additions & 23 deletions Sources/SwiftPhoenixClient/PhoenixTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,13 @@ open class URLSessionTransport: NSObject, PhoenixTransport, URLSessionWebSocketD

/// The ongoing task. Assigned during `connect()`
private var task: URLSessionWebSocketTask? = nil


/// Holds the current receive task
private var receiveMessageTask: Task<Void, Never>? {
didSet {
oldValue?.cancel()
}
}

/**
Initializes a `Transport` layer built using URLSession's WebSocket
Expand Down Expand Up @@ -192,6 +198,7 @@ open class URLSessionTransport: NSObject, PhoenixTransport, URLSessionWebSocketD

deinit {
self.delegate = nil
receiveMessageTask?.cancel()
}


Expand Down Expand Up @@ -233,6 +240,7 @@ open class URLSessionTransport: NSObject, PhoenixTransport, URLSessionWebSocketD
self.readyState = .closing
self.task?.cancel(with: closeCode, reason: reason?.data(using: .utf8))
self.session?.finishTasksAndInvalidate()
receiveMessageTask?.cancel()
}

open func send(data: Data) {
Expand Down Expand Up @@ -276,29 +284,28 @@ open class URLSessionTransport: NSObject, PhoenixTransport, URLSessionWebSocketD

// MARK: - Private
private func receive() {
self.task?.receive { [weak self] result in
guard let self = self else { return }

switch result {
case .success(let message):
switch message {
case .data:
print("Data received. This method is unsupported by the Client")
case .string(let text):
self.delegate?.onMessage(message: text)
default:
fatalError("Unknown result was received. [\(result)]")
}

// Since `.receive()` is only good for a single message, it must
// be called again after a message is received in order to
// received the next message.
self.receive()
case .failure(let error):
print("Error when receiving \(error)")
self.abnormalErrorReceived(error, response: nil)
receiveMessageTask = Task { [weak self] in
guard let self else { return }
do {
let message = try await task?.receive()
switch message {
case .data:
print("Data received. This method is unsupported by the Client")
case .string(let text):
delegate?.onMessage(message: text)
default:
fatalError("Nil message received.")
}
// Since `.receive()` is only good for a single message, it must
// be called again after a message is received in order to
// received the next message.
receive()
} catch {
print("Error when receiving \(error)")
abnormalErrorReceived(error, response: nil)
}
}
}
}

private func abnormalErrorReceived(_ error: Error, response: URLResponse?) {
Expand Down

0 comments on commit d53927d

Please sign in to comment.