@@ -62,13 +62,13 @@ private enum GoogleDataTransportConfig {
62
62
63
63
// Initializes the SDK and top-level classes
64
64
required convenience init ( appID: String , installations: InstallationsProtocol ) {
65
- let googleDataTransport = GDTCORTransport (
65
+ let googleDataTransport = GoogleDataTransporter (
66
66
mappingID: GoogleDataTransportConfig . sessionsLogSource,
67
67
transformers: nil ,
68
68
target: GoogleDataTransportConfig . sessionsTarget
69
69
)
70
70
71
- let fireLogger = EventGDTLogger ( googleDataTransport: googleDataTransport! )
71
+ let fireLogger = EventGDTLogger ( googleDataTransport: googleDataTransport)
72
72
73
73
let appInfo = ApplicationInfo ( appID: appID)
74
74
let settings = SessionsSettings (
@@ -135,10 +135,10 @@ private enum GoogleDataTransportConfig {
135
135
}
136
136
137
137
// Initializes the SDK and begins the process of listening for lifecycle events and logging
138
- // events
138
+ // events. `logEventCallback` is invoked on a global background queue.
139
139
init ( appID: String , sessionGenerator: SessionGenerator , coordinator: SessionCoordinatorProtocol ,
140
140
initiator: SessionInitiator , appInfo: ApplicationInfoProtocol , settings: SettingsProtocol ,
141
- loggedEventCallback: @escaping ( Result < Void , FirebaseSessionsError > ) -> Void ) {
141
+ loggedEventCallback: @escaping @ Sendable ( Result < Void , FirebaseSessionsError > ) -> Void ) {
142
142
self . appID = appID
143
143
144
144
self . sessionGenerator = sessionGenerator
@@ -247,18 +247,40 @@ private enum GoogleDataTransportConfig {
247
247
return SessionDetails ( sessionId: sessionGenerator. currentSession? . sessionId)
248
248
}
249
249
250
+ // This type is not actually sendable, but works around an issue below.
251
+ // It's safe only if executed on the main actor.
252
+ private struct MainActorNotificationCallback : @unchecked Sendable {
253
+ private let callback : ( Notification ) -> Void
254
+
255
+ init ( _ callback: @escaping ( Notification ) -> Void ) {
256
+ self . callback = callback
257
+ }
258
+
259
+ func invoke( notification: Notification ) {
260
+ dispatchPrecondition ( condition: . onQueue( . main) )
261
+ callback ( notification)
262
+ }
263
+ }
264
+
250
265
func register( subscriber: SessionsSubscriber ) {
251
266
Logger
252
267
. logDebug (
253
268
" Registering Sessions SDK subscriber with name: \( subscriber. sessionsSubscriberName) , data collection enabled: \( subscriber. isDataCollectionEnabled) "
254
269
)
255
270
271
+ // TODO(Firebase 12): After bumping to iOS 13, this hack should be replaced
272
+ // with `Task { @MainActor in }`.
273
+ let callback = MainActorNotificationCallback { notification in
274
+ subscriber. onSessionChanged ( self . currentSessionDetails)
275
+ }
276
+
277
+ // Guaranteed to execute its callback on the main queue because of the queue parameter.
256
278
notificationCenter. addObserver (
257
279
forName: Sessions . SessionIDChangedNotificationName,
258
280
object: nil ,
259
- queue: nil
281
+ queue: OperationQueue . main
260
282
) { notification in
261
- subscriber . onSessionChanged ( self . currentSessionDetails )
283
+ callback . invoke ( notification : notification )
262
284
}
263
285
// Immediately call the callback because the Sessions SDK starts
264
286
// before subscribers, so subscribers will miss the first Notification
0 commit comments