diff --git a/packages/url_launcher/CHANGELOG.md b/packages/url_launcher/CHANGELOG.md index db2ace15b1e9..0ffbf290a5f7 100644 --- a/packages/url_launcher/CHANGELOG.md +++ b/packages/url_launcher/CHANGELOG.md @@ -1,3 +1,8 @@ + +## 5.1.3 + +* Always launch url from the top most UIViewController in iOS. + ## 5.1.2 * Update AGP and gradle. diff --git a/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m b/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m index 56681dcd1ee3..b21829867a7e 100644 --- a/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m +++ b/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m @@ -61,33 +61,16 @@ @interface FLTUrlLauncherPlugin () @end -@interface FLTUrlLauncherPlugin () - -@property(strong, nonatomic) UIViewController *viewController; - -@end - @implementation FLTUrlLauncherPlugin + (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/url_launcher" binaryMessenger:registrar.messenger]; - UIViewController *viewController = - [UIApplication sharedApplication].delegate.window.rootViewController; - FLTUrlLauncherPlugin *plugin = - [[FLTUrlLauncherPlugin alloc] initWithViewController:viewController]; + FLTUrlLauncherPlugin *plugin = [[FLTUrlLauncherPlugin alloc] init]; [registrar addMethodCallDelegate:plugin channel:channel]; } -- (instancetype)initWithViewController:(UIViewController *)viewController { - self = [super init]; - if (self) { - self.viewController = viewController; - } - return self; -} - - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { NSString *url = call.arguments[@"url"]; if ([@"canLaunch" isEqualToString:call.method]) { @@ -153,9 +136,9 @@ - (void)launchURLInVC:(NSString *)urlString result:(FlutterResult)result API_AVA self.currentSession.didFinish = ^(void) { weakSelf.currentSession = nil; }; - [self.viewController presentViewController:self.currentSession.safari - animated:YES - completion:nil]; + [self.topViewController presentViewController:self.currentSession.safari + animated:YES + completion:nil]; } - (void)closeWebViewWithResult:(FlutterResult)result API_AVAILABLE(ios(9.0)) { @@ -165,4 +148,36 @@ - (void)closeWebViewWithResult:(FlutterResult)result API_AVAILABLE(ios(9.0)) { result(nil); } +- (UIViewController *)topViewController { + return [self topViewControllerFromViewController:[UIApplication sharedApplication] + .keyWindow.rootViewController]; +} + +/** + * This method recursively iterate through the view hierarchy + * to return the top most view controller. + * + * It supports the following scenarios: + * + * - The view controller is presenting another view. + * - The view controller is a UINavigationController. + * - The view controller is a UITabBarController. + * + * @return The top most view controller. + */ +- (UIViewController *)topViewControllerFromViewController:(UIViewController *)viewController { + if ([viewController isKindOfClass:[UINavigationController class]]) { + UINavigationController *navigationController = (UINavigationController *)viewController; + return [self + topViewControllerFromViewController:[navigationController.viewControllers lastObject]]; + } + if ([viewController isKindOfClass:[UITabBarController class]]) { + UITabBarController *tabController = (UITabBarController *)viewController; + return [self topViewControllerFromViewController:tabController.selectedViewController]; + } + if (viewController.presentedViewController) { + return [self topViewControllerFromViewController:viewController.presentedViewController]; + } + return viewController; +} @end diff --git a/packages/url_launcher/pubspec.yaml b/packages/url_launcher/pubspec.yaml index f7b77db58818..34343639e9f2 100644 --- a/packages/url_launcher/pubspec.yaml +++ b/packages/url_launcher/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for launching a URL on Android and iOS. Supports web, phone, SMS, and email schemes. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher -version: 5.1.2 +version: 5.1.3 flutter: plugin: