diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h index 6ddc181e0149d..09bdfa8b0ea47 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h +++ b/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/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index ccde195ae5a2f..54873532ae18b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/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 @@ 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 @@ - (void)popSystemNavigator { // 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/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 74b8b9455892a..2c42c14911e57 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/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 @@ @implementation FlutterViewController { fml::scoped_nsobject _dartProject; shell::ThreadHost _threadHost; std::unique_ptr _shell; + std::unique_ptr> _weakFactory; // Channels fml::scoped_nsobject _platformPlugin; @@ -65,6 +67,7 @@ - (instancetype)initWithProject:(FlutterDartProject*)projectOrNil 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 @@ - (void)setupChannels { 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]; }];