Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 0e8f89c

Browse files
zhongwuzwgaaclarke
andauthored
Fixes UI freezes when multiple Flutter VC shared one engine (#18816)
Co-authored-by: Aaron Clarke <[email protected]>
1 parent b1a08f2 commit 0e8f89c

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,11 @@ - (void)viewWillDisappear:(BOOL)animated {
553553

554554
- (void)viewDidDisappear:(BOOL)animated {
555555
TRACE_EVENT0("flutter", "viewDidDisappear");
556-
[self surfaceUpdated:NO];
557-
[[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"];
558-
[self flushOngoingTouches];
556+
if ([_engine.get() viewController] == self) {
557+
[self surfaceUpdated:NO];
558+
[[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"];
559+
[self flushOngoingTouches];
560+
}
559561

560562
[super viewDidDisappear:animated];
561563
}

shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,45 @@ - (UIAccessibilityContrast)accessibilityContrast;
5454
#endif
5555

5656
@interface FlutterViewController (Tests)
57+
- (void)surfaceUpdated:(BOOL)appeared;
5758
- (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences;
5859
@end
5960

6061
@implementation FlutterViewControllerTest
6162

63+
- (void)testViewDidDisappearDoesntPauseEngine {
64+
id engine = OCMClassMock([FlutterEngine class]);
65+
id lifecycleChannel = OCMClassMock([FlutterBasicMessageChannel class]);
66+
OCMStub([engine lifecycleChannel]).andReturn(lifecycleChannel);
67+
FlutterViewController* viewControllerA = [[FlutterViewController alloc] initWithEngine:engine
68+
nibName:nil
69+
bundle:nil];
70+
FlutterViewController* viewControllerB = [[FlutterViewController alloc] initWithEngine:engine
71+
nibName:nil
72+
bundle:nil];
73+
id viewControllerMock = OCMPartialMock(viewControllerA);
74+
OCMStub([viewControllerMock surfaceUpdated:NO]);
75+
OCMStub([engine viewController]).andReturn(viewControllerB);
76+
[viewControllerA viewDidDisappear:NO];
77+
OCMReject([lifecycleChannel sendMessage:@"AppLifecycleState.paused"]);
78+
OCMReject([viewControllerMock surfaceUpdated:[OCMArg any]]);
79+
}
80+
81+
- (void)testViewDidDisappearDoesPauseEngine {
82+
id engine = OCMClassMock([FlutterEngine class]);
83+
id lifecycleChannel = OCMClassMock([FlutterBasicMessageChannel class]);
84+
OCMStub([engine lifecycleChannel]).andReturn(lifecycleChannel);
85+
FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine
86+
nibName:nil
87+
bundle:nil];
88+
id viewControllerMock = OCMPartialMock(viewController);
89+
OCMStub([viewControllerMock surfaceUpdated:NO]);
90+
OCMStub([engine viewController]).andReturn(viewController);
91+
[viewController viewDidDisappear:NO];
92+
OCMVerify([lifecycleChannel sendMessage:@"AppLifecycleState.paused"]);
93+
OCMVerify([viewControllerMock surfaceUpdated:NO]);
94+
}
95+
6296
- (void)testBinaryMessenger {
6397
id engine = OCMClassMock([FlutterEngine class]);
6498
FlutterViewController* vc = [[FlutterViewController alloc] initWithEngine:engine

0 commit comments

Comments
 (0)