@@ -10,8 +10,7 @@ import OSLog
10
10
11
11
/// Connects to the remote server and sends logs remotely. In the current version,
12
12
/// a server is a Pulse Pro app for macOS).
13
- ///
14
- /// - warning: Has to be used from the main thread.
13
+ @MainActor
15
14
public final class RemoteLogger : ObservableObject , RemoteLoggerConnectionDelegate {
16
15
/// The store that the logger was initialized with.
17
16
public private( set) var store : LoggerStore ?
@@ -46,10 +45,14 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat
46
45
47
46
@Published
48
47
public private( set) var connectionState : ConnectionState = . disconnected {
49
- didSet { os_log ( " Set public connection state %{public}@ " , log: log, " \( oldValue) → \( connectionState) " ) }
50
-
48
+ didSet {
49
+ os_log ( " Set public connection state %{public}@ " , log: log, " \( oldValue) → \( connectionState) " )
50
+ RemoteLogger . latestConnectionState. value = connectionState
51
+ }
51
52
}
52
53
54
+ nonisolated static let latestConnectionState = Mutex < ConnectionState > ( . disconnected)
55
+
53
56
// Browsing
54
57
private var browser : NWBrowser ?
55
58
private var selectedServerPasscode : String ?
@@ -101,8 +104,7 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat
101
104
}
102
105
}
103
106
104
- public static var shared : RemoteLogger { _shared. value }
105
- private static let _shared = Mutex ( RemoteLogger ( ) )
107
+ public static let shared = RemoteLogger ( )
106
108
107
109
/// - parameter store: The store to be synced with the server. By default,
108
110
/// ``LoggerStore/shared``. Only one store can be synced at at time.
@@ -128,9 +130,8 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat
128
130
129
131
// The buffer is used to cover the time between the app launch and the
130
132
// initial (automatic) connection to the server.
131
- let box = SendableBox ( value: self )
132
- DispatchQueue . main. asyncAfter ( deadline: . now( ) + . seconds( 3 ) ) {
133
- box. value? . clearBuffer ( )
133
+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + . seconds( 3 ) ) { [ weak self] in
134
+ self ? . clearBuffer ( )
134
135
}
135
136
}
136
137
@@ -201,12 +202,15 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat
201
202
parameters. includePeerToPeer = true
202
203
203
204
let browser = NWBrowser ( for: . bonjourWithTXTRecord( type: RemoteLogger . serviceType, domain: nil ) , using: parameters)
204
- let box = SendableBox ( value: self )
205
- browser. stateUpdateHandler = {
206
- box. value? . browserDidUpdateState ( $0)
205
+ browser. stateUpdateHandler = { [ weak self] state in
206
+ MainActor . assumeIsolated {
207
+ self ? . browserDidUpdateState ( state)
208
+ }
207
209
}
208
- browser. browseResultsChangedHandler = { results, _ in
209
- box. value? . browserDidUpdateResults ( results)
210
+ browser. browseResultsChangedHandler = { [ weak self] results, _ in
211
+ MainActor . assumeIsolated {
212
+ self ? . browserDidUpdateResults ( results)
213
+ }
210
214
}
211
215
browser. start ( queue: . main)
212
216
@@ -249,9 +253,8 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat
249
253
os_log ( " Did scheduled browser retry " , log: log)
250
254
251
255
// Automatically retry until the user cancels
252
- let box = SendableBox ( value: self )
253
- DispatchQueue . main. asyncAfter ( deadline: . now( ) + . seconds( 5 ) ) {
254
- guard let self = box. value, self . isEnabled else { return }
256
+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + . seconds( 5 ) ) { [ weak self] in
257
+ guard let self, self . isEnabled else { return }
255
258
self . stopBrowser ( )
256
259
self . startBrowser ( )
257
260
}
@@ -440,9 +443,8 @@ public final class RemoteLogger: ObservableObject, RemoteLoggerConnectionDelegat
440
443
connection? . send ( code: . clientHello, entity: body)
441
444
442
445
// Set timeout and retry in case there was no response from the server
443
- let box = SendableBox ( value: self )
444
- DispatchQueue . main. asyncAfter ( deadline: . now( ) + . seconds( 10 ) ) {
445
- box. value? . handshakeDidTimeout ( )
446
+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + . seconds( 10 ) ) { [ weak self] in
447
+ self ? . handshakeDidTimeout ( )
446
448
}
447
449
}
448
450
@@ -692,10 +694,6 @@ private func getFallbackDeviceId() -> UUID {
692
694
return id
693
695
}
694
696
695
- private struct SendableBox < T: AnyObject > : @unchecked Sendable {
696
- weak var value : T ?
697
- }
698
-
699
697
private extension NWBrowser . Result {
700
698
var name : String ? {
701
699
switch endpoint {
0 commit comments