fix: resolve Swift 6 concurrency warnings in WebSocketManager
- listen(): capture `task` as local `t` before the Sendable receive closure so the @MainActor-isolated property isn't referenced inside a Sendable context - startPing(): dispatch to @MainActor inside the timer block before accessing `task` - scheduleReconnect(): capture `self` weakly in the reconnect Task XcodeGen regenerated to include BackgroundRefreshManager.swift in the project. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -60,13 +60,16 @@ final class WebSocketManager: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func listen() {
|
private func listen() {
|
||||||
task?.receive { [weak self] result in
|
// Capture task locally so the Sendable receive closure doesn't reference
|
||||||
guard let self else { return }
|
// the @MainActor-isolated property directly.
|
||||||
|
guard let t = task else { return }
|
||||||
|
t.receive { [weak self] result in
|
||||||
switch result {
|
switch result {
|
||||||
case .failure:
|
case .failure:
|
||||||
Task { @MainActor in self.handleDisconnect() }
|
Task { @MainActor [weak self] in self?.handleDisconnect() }
|
||||||
case .success(let message):
|
case .success(let message):
|
||||||
Task { @MainActor in
|
Task { @MainActor [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
self.handle(message: message)
|
self.handle(message: message)
|
||||||
self.listen()
|
self.listen()
|
||||||
}
|
}
|
||||||
@@ -99,9 +102,13 @@ final class WebSocketManager: ObservableObject {
|
|||||||
private func startPing() {
|
private func startPing() {
|
||||||
pingTimer?.invalidate()
|
pingTimer?.invalidate()
|
||||||
pingTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { [weak self] _ in
|
pingTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { [weak self] _ in
|
||||||
self?.task?.sendPing { error in
|
// Hop to MainActor before touching the isolated `task` property.
|
||||||
if error != nil {
|
Task { @MainActor [weak self] in
|
||||||
Task { @MainActor in self?.handleDisconnect() }
|
guard let self else { return }
|
||||||
|
self.task?.sendPing { [weak self] error in
|
||||||
|
if error != nil {
|
||||||
|
Task { @MainActor [weak self] in self?.handleDisconnect() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,10 +126,10 @@ final class WebSocketManager: ObservableObject {
|
|||||||
let delay = min(pow(2.0, Double(attempt - 1)), maxBackoff)
|
let delay = min(pow(2.0, Double(attempt - 1)), maxBackoff)
|
||||||
connectionState = .reconnecting(attempt: attempt)
|
connectionState = .reconnecting(attempt: attempt)
|
||||||
|
|
||||||
reconnectTask = Task {
|
reconnectTask = Task { [weak self] in
|
||||||
try? await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
|
try? await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
|
||||||
guard !Task.isCancelled else { return }
|
guard !Task.isCancelled else { return }
|
||||||
await MainActor.run { self.openConnection() }
|
await MainActor.run { self?.openConnection() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user