From 2dba0eba61533a7e64efec7f7d738250f55d10d4 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Thu, 4 Jun 2020 15:14:17 +0800 Subject: [PATCH 1/3] Fixes UI freezes when multiple Flutter VC shared one engine --- .../darwin/ios/framework/Source/FlutterViewController.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 568a222455681..bc8f4c457e512 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -553,9 +553,11 @@ - (void)viewWillDisappear:(BOOL)animated { - (void)viewDidDisappear:(BOOL)animated { TRACE_EVENT0("flutter", "viewDidDisappear"); - [self surfaceUpdated:NO]; - [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"]; - [self flushOngoingTouches]; + if ([_engine.get() viewController] == self) { + [self surfaceUpdated:NO]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"]; + [self flushOngoingTouches]; + } [super viewDidDisappear:animated]; } From 33f9da3de2f9aee7aafacef02295276a589a6c9c Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Sat, 6 Jun 2020 16:34:16 +0800 Subject: [PATCH 2/3] Add test case --- .../framework/Source/FlutterViewControllerTest.mm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 7c986c120f46a..286502edda71d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -54,11 +54,26 @@ - (UIAccessibilityContrast)accessibilityContrast; #endif @interface FlutterViewController (Tests) +- (void)surfaceUpdated:(BOOL)appeared; - (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences; @end @implementation FlutterViewControllerTest +- (void)testMultipleFlutterViewControllerShareEngine { + FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"testEngine"]; + [engine run]; + FlutterViewController* vcA = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + __unused FlutterViewController* vcB = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + id vcMockA = OCMPartialMock(vcA); + [vcMockA viewDidDisappear:NO]; + OCMReject([vcMockA surfaceUpdated:NO]); +} + - (void)testBinaryMessenger { id engine = OCMClassMock([FlutterEngine class]); FlutterViewController* vc = [[FlutterViewController alloc] initWithEngine:engine From 6ea577fa93bc6c79b4977f0d9f966fac2ffd6902 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Mon, 8 Jun 2020 10:48:08 -0700 Subject: [PATCH 3/3] updated unit tests --- .../Source/FlutterViewControllerTest.mm | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 286502edda71d..6c5d6ff4b45a7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -60,18 +60,37 @@ - (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences; @implementation FlutterViewControllerTest -- (void)testMultipleFlutterViewControllerShareEngine { - FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"testEngine"]; - [engine run]; - FlutterViewController* vcA = [[FlutterViewController alloc] initWithEngine:engine - nibName:nil - bundle:nil]; - __unused FlutterViewController* vcB = [[FlutterViewController alloc] initWithEngine:engine - nibName:nil - bundle:nil]; - id vcMockA = OCMPartialMock(vcA); - [vcMockA viewDidDisappear:NO]; - OCMReject([vcMockA surfaceUpdated:NO]); +- (void)testViewDidDisappearDoesntPauseEngine { + id engine = OCMClassMock([FlutterEngine class]); + id lifecycleChannel = OCMClassMock([FlutterBasicMessageChannel class]); + OCMStub([engine lifecycleChannel]).andReturn(lifecycleChannel); + FlutterViewController* viewControllerA = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + FlutterViewController* viewControllerB = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + id viewControllerMock = OCMPartialMock(viewControllerA); + OCMStub([viewControllerMock surfaceUpdated:NO]); + OCMStub([engine viewController]).andReturn(viewControllerB); + [viewControllerA viewDidDisappear:NO]; + OCMReject([lifecycleChannel sendMessage:@"AppLifecycleState.paused"]); + OCMReject([viewControllerMock surfaceUpdated:[OCMArg any]]); +} + +- (void)testViewDidDisappearDoesPauseEngine { + id engine = OCMClassMock([FlutterEngine class]); + id lifecycleChannel = OCMClassMock([FlutterBasicMessageChannel class]); + OCMStub([engine lifecycleChannel]).andReturn(lifecycleChannel); + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + id viewControllerMock = OCMPartialMock(viewController); + OCMStub([viewControllerMock surfaceUpdated:NO]); + OCMStub([engine viewController]).andReturn(viewController); + [viewController viewDidDisappear:NO]; + OCMVerify([lifecycleChannel sendMessage:@"AppLifecycleState.paused"]); + OCMVerify([viewControllerMock surfaceUpdated:NO]); } - (void)testBinaryMessenger {