Skip to content

Commit 2dbbe22

Browse files
author
Gleb Tarasov
committed
Fix when screenIsReady is called on the child view controller for observersOnBackgroundQueue experiment
1 parent 6d79405 commit 2dbbe22

File tree

5 files changed

+64
-9
lines changed

5 files changed

+64
-9
lines changed

PerformanceSuite/Sources/TTIObserver+Extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public extension UIViewController {
2929
/// }
3030
/// ```
3131
@objc func screenIsReady() {
32-
let observer = ViewControllerObserverFactoryHelper.existingObserver(for: self, identifier: TTIObserverHelper.identifier) as? ScreenIsReadyProvider
32+
let observer = ViewControllerObserverFactoryHelper.existingObserver(forChild: self, identifier: TTIObserverHelper.identifier) as? ScreenIsReadyProvider
3333
observer?.screenIsReady()
3434
}
3535

PerformanceSuite/Sources/ViewControllerObserver.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,16 @@ final class ViewControllerObserverFactoryHelper {
200200

201201
return nil
202202
}
203+
204+
static func existingObserver(forChild viewController: UIViewController, identifier: AnyObject) -> Any? {
205+
var vc: UIViewController? = viewController
206+
while let current = vc {
207+
let tPointer = unsafeBitCast(identifier, to: UnsafeRawPointer.self)
208+
if let result = objc_getAssociatedObject(current, tPointer) {
209+
return result
210+
}
211+
vc = current.parent
212+
}
213+
return nil
214+
}
203215
}

PerformanceSuite/Tests/TTIObserverExtensionTests.swift

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class TTIObserverExtensionTests: XCTestCase {
2121
try super.setUpWithError()
2222
defaultTimeProvider = timeProvider
2323
metricsReceiver = TTIMetricsReceiverStub()
24-
try PerformanceMonitoring.enable(config: [.screenLevelTTI(metricsReceiver)], experiments: Experiments())
24+
try PerformanceMonitoring.enable(config: [.screenLevelTTI(metricsReceiver)], experiments: Experiments(observersOnBackgroundQueue: true))
2525
}
2626

2727
override func tearDownWithError() throws {
@@ -308,6 +308,44 @@ class TTIObserverExtensionTests: XCTestCase {
308308
XCTAssertEqual(metricsReceiver.ttiMetrics?.tti, .seconds(2))
309309
XCTAssertEqual(metricsReceiver.lastController?.title, "vc3")
310310
}
311+
312+
func testScreenIsReadyForChildViewController() {
313+
let now = DispatchTime(uptimeNanoseconds: 10_000_000)
314+
timeProvider.time = now
315+
316+
let vc1 = MyViewController()
317+
vc1.title = "vc1"
318+
319+
let vc2 = UIViewController()
320+
vc2.title = "vc2"
321+
322+
vc1.addChild(vc2)
323+
324+
timeProvider.time = now.advanced(by: .seconds(1))
325+
326+
let exp1 = expectation(description: "viewDidAppear vc1")
327+
vc1.viewAppeared = {
328+
DispatchQueue.main.async {
329+
exp1.fulfill()
330+
}
331+
}
332+
333+
let window = makeWindow()
334+
window.rootViewController = vc1
335+
window.makeKeyAndVisible()
336+
337+
waitForExpectations(timeout: 3, handler: nil)
338+
339+
// we call screenIsReady for the child, but it should work for the parent
340+
vc2.screenIsReady()
341+
342+
PerformanceMonitoring.queue.sync {}
343+
PerformanceMonitoring.consumerQueue.sync {}
344+
345+
XCTAssertNotNil(metricsReceiver.ttiMetrics)
346+
XCTAssertEqual(metricsReceiver.ttiMetrics?.tti, .seconds(1))
347+
XCTAssertEqual(metricsReceiver.lastController?.title, "vc1")
348+
}
311349
}
312350

313351
private class MyHostingController<T: View>: UIHostingController<T> {

PerformanceSuite/Tests/TTIObserverTests.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,22 @@ class TTIObserverTests: XCTestCase {
2929
}
3030

3131
func testTTIObserverForViewController() throws {
32-
let vc1 = UIViewController()
32+
let vc1 = MyViewController()
3333
waitForTheNextRunLoop()
3434
XCTAssertNil(ViewControllerObserverFactoryHelper.existingObserver(for: vc1, identifier: TTIObserverHelper.identifier))
3535

3636
try PerformanceMonitoring.enable(config: [.screenLevelTTI(TTIMetricsReceiverStub())])
37-
let vc2 = UIViewController()
37+
let vc2 = MyViewController()
3838
waitForTheNextRunLoop()
3939
XCTAssertNotNil(ViewControllerObserverFactoryHelper.existingObserver(for: vc2, identifier: TTIObserverHelper.identifier))
4040

4141
try PerformanceMonitoring.disable()
42-
let vc3 = UIViewController()
42+
let vc3 = MyViewController()
4343
waitForTheNextRunLoop()
4444
XCTAssertNil(ViewControllerObserverFactoryHelper.existingObserver(for: vc3, identifier: TTIObserverHelper.identifier))
4545

4646
try PerformanceMonitoring.enable(config: [])
47-
let vc4 = UIViewController()
47+
let vc4 = MyViewController()
4848
waitForTheNextRunLoop()
4949
XCTAssertNil(ViewControllerObserverFactoryHelper.existingObserver(for: vc4, identifier: TTIObserverHelper.identifier))
5050
try PerformanceMonitoring.disable()
@@ -539,7 +539,8 @@ class TTIMetricsReceiverStub: TTIMetricsReceiver {
539539

540540
func screenIdentifier(for viewController: UIViewController) -> UIViewController? {
541541
if viewController is UINavigationController
542-
|| viewController is UITabBarController {
542+
|| viewController is UITabBarController
543+
|| type(of: viewController) == UIViewController.self {
543544
return nil
544545
}
545546
return viewController
@@ -549,3 +550,5 @@ class TTIMetricsReceiverStub: TTIMetricsReceiver {
549550
var ttiMetrics: TTIMetrics?
550551
var lastController: UIViewController?
551552
}
553+
554+
private class MyViewController: UIViewController { }

PerformanceSuite/Tests/ViewControllerObserverTests.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class ViewControllerObserverTests: XCTestCase {
7979

8080
lastObserverCreated = nil
8181

82-
let vc1 = UIViewController()
82+
let vc1 = MyViewController()
8383
factory.beforeInit(viewController: vc1)
8484
PerformanceMonitoring.queue.sync { }
8585

@@ -100,7 +100,7 @@ class ViewControllerObserverTests: XCTestCase {
100100
observer?.clear()
101101

102102

103-
let vc2 = UIViewController()
103+
let vc2 = MyViewController()
104104
factory.afterViewDidAppear(viewController: vc2)
105105
PerformanceMonitoring.queue.sync { }
106106

@@ -158,3 +158,5 @@ private class MetricsConsumerForSwiftUITest: ScreenMetricsReceiver {
158158
func renderingMetricsReceived(metrics: RenderingMetrics, screen: UIViewController) {}
159159
func appRenderingMetricsReceived(metrics: RenderingMetrics) {}
160160
}
161+
162+
private class MyViewController: UIViewController { }

0 commit comments

Comments
 (0)