@@ -62,13 +62,13 @@ private enum GoogleDataTransportConfig {
6262
6363 // Initializes the SDK and top-level classes
6464 required convenience init ( appID: String , installations: InstallationsProtocol ) {
65- let googleDataTransport = GDTCORTransport (
65+ let googleDataTransport = GoogleDataTransporter (
6666 mappingID: GoogleDataTransportConfig . sessionsLogSource,
6767 transformers: nil ,
6868 target: GoogleDataTransportConfig . sessionsTarget
6969 )
7070
71- let fireLogger = EventGDTLogger ( googleDataTransport: googleDataTransport! )
71+ let fireLogger = EventGDTLogger ( googleDataTransport: googleDataTransport)
7272
7373 let appInfo = ApplicationInfo ( appID: appID)
7474 let settings = SessionsSettings (
@@ -135,10 +135,10 @@ private enum GoogleDataTransportConfig {
135135 }
136136
137137 // 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.
139139 init ( appID: String , sessionGenerator: SessionGenerator , coordinator: SessionCoordinatorProtocol ,
140140 initiator: SessionInitiator , appInfo: ApplicationInfoProtocol , settings: SettingsProtocol ,
141- loggedEventCallback: @escaping ( Result < Void , FirebaseSessionsError > ) -> Void ) {
141+ loggedEventCallback: @escaping @ Sendable ( Result < Void , FirebaseSessionsError > ) -> Void ) {
142142 self . appID = appID
143143
144144 self . sessionGenerator = sessionGenerator
@@ -247,18 +247,40 @@ private enum GoogleDataTransportConfig {
247247 return SessionDetails ( sessionId: sessionGenerator. currentSession? . sessionId)
248248 }
249249
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+
250265 func register( subscriber: SessionsSubscriber ) {
251266 Logger
252267 . logDebug (
253268 " Registering Sessions SDK subscriber with name: \( subscriber. sessionsSubscriberName) , data collection enabled: \( subscriber. isDataCollectionEnabled) "
254269 )
255270
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.
256278 notificationCenter. addObserver (
257279 forName: Sessions . SessionIDChangedNotificationName,
258280 object: nil ,
259- queue: nil
281+ queue: OperationQueue . main
260282 ) { notification in
261- subscriber . onSessionChanged ( self . currentSessionDetails )
283+ callback . invoke ( notification : notification )
262284 }
263285 // Immediately call the callback because the Sessions SDK starts
264286 // before subscribers, so subscribers will miss the first Notification
0 commit comments