From eceab41f644bcc7c8867946dcc0771bc5f0e24e0 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Feb 2020 13:52:59 -0800 Subject: [PATCH 01/11] Fixed the ability to scroll to the top on ios 13 by introducing a uiscrollview to FlutterViewController. --- .../framework/Source/FlutterViewController.mm | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 5b04408ec9d2c..5f536ceec26c2 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -23,6 +23,8 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" +constexpr int kMicrosecondsPerSecond = 1000 * 1000; + NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate"; NSNotificationName const FlutterViewControllerWillDealloc = @"FlutterViewControllerWillDealloc"; @@ -86,7 +88,7 @@ - (void)invalidate { // This is left a FlutterBinaryMessenger privately for now to give people a chance to notice the // change. Unfortunately unless you have Werror turned on, incompatible pointers as arguments are // just a warning. -@interface FlutterViewController () +@interface FlutterViewController () @property(nonatomic, readwrite, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI; @end @@ -329,6 +331,54 @@ - (void)loadView { self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self installSplashScreenViewIfNecessary]; + if (@available(iOS 13, *)) { + // This is a workaround on iOS 13 and higher. There isn't a way to get touches on the status + // bar to trigger scrolling to the top of a scroll view. We place a UIScrollView underneath + // the status bar with a content offset so we can get those events. + // See also: https://github.com/flutter/flutter/issues/35050 + UIScrollView* scrollView = [[UIScrollView alloc] init]; + scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; + // The color shouldn't matter since it is underneath the status bar. + scrollView.backgroundColor = [UIColor colorWithRed:255 green:255 blue:255 alpha:255]; + // Alpha can't be completely zero, otherwise we won't get events. The scroll view should be + // obscured by the status bar so this shouldn't matter. + scrollView.alpha = 0.1f; + scrollView.delegate = self; + // This is an arbitrary small size. + scrollView.contentSize = CGSizeMake(10, 10); + scrollView.opaque = NO; + // This is an arbitrary offset that is not CGPointZero. + scrollView.contentOffset = CGPointMake(10, 10); + [self.view addSubview:scrollView]; + UIStatusBarManager* manager = + [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager; + CGRect statusBarFrame = manager.statusBarFrame; + scrollView.frame = CGRectMake(0, 0, statusBarFrame.size.width, statusBarFrame.size.height); + [scrollView release]; + } +} + +static void sendFakeTouchEvent(FlutterEngine* engine, + CGPoint location, + flutter::PointerData::Change change) { + const CGFloat scale = [UIScreen mainScreen].scale; + flutter::PointerData pointer_data; + pointer_data.Clear(); + pointer_data.physical_x = location.x * scale; + pointer_data.physical_y = location.y * scale; + pointer_data.kind = flutter::PointerData::DeviceKind::kTouch; + pointer_data.time_stamp = [[NSDate date] timeIntervalSince1970] * kMicrosecondsPerSecond; + auto packet = std::make_unique(/*count=*/1); + pointer_data.change = change; + packet->SetPointerData(0, pointer_data); + [engine dispatchPointerDataPacket:std::move(packet)]; +} + +- (BOOL)scrollViewShouldScrollToTop:(UIScrollView*)scrollView { + CGPoint statusBarPoint = CGPointZero; + sendFakeTouchEvent(_engine.get(), statusBarPoint, flutter::PointerData::Change::kDown); + sendFakeTouchEvent(_engine.get(), statusBarPoint, flutter::PointerData::Change::kUp); + return NO; } #pragma mark - Managing launch views @@ -569,7 +619,6 @@ - (void)flushOngoingTouches { flutter::PointerData pointer_data; pointer_data.Clear(); - constexpr int kMicrosecondsPerSecond = 1000 * 1000; // Use current time. pointer_data.time_stamp = [[NSDate date] timeIntervalSince1970] * kMicrosecondsPerSecond; @@ -1152,6 +1201,12 @@ - (NSString*)contrastMode { constexpr CGFloat kStandardStatusBarHeight = 20.0; - (void)handleStatusBarTouches:(UIEvent*)event { + if (@available(iOS 13, *)) { + // This call shouldn't be happening as of iOS 13, to be safe we ignore it, + // scrollViewShouldScrollToTop: will handle this functionality. + // See also: https://github.com/flutter/flutter/issues/35050 + return; + } CGFloat standardStatusBarHeight = kStandardStatusBarHeight; if (@available(iOS 11, *)) { standardStatusBarHeight = self.view.safeAreaInsets.top; From c2a7861ad10c284f47beb63f51ffc7521d946a74 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Feb 2020 15:22:58 -0800 Subject: [PATCH 02/11] Removed old code for handling tapping the statusbar, tested on 10.3.1. --- .../framework/Headers/FlutterAppDelegate.h | 9 -- .../framework/Headers/FlutterViewController.h | 2 - .../framework/Source/FlutterAppDelegate.mm | 9 -- .../framework/Source/FlutterViewController.mm | 88 +++++-------------- 4 files changed, 21 insertions(+), 87 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h b/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h index 9c534a6fc80e0..8684a22ea7733 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h @@ -29,15 +29,6 @@ FLUTTER_EXPORT @property(strong, nonatomic) UIWindow* window; -/** - * Handle StatusBar touches. - * - * Call this from your AppDelegate's `touchesBegan:withEvent:` to have Flutter respond to StatusBar - * touches. For example, to enable scroll-to-top behavior. FlutterAppDelegate already calls it so - * you only need to manually call it if you aren't using a FlutterAppDelegate. - */ -+ (void)handleStatusBarTouches:(NSSet*)touches withEvent:(UIEvent*)event; - @end #endif // FLUTTER_FLUTTERDARTPROJECT_H_ diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h index b0f7df28614e0..9753cdb68bca0 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h @@ -72,8 +72,6 @@ FLUTTER_EXPORT nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER; -- (void)handleStatusBarTouches:(UIEvent*)event; - /** * Registers a callback that will be invoked when the Flutter view has been rendered. * The callback will be fired only once. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index b4c750171485f..42a4081cca13c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -48,15 +48,6 @@ + (FlutterViewController*)rootFlutterViewController { return nil; } -+ (void)handleStatusBarTouches:(NSSet*)touches withEvent:(UIEvent*)event { - [self.rootFlutterViewController handleStatusBarTouches:event]; -} - -- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { - [super touchesBegan:touches withEvent:event]; - [[self class] handleStatusBarTouches:touches withEvent:event]; -} - // Do not remove, some clients may be calling these via `super`. - (void)applicationDidEnterBackground:(UIApplication*)application { } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 5f536ceec26c2..495a136d13055 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -125,6 +125,7 @@ @implementation FlutterViewController { // Coalescer that filters out superfluous keyboard notifications when the app // is being foregrounded. fml::scoped_nsobject _updateViewportMetrics; + fml::scoped_nsobject _scrollView; } @synthesize displayingFlutterUI = _displayingFlutterUI; @@ -331,31 +332,24 @@ - (void)loadView { self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self installSplashScreenViewIfNecessary]; - if (@available(iOS 13, *)) { - // This is a workaround on iOS 13 and higher. There isn't a way to get touches on the status - // bar to trigger scrolling to the top of a scroll view. We place a UIScrollView underneath - // the status bar with a content offset so we can get those events. - // See also: https://github.com/flutter/flutter/issues/35050 - UIScrollView* scrollView = [[UIScrollView alloc] init]; - scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; - // The color shouldn't matter since it is underneath the status bar. - scrollView.backgroundColor = [UIColor colorWithRed:255 green:255 blue:255 alpha:255]; - // Alpha can't be completely zero, otherwise we won't get events. The scroll view should be - // obscured by the status bar so this shouldn't matter. - scrollView.alpha = 0.1f; - scrollView.delegate = self; - // This is an arbitrary small size. - scrollView.contentSize = CGSizeMake(10, 10); - scrollView.opaque = NO; - // This is an arbitrary offset that is not CGPointZero. - scrollView.contentOffset = CGPointMake(10, 10); - [self.view addSubview:scrollView]; - UIStatusBarManager* manager = - [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager; - CGRect statusBarFrame = manager.statusBarFrame; - scrollView.frame = CGRectMake(0, 0, statusBarFrame.size.width, statusBarFrame.size.height); - [scrollView release]; - } + // This is a workaround on iOS 13 and higher. There isn't a way to get touches on the status + // bar to trigger scrolling to the top of a scroll view. We place a UIScrollView underneath + // the status bar with a content offset so we can get those events. + // See also: https://github.com/flutter/flutter/issues/35050 + UIScrollView* scrollView = [[UIScrollView alloc] init]; + scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; + // The color shouldn't matter since it is underneath the status bar. + scrollView.backgroundColor = UIColor.whiteColor; + // Alpha can't be completely zero, otherwise we won't get events. The scroll view should be + // obscured by the status bar so this shouldn't matter. + scrollView.delegate = self; + // This is an arbitrary small size. + scrollView.contentSize = CGSizeMake(10, 10); + // This is an arbitrary offset that is not CGPointZero. + scrollView.contentOffset = CGPointMake(10, 10); + scrollView.bounds = CGRectMake(0, -10, 0, 10); + [self.view addSubview:scrollView]; + _scrollView.reset(scrollView); } static void sendFakeTouchEvent(FlutterEngine* engine, @@ -884,6 +878,8 @@ - (void)viewDidLayoutSubviews { CGSize viewSize = self.view.bounds.size; CGFloat scale = [UIScreen mainScreen].scale; + _scrollView.get().bounds = CGRectMake(0.0, -10.0, viewSize.width, 0); + // First time since creation that the dimensions of its view is known. bool firstViewBoundsUpdate = !_viewportMetrics.physical_width; _viewportMetrics.device_pixel_ratio = scale; @@ -1195,48 +1191,6 @@ - (NSString*)contrastMode { } } -#pragma mark - Status Bar touch event handling - -// Standard iOS status bar height in points. -constexpr CGFloat kStandardStatusBarHeight = 20.0; - -- (void)handleStatusBarTouches:(UIEvent*)event { - if (@available(iOS 13, *)) { - // This call shouldn't be happening as of iOS 13, to be safe we ignore it, - // scrollViewShouldScrollToTop: will handle this functionality. - // See also: https://github.com/flutter/flutter/issues/35050 - return; - } - CGFloat standardStatusBarHeight = kStandardStatusBarHeight; - if (@available(iOS 11, *)) { - standardStatusBarHeight = self.view.safeAreaInsets.top; - } - - // If the status bar is double-height, don't handle status bar taps. iOS - // should open the app associated with the status bar. - CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; - if (statusBarFrame.size.height != standardStatusBarHeight) { - return; - } - - // If we detect a touch in the status bar, synthesize a fake touch begin/end. - for (UITouch* touch in event.allTouches) { - if (touch.phase == UITouchPhaseBegan && touch.tapCount > 0) { - CGPoint windowLoc = [touch locationInView:nil]; - CGPoint screenLoc = [touch.window convertPoint:windowLoc toWindow:nil]; - if (CGRectContainsPoint(statusBarFrame, screenLoc)) { - NSSet* statusbarTouches = [NSSet setWithObject:touch]; - - flutter::PointerData::Change change = flutter::PointerData::Change::kDown; - [self dispatchTouches:statusbarTouches pointerDataChangeOverride:&change]; - change = flutter::PointerData::Change::kUp; - [self dispatchTouches:statusbarTouches pointerDataChangeOverride:&change]; - return; - } - } - } -} - #pragma mark - Status bar style - (UIStatusBarStyle)preferredStatusBarStyle { From b861affc78ee0f305ec6650509aec6cc30fbc346 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Feb 2020 15:27:11 -0800 Subject: [PATCH 03/11] Updated comments. --- .../darwin/ios/framework/Source/FlutterViewController.mm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 495a136d13055..225d670ef82b6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -338,15 +338,14 @@ - (void)loadView { // See also: https://github.com/flutter/flutter/issues/35050 UIScrollView* scrollView = [[UIScrollView alloc] init]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; - // The color shouldn't matter since it is underneath the status bar. + // The color shouldn't matter since it is offscreen. scrollView.backgroundColor = UIColor.whiteColor; - // Alpha can't be completely zero, otherwise we won't get events. The scroll view should be - // obscured by the status bar so this shouldn't matter. scrollView.delegate = self; // This is an arbitrary small size. scrollView.contentSize = CGSizeMake(10, 10); // This is an arbitrary offset that is not CGPointZero. scrollView.contentOffset = CGPointMake(10, 10); + // This is some aribrary place offscreen. scrollView.bounds = CGRectMake(0, -10, 0, 10); [self.view addSubview:scrollView]; _scrollView.reset(scrollView); From 1db613a19e5a9081ffa88bbfbd93cc2440433f03 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Feb 2020 15:32:03 -0800 Subject: [PATCH 04/11] updated comments again --- .../darwin/ios/framework/Source/FlutterViewController.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 225d670ef82b6..4f2d09247b2ae 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -332,10 +332,10 @@ - (void)loadView { self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self installSplashScreenViewIfNecessary]; - // This is a workaround on iOS 13 and higher. There isn't a way to get touches on the status - // bar to trigger scrolling to the top of a scroll view. We place a UIScrollView underneath - // the status bar with a content offset so we can get those events. - // See also: https://github.com/flutter/flutter/issues/35050 + // This is a workaround to accomodate iOS 13 and higher. There isn't a way to get touches on the + // status bar to trigger scrolling to the top of a scroll view. We place a UIScrollView offscreen + // with a content offset so we can get those events. See also: + // https://github.com/flutter/flutter/issues/35050 UIScrollView* scrollView = [[UIScrollView alloc] init]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; // The color shouldn't matter since it is offscreen. From f182e105a63eafc254cd8b4a59536f46606beffd Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 26 Feb 2020 15:36:30 -0800 Subject: [PATCH 05/11] added comment --- .../darwin/ios/framework/Source/FlutterViewController.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 4f2d09247b2ae..d047fd6bbe83a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -877,6 +877,7 @@ - (void)viewDidLayoutSubviews { CGSize viewSize = self.view.bounds.size; CGFloat scale = [UIScreen mainScreen].scale; + // Purposefully place this offscreen. _scrollView.get().bounds = CGRectMake(0.0, -10.0, viewSize.width, 0); // First time since creation that the dimensions of its view is known. From 663b804ffe9082fab6099193ddb0f04d780545d8 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Mar 2020 11:41:49 -0800 Subject: [PATCH 06/11] made the scroll view have height zero --- .../framework/Source/FlutterViewController.mm | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index d047fd6bbe83a..55cb34264a64a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -24,6 +24,7 @@ #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" constexpr int kMicrosecondsPerSecond = 1000 * 1000; +constexpr CGFloat kScrollViewContentSize = 10.0; NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate"; @@ -333,8 +334,8 @@ - (void)loadView { [self installSplashScreenViewIfNecessary]; // This is a workaround to accomodate iOS 13 and higher. There isn't a way to get touches on the - // status bar to trigger scrolling to the top of a scroll view. We place a UIScrollView offscreen - // with a content offset so we can get those events. See also: + // status bar to trigger scrolling to the top of a scroll view. We place a UIScrollView with + // height zero and a content offset so we can get those events. See also: // https://github.com/flutter/flutter/issues/35050 UIScrollView* scrollView = [[UIScrollView alloc] init]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; @@ -342,11 +343,11 @@ - (void)loadView { scrollView.backgroundColor = UIColor.whiteColor; scrollView.delegate = self; // This is an arbitrary small size. - scrollView.contentSize = CGSizeMake(10, 10); + scrollView.contentSize = CGSizeMake(kScrollViewContentSize, kScrollViewContentSize); // This is an arbitrary offset that is not CGPointZero. - scrollView.contentOffset = CGPointMake(10, 10); // This is some aribrary place offscreen. - scrollView.bounds = CGRectMake(0, -10, 0, 10); + scrollView.frame = CGRectMake(0, 0, 0, 0); + scrollView.contentOffset = CGPointMake(kScrollViewContentSize, kScrollViewContentSize); [self.view addSubview:scrollView]; _scrollView.reset(scrollView); } @@ -877,8 +878,9 @@ - (void)viewDidLayoutSubviews { CGSize viewSize = self.view.bounds.size; CGFloat scale = [UIScreen mainScreen].scale; - // Purposefully place this offscreen. - _scrollView.get().bounds = CGRectMake(0.0, -10.0, viewSize.width, 0); + // Purposefully place this not visible. + _scrollView.get().frame = CGRectMake(0.0, 0.0, viewSize.width, 0.0); + _scrollView.get().contentOffset = CGPointMake(kScrollViewContentSize, kScrollViewContentSize); // First time since creation that the dimensions of its view is known. bool firstViewBoundsUpdate = !_viewportMetrics.physical_width; From 7cc5adb6fd50ac4fef79d90d052e0a90f06427d3 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Mar 2020 17:21:32 -0800 Subject: [PATCH 07/11] made consts static --- .../darwin/ios/framework/Source/FlutterViewController.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 55cb34264a64a..6ea0ef2f7eb14 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -23,8 +23,8 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" -constexpr int kMicrosecondsPerSecond = 1000 * 1000; -constexpr CGFloat kScrollViewContentSize = 10.0; +static constexpr int kMicrosecondsPerSecond = 1000 * 1000; +static constexpr CGFloat kScrollViewContentSize = 2.0; NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate"; From 944c0ed52d25ea8a33463e0fe797ce3af45db0d0 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Mar 2020 17:29:40 -0800 Subject: [PATCH 08/11] added ui test --- .../ios/Flutter/Generated.xcconfig | 9 +++++ .../ios/Flutter/flutter_export_environment.sh | 10 +++++ .../Scenarios.xcodeproj/project.pbxproj | 6 +++ .../ios/Scenarios/Scenarios/AppDelegate.m | 16 +++++++- .../ScenariosUITests/StatusBarTest.h | 13 ++++++ .../ScenariosUITests/StatusBarTest.m | 40 +++++++++++++++++++ testing/scenario_app/lib/main.dart | 2 + .../lib/src/touches_scenario.dart | 31 ++++++++++++++ 8 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 testing/scenario_app/ios/Flutter/Generated.xcconfig create mode 100755 testing/scenario_app/ios/Flutter/flutter_export_environment.sh create mode 100644 testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.h create mode 100644 testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m create mode 100644 testing/scenario_app/lib/src/touches_scenario.dart diff --git a/testing/scenario_app/ios/Flutter/Generated.xcconfig b/testing/scenario_app/ios/Flutter/Generated.xcconfig new file mode 100644 index 0000000000000..7efd5b72e66c6 --- /dev/null +++ b/testing/scenario_app/ios/Flutter/Generated.xcconfig @@ -0,0 +1,9 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=/Users/aaclarke/dev/flutter +FLUTTER_APPLICATION_PATH=/Users/aaclarke/dev/engine/src/flutter/testing/scenario_app +FLUTTER_TARGET=lib/main.dart +FLUTTER_BUILD_DIR=build +SYMROOT=${SOURCE_ROOT}/../build/ios +FLUTTER_FRAMEWORK_DIR=/Users/aaclarke/dev/flutter/bin/cache/artifacts/engine/ios +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 diff --git a/testing/scenario_app/ios/Flutter/flutter_export_environment.sh b/testing/scenario_app/ios/Flutter/flutter_export_environment.sh new file mode 100755 index 0000000000000..01207b23d4467 --- /dev/null +++ b/testing/scenario_app/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/Users/aaclarke/dev/flutter" +export "FLUTTER_APPLICATION_PATH=/Users/aaclarke/dev/engine/src/flutter/testing/scenario_app" +export "FLUTTER_TARGET=lib/main.dart" +export "FLUTTER_BUILD_DIR=build" +export "SYMROOT=${SOURCE_ROOT}/../build/ios" +export "FLUTTER_FRAMEWORK_DIR=/Users/aaclarke/dev/flutter/bin/cache/artifacts/engine/ios" +export "FLUTTER_BUILD_NAME=1.0.0" +export "FLUTTER_BUILD_NUMBER=1" diff --git a/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj b/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj index 5da90fd32a674..8f95dec91db4f 100644 --- a/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj +++ b/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 0A57B3BF2323C74200DD9521 /* FlutterEngine+ScenariosTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A57B3BE2323C74200DD9521 /* FlutterEngine+ScenariosTest.m */; }; 0A57B3C22323D2D700DD9521 /* AppLifecycleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A57B3C12323D2D700DD9521 /* AppLifecycleTests.m */; }; 0D14A3FE239743190013D873 /* golden_platform_view_rotate_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 0D14A3FD239743190013D873 /* golden_platform_view_rotate_iPhone SE_simulator.png */; }; + 0D8470A4240F0B1F0030B565 /* StatusBarTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D8470A3240F0B1F0030B565 /* StatusBarTest.m */; }; 0DB781EF22E931BE00E9B371 /* Flutter.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 246B4E4522E3B61000073EBF /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 0DB781F122E933E800E9B371 /* Flutter.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 246B4E4522E3B61000073EBF /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 0DB781FE22EA2C6D00E9B371 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 246B4E4522E3B61000073EBF /* Flutter.framework */; }; @@ -114,6 +115,8 @@ 0A57B3C02323C74D00DD9521 /* FlutterEngine+ScenariosTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FlutterEngine+ScenariosTest.h"; sourceTree = ""; }; 0A57B3C12323D2D700DD9521 /* AppLifecycleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppLifecycleTests.m; sourceTree = ""; }; 0D14A3FD239743190013D873 /* golden_platform_view_rotate_iPhone SE_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_platform_view_rotate_iPhone SE_simulator.png"; sourceTree = ""; }; + 0D8470A2240F0B1F0030B565 /* StatusBarTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StatusBarTest.h; sourceTree = ""; }; + 0D8470A3240F0B1F0030B565 /* StatusBarTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StatusBarTest.m; sourceTree = ""; }; 0DB781FC22EA2C0300E9B371 /* FlutterViewControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlutterViewControllerTest.m; sourceTree = ""; }; 244EA6CF230DBE8900B2D26E /* golden_platform_view_D21AP.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = golden_platform_view_D21AP.png; sourceTree = ""; }; 246B4E4122E3B5F700073EBF /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = App.framework; sourceTree = ""; }; @@ -272,6 +275,8 @@ 6816DBA22318358200A51400 /* PlatformViewGoldenTestManager.h */, 6816DBA32318358200A51400 /* PlatformViewGoldenTestManager.m */, 68A5B63323EB71D300BDBCDB /* PlatformViewGestureRecognizerTests.m */, + 0D8470A2240F0B1F0030B565 /* StatusBarTest.h */, + 0D8470A3240F0B1F0030B565 /* StatusBarTest.m */, ); path = ScenariosUITests; sourceTree = ""; @@ -466,6 +471,7 @@ 6816DB9E231750ED00A51400 /* GoldenPlatformViewTests.m in Sources */, 6816DBA42318358200A51400 /* PlatformViewGoldenTestManager.m in Sources */, 248D76EF22E388380012F0C1 /* PlatformViewUITests.m in Sources */, + 0D8470A4240F0B1F0030B565 /* StatusBarTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m b/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m index 8805ad80bd644..55559ec52b190 100644 --- a/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m +++ b/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m @@ -41,6 +41,7 @@ - (BOOL)application:(UIApplication*)application @"--gesture-reject-after-touches-ended" : @"platform_view_gesture_reject_after_touches_ended", @"--gesture-reject-eager" : @"platform_view_gesture_reject_eager", @"--gesture-accept" : @"platform_view_gesture_accept", + @"--tap-status-bar" : @"tap_status_bar", }; __block NSString* platformViewTestName = nil; [launchArgsMap @@ -67,8 +68,12 @@ - (void)readyContextForPlatformViewTests:(NSString*)scenarioIdentifier { FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"PlatformViewTest" project:nil]; [engine runWithEntrypoint:nil]; - FlutterViewController* flutterViewController = - [[NoStatusBarFlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + FlutterViewController* flutterViewController; + if ([scenarioIdentifier isEqualToString:@"tap_status_bar"]) { + flutterViewController = [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + } else { + flutterViewController = [[NoStatusBarFlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + } [engine.binaryMessenger setMessageHandlerOnChannel:@"scenario_status" binaryMessageHandler:^(NSData* _Nullable message, FlutterBinaryReply _Nonnull reply) { @@ -76,6 +81,13 @@ - (void)readyContextForPlatformViewTests:(NSString*)scenarioIdentifier { sendOnChannel:@"set_scenario" message:[scenarioIdentifier dataUsingEncoding:NSUTF8StringEncoding]]; }]; + [engine.binaryMessenger + setMessageHandlerOnChannel:@"touches_scenario" binaryMessageHandler:^(NSData * _Nullable message, FlutterBinaryReply _Nonnull reply) { + NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:message options:0 error:nil]; + UITextField* text = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 300, 100)]; + text.text = dict[@"change"]; + [flutterViewController.view addSubview:text]; + }]; TextPlatformViewFactory* textPlatformViewFactory = [[TextPlatformViewFactory alloc] initWithMessenger:flutterViewController.binaryMessenger]; NSObject* registrar = diff --git a/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.h b/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.h new file mode 100644 index 0000000000000..03ff9a1c662cd --- /dev/null +++ b/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.h @@ -0,0 +1,13 @@ +// Copyright 2020 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface StatusBarTest : XCTestCase +@property(nonatomic, strong) XCUIApplication* application; +@end + +NS_ASSUME_NONNULL_END diff --git a/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m b/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m new file mode 100644 index 0000000000000..7e4a8d32633ae --- /dev/null +++ b/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m @@ -0,0 +1,40 @@ +// Copyright 2020 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "StatusBarTest.h" + +@implementation StatusBarTest + +- (void)setUp { + [super setUp]; + self.continueAfterFailure = NO; + + self.application = [[XCUIApplication alloc] init]; + self.application.launchArguments = @[ @"--tap-status-bar" ]; + [self.application launch]; +} + +-(void)testTapStatusBar { + if (@available(iOS 13, *)) { + XCUIApplication* systemApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.springboard"]; + XCUIElement* statusBar = [systemApp.statusBars firstMatch]; + if (statusBar.isHittable) { + [statusBar tap]; + } else { + XCUICoordinate* coordinates = [statusBar coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; + [coordinates tap]; + } + } else { + [[self.application.statusBars firstMatch] tap]; + } + + XCUIElement* addTextField = self.application.textFields[@"PointerChange.add"]; + BOOL exists = [addTextField waitForExistenceWithTimeout:1]; + XCTAssertTrue(exists, @""); + XCUIElement* upTextField = self.application.textFields[@"PointerChange.up"]; + exists = [upTextField waitForExistenceWithTimeout:1]; + XCTAssertTrue(exists, @""); +} + +@end diff --git a/testing/scenario_app/lib/main.dart b/testing/scenario_app/lib/main.dart index 8523234f940f7..494d6585aa7fe 100644 --- a/testing/scenario_app/lib/main.dart +++ b/testing/scenario_app/lib/main.dart @@ -14,6 +14,7 @@ import 'src/animated_color_square.dart'; import 'src/platform_view.dart'; import 'src/poppable_screen.dart'; import 'src/scenario.dart'; +import 'src/touches_scenario.dart'; Map _scenarios = { 'animated_color_square': AnimatedColorSquareScenario(window), @@ -30,6 +31,7 @@ Map _scenarios = { 'platform_view_gesture_reject_eager': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: false), 'platform_view_gesture_accept': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: true), 'platform_view_gesture_reject_after_touches_ended': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: false, rejectUntilTouchesEnded: true), + 'tap_status_bar' : TouchesScenario(window), }; Scenario _currentScenario = _scenarios['animated_color_square']; diff --git a/testing/scenario_app/lib/src/touches_scenario.dart b/testing/scenario_app/lib/src/touches_scenario.dart new file mode 100644 index 0000000000000..d0148ef5a28d9 --- /dev/null +++ b/testing/scenario_app/lib/src/touches_scenario.dart @@ -0,0 +1,31 @@ +// Copyright 2020 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; +import 'dart:ui'; + +import 'scenario.dart'; + +/// A scenario that sends back messages when touches are received. +class TouchesScenario extends Scenario { + /// Constructor for `TouchesScenario`. + TouchesScenario(Window window) : super(window); + + @override + void onBeginFrame(Duration duration) {} + + @override + void onPointerDataPacket(PointerDataPacket packet) { + window.sendPlatformMessage( + 'touches_scenario', + utf8.encoder + .convert(const JsonCodec().encode({ + 'change': packet.data[0].change.toString(), + })) + .buffer + .asByteData(), + null, + ); + } +} From 3eeeeb987ef6e2e9dda3d8fc36cc3a064071caa4 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Mar 2020 17:59:57 -0800 Subject: [PATCH 09/11] moved comment --- .../framework/Source/FlutterViewController.mm | 11 ++++----- .../ios/Scenarios/Scenarios/AppDelegate.m | 23 ++++++++++++------- .../ScenariosUITests/StatusBarTest.m | 5 ++-- testing/scenario_app/run_ios_tests.sh | 4 +++- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 6ea0ef2f7eb14..0a211391693ca 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -126,6 +126,11 @@ @implementation FlutterViewController { // Coalescer that filters out superfluous keyboard notifications when the app // is being foregrounded. fml::scoped_nsobject _updateViewportMetrics; + // This scroll view is a workaround to accomodate iOS 13 and higher. There isn't a way to get + // touches on the status bar to trigger scrolling to the top of a scroll view. We place a + // UIScrollView with height zero and a content offset so we can get those events. See also: + // https://github.com/flutter/flutter/issues/35050 + fml::scoped_nsobject _scrollView; } @@ -333,10 +338,6 @@ - (void)loadView { self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self installSplashScreenViewIfNecessary]; - // This is a workaround to accomodate iOS 13 and higher. There isn't a way to get touches on the - // status bar to trigger scrolling to the top of a scroll view. We place a UIScrollView with - // height zero and a content offset so we can get those events. See also: - // https://github.com/flutter/flutter/issues/35050 UIScrollView* scrollView = [[UIScrollView alloc] init]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; // The color shouldn't matter since it is offscreen. @@ -345,8 +346,6 @@ - (void)loadView { // This is an arbitrary small size. scrollView.contentSize = CGSizeMake(kScrollViewContentSize, kScrollViewContentSize); // This is an arbitrary offset that is not CGPointZero. - // This is some aribrary place offscreen. - scrollView.frame = CGRectMake(0, 0, 0, 0); scrollView.contentOffset = CGPointMake(kScrollViewContentSize, kScrollViewContentSize); [self.view addSubview:scrollView]; _scrollView.reset(scrollView); diff --git a/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m b/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m index 55559ec52b190..348889b19b856 100644 --- a/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m +++ b/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m @@ -70,9 +70,13 @@ - (void)readyContextForPlatformViewTests:(NSString*)scenarioIdentifier { FlutterViewController* flutterViewController; if ([scenarioIdentifier isEqualToString:@"tap_status_bar"]) { - flutterViewController = [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + flutterViewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; } else { - flutterViewController = [[NoStatusBarFlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + flutterViewController = [[NoStatusBarFlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; } [engine.binaryMessenger setMessageHandlerOnChannel:@"scenario_status" @@ -82,12 +86,15 @@ - (void)readyContextForPlatformViewTests:(NSString*)scenarioIdentifier { message:[scenarioIdentifier dataUsingEncoding:NSUTF8StringEncoding]]; }]; [engine.binaryMessenger - setMessageHandlerOnChannel:@"touches_scenario" binaryMessageHandler:^(NSData * _Nullable message, FlutterBinaryReply _Nonnull reply) { - NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:message options:0 error:nil]; - UITextField* text = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 300, 100)]; - text.text = dict[@"change"]; - [flutterViewController.view addSubview:text]; - }]; + setMessageHandlerOnChannel:@"touches_scenario" + binaryMessageHandler:^(NSData* _Nullable message, FlutterBinaryReply _Nonnull reply) { + NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:message + options:0 + error:nil]; + UITextField* text = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 300, 100)]; + text.text = dict[@"change"]; + [flutterViewController.view addSubview:text]; + }]; TextPlatformViewFactory* textPlatformViewFactory = [[TextPlatformViewFactory alloc] initWithMessenger:flutterViewController.binaryMessenger]; NSObject* registrar = diff --git a/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m b/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m index 7e4a8d32633ae..5192b62e461fc 100644 --- a/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m +++ b/testing/scenario_app/ios/Scenarios/ScenariosUITests/StatusBarTest.m @@ -15,9 +15,10 @@ - (void)setUp { [self.application launch]; } --(void)testTapStatusBar { +- (void)testTapStatusBar { if (@available(iOS 13, *)) { - XCUIApplication* systemApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.springboard"]; + XCUIApplication* systemApp = + [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.springboard"]; XCUIElement* statusBar = [systemApp.statusBars firstMatch]; if (statusBar.isHittable) { [statusBar tap]; diff --git a/testing/scenario_app/run_ios_tests.sh b/testing/scenario_app/run_ios_tests.sh index fd9a548f4751e..7d4be35423026 100755 --- a/testing/scenario_app/run_ios_tests.sh +++ b/testing/scenario_app/run_ios_tests.sh @@ -19,9 +19,11 @@ cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd pushd ios/Scenarios +exit 1 + set -o pipefail && xcodebuild -sdk iphonesimulator \ -scheme Scenarios \ - -destination 'platform=iOS Simulator,OS=13.0,name=iPhone 8' \ + -destination 'platform=iOS Simulator,OS=13.3,name=iPhone 8' \ test \ FLUTTER_ENGINE=$FLUTTER_ENGINE | $PRETTY From e520d3044d024991e7331938560203e2e8df8873 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Mar 2020 18:04:21 -0800 Subject: [PATCH 10/11] reverted accidental commits --- testing/scenario_app/ios/Flutter/Generated.xcconfig | 9 --------- .../ios/Flutter/flutter_export_environment.sh | 10 ---------- testing/scenario_app/run_ios_tests.sh | 4 +--- 3 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 testing/scenario_app/ios/Flutter/Generated.xcconfig delete mode 100755 testing/scenario_app/ios/Flutter/flutter_export_environment.sh diff --git a/testing/scenario_app/ios/Flutter/Generated.xcconfig b/testing/scenario_app/ios/Flutter/Generated.xcconfig deleted file mode 100644 index 7efd5b72e66c6..0000000000000 --- a/testing/scenario_app/ios/Flutter/Generated.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -// This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=/Users/aaclarke/dev/flutter -FLUTTER_APPLICATION_PATH=/Users/aaclarke/dev/engine/src/flutter/testing/scenario_app -FLUTTER_TARGET=lib/main.dart -FLUTTER_BUILD_DIR=build -SYMROOT=${SOURCE_ROOT}/../build/ios -FLUTTER_FRAMEWORK_DIR=/Users/aaclarke/dev/flutter/bin/cache/artifacts/engine/ios -FLUTTER_BUILD_NAME=1.0.0 -FLUTTER_BUILD_NUMBER=1 diff --git a/testing/scenario_app/ios/Flutter/flutter_export_environment.sh b/testing/scenario_app/ios/Flutter/flutter_export_environment.sh deleted file mode 100755 index 01207b23d4467..0000000000000 --- a/testing/scenario_app/ios/Flutter/flutter_export_environment.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/aaclarke/dev/flutter" -export "FLUTTER_APPLICATION_PATH=/Users/aaclarke/dev/engine/src/flutter/testing/scenario_app" -export "FLUTTER_TARGET=lib/main.dart" -export "FLUTTER_BUILD_DIR=build" -export "SYMROOT=${SOURCE_ROOT}/../build/ios" -export "FLUTTER_FRAMEWORK_DIR=/Users/aaclarke/dev/flutter/bin/cache/artifacts/engine/ios" -export "FLUTTER_BUILD_NAME=1.0.0" -export "FLUTTER_BUILD_NUMBER=1" diff --git a/testing/scenario_app/run_ios_tests.sh b/testing/scenario_app/run_ios_tests.sh index 7d4be35423026..fd9a548f4751e 100755 --- a/testing/scenario_app/run_ios_tests.sh +++ b/testing/scenario_app/run_ios_tests.sh @@ -19,11 +19,9 @@ cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd pushd ios/Scenarios -exit 1 - set -o pipefail && xcodebuild -sdk iphonesimulator \ -scheme Scenarios \ - -destination 'platform=iOS Simulator,OS=13.3,name=iPhone 8' \ + -destination 'platform=iOS Simulator,OS=13.0,name=iPhone 8' \ test \ FLUTTER_ENGINE=$FLUTTER_ENGINE | $PRETTY From 0c88a32f4196257224789625f40a731428f86aab Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 4 Mar 2020 10:01:33 -0800 Subject: [PATCH 11/11] removed whitespace --- .../darwin/ios/framework/Source/FlutterViewController.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 0a211391693ca..470811a5a8882 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -130,7 +130,6 @@ @implementation FlutterViewController { // touches on the status bar to trigger scrolling to the top of a scroll view. We place a // UIScrollView with height zero and a content offset so we can get those events. See also: // https://github.com/flutter/flutter/issues/35050 - fml::scoped_nsobject _scrollView; }