@@ -33,6 +33,16 @@ final class ViewControllerObserverFactory<T: ViewControllerObserver, S: ScreenMe
3333 private let metricsReceiver : S
3434 private let observerMaker : ( S . ScreenIdentifier ) -> T
3535
36+ private func ensureDeallocationOnTheMainThread( viewController: UIViewController ) {
37+ DispatchQueue . main. async {
38+ // Make sure viewController is deallocated on the main thread, because
39+ // if the last access is on the background thread, it will be deallocated
40+ // in background, and it can cause data races in UIKit.
41+ // Calling `hash` to make sure this call is not removed by the compilation optimizer
42+ _ = viewController. hash
43+ }
44+ }
45+
3646 private func observer( for viewController: UIViewController ) -> T ? {
3747 if PerformanceMonitoring . experiments. observersOnBackgroundQueue {
3848 dispatchPrecondition ( condition: . onQueue( PerformanceMonitoring . queue) )
@@ -66,6 +76,7 @@ final class ViewControllerObserverFactory<T: ViewControllerObserver, S: ScreenMe
6676 if PerformanceMonitoring . experiments. observersOnBackgroundQueue {
6777 PerformanceMonitoring . queue. async {
6878 self . observer ( for: viewController) ? . beforeInit ( viewController: viewController)
79+ self . ensureDeallocationOnTheMainThread ( viewController: viewController)
6980 }
7081 } else {
7182 observer ( for: viewController) ? . beforeInit ( viewController: viewController)
@@ -76,6 +87,7 @@ final class ViewControllerObserverFactory<T: ViewControllerObserver, S: ScreenMe
7687 if PerformanceMonitoring . experiments. observersOnBackgroundQueue {
7788 PerformanceMonitoring . queue. async {
7889 self . observer ( for: viewController) ? . beforeViewDidLoad ( viewController: viewController)
90+ self . ensureDeallocationOnTheMainThread ( viewController: viewController)
7991 }
8092 } else {
8193 observer ( for: viewController) ? . beforeViewDidLoad ( viewController: viewController)
@@ -86,6 +98,7 @@ final class ViewControllerObserverFactory<T: ViewControllerObserver, S: ScreenMe
8698 if PerformanceMonitoring . experiments. observersOnBackgroundQueue {
8799 PerformanceMonitoring . queue. async {
88100 self . observer ( for: viewController) ? . afterViewDidAppear ( viewController: viewController)
101+ self . ensureDeallocationOnTheMainThread ( viewController: viewController)
89102 }
90103 } else {
91104 observer ( for: viewController) ? . afterViewDidAppear ( viewController: viewController)
@@ -96,6 +109,7 @@ final class ViewControllerObserverFactory<T: ViewControllerObserver, S: ScreenMe
96109 if PerformanceMonitoring . experiments. observersOnBackgroundQueue {
97110 PerformanceMonitoring . queue. async {
98111 self . observer ( for: viewController) ? . beforeViewWillDisappear ( viewController: viewController)
112+ self . ensureDeallocationOnTheMainThread ( viewController: viewController)
99113 }
100114 } else {
101115 observer ( for: viewController) ? . beforeViewWillDisappear ( viewController: viewController)
@@ -106,6 +120,7 @@ final class ViewControllerObserverFactory<T: ViewControllerObserver, S: ScreenMe
106120 if PerformanceMonitoring . experiments. observersOnBackgroundQueue {
107121 PerformanceMonitoring . queue. async {
108122 self . observer ( for: viewController) ? . afterViewWillAppear ( viewController: viewController)
123+ self . ensureDeallocationOnTheMainThread ( viewController: viewController)
109124 }
110125 } else {
111126 observer ( for: viewController) ? . afterViewWillAppear ( viewController: viewController)
@@ -116,6 +131,7 @@ final class ViewControllerObserverFactory<T: ViewControllerObserver, S: ScreenMe
116131 if PerformanceMonitoring . experiments. observersOnBackgroundQueue {
117132 PerformanceMonitoring . queue. async {
118133 self . observer ( for: viewController) ? . beforeViewDidDisappear ( viewController: viewController)
134+ self . ensureDeallocationOnTheMainThread ( viewController: viewController)
119135 }
120136 } else {
121137 observer ( for: viewController) ? . beforeViewDidDisappear ( viewController: viewController)
0 commit comments