From db97bea01f57968190d104bc083ee1ffd0eee2ef Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 27 Sep 2018 08:57:30 -0700 Subject: [PATCH] SystemNavigator.pop can pop w/o UINavigationController (flutter/engine#6341) * SystemNavigator.pop can pop w/o UINavigationController --- .../framework/Source/FlutterPlatformPlugin.h | 7 ++++- .../framework/Source/FlutterPlatformPlugin.mm | 26 ++++++++++++++++++- .../framework/Source/FlutterViewController.mm | 6 ++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h index 6ddc181e014..09bdfa8b0ea 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h @@ -5,10 +5,15 @@ #ifndef SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMPLUGIN_H_ #define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMPLUGIN_H_ +#include "flutter/fml/memory/weak_ptr.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" -@interface FlutterPlatformPlugin : NSObject +#include +@interface FlutterPlatformPlugin : NSObject +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithViewController:(fml::WeakPtr)viewController + NS_DESIGNATED_INITIALIZER; - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result; @end diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index ccde195ae5a..54873532ae1 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" +#include "flutter/fml/logging.h" #include #include @@ -31,7 +32,26 @@ const char* const kOverlayStyleUpdateNotificationKey = using namespace shell; -@implementation FlutterPlatformPlugin +@implementation FlutterPlatformPlugin { + fml::WeakPtr _viewController; +} + +- (instancetype)init { + @throw([NSException exceptionWithName:@"FlutterPlatformPlugin must initWithViewController" + reason:nil + userInfo:nil]); +} + +- (instancetype)initWithViewController:(fml::WeakPtr)viewController { + FML_DCHECK(viewController) << "viewController must be set"; + self = [super init]; + + if (self) { + _viewController = viewController; + } + + return self; +} - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { NSString* method = call.method; @@ -178,9 +198,13 @@ using namespace shell; // Apple's human user guidelines say not to terminate iOS applications. However, if the // root view of the app is a navigation controller, it is instructed to back up a level // in the navigation hierarchy. + // It's also possible in an Add2App scenario that the FlutterViewController was presented + // outside the context of a UINavigationController, and still wants to be popped. UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController; if ([viewController isKindOfClass:[UINavigationController class]]) { [((UINavigationController*)viewController) popViewControllerAnimated:NO]; + } else if (viewController != _viewController.get()) { + [_viewController.get() dismissViewControllerAnimated:NO completion:nil]; } } diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 74b8b945589..2c42c14911e 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -8,6 +8,7 @@ #include +#include "flutter/fml/memory/weak_ptr.h" #include "flutter/fml/message_loop.h" #include "flutter/fml/platform/darwin/platform_version.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" @@ -34,6 +35,7 @@ fml::scoped_nsobject _dartProject; shell::ThreadHost _threadHost; std::unique_ptr _shell; + std::unique_ptr> _weakFactory; // Channels fml::scoped_nsobject _platformPlugin; @@ -65,6 +67,7 @@ bundle:(NSBundle*)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { + _weakFactory = std::make_unique>(self); if (projectOrNil == nil) _dartProject.reset([[FlutterDartProject alloc] init]); else @@ -209,7 +212,8 @@ binaryMessenger:self codec:[FlutterJSONMessageCodec sharedInstance]]); - _platformPlugin.reset([[FlutterPlatformPlugin alloc] init]); + _platformPlugin.reset( + [[FlutterPlatformPlugin alloc] initWithViewController:_weakFactory->GetWeakPtr()]); [_platformChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { [_platformPlugin.get() handleMethodCall:call result:result]; }];