Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit f7193bc

Browse files
vitor-gyantMichael Klimushyn
authored andcommitted
[url_launcher] Removed reference to rootViewController during initialization (#2038)
The current plugin implementation stores a reference to the rootViewController during the initialisation which breaks scenarios like app2app. This PR does not store any variable to rootViewController but search through the VC hierarchy to get the top most VC in order to present the new vc.
1 parent 283284f commit f7193bc

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

packages/url_launcher/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2+
## 5.1.3
3+
4+
* Always launch url from the top most UIViewController in iOS.
5+
16
## 5.1.2
27

38
* Update AGP and gradle.

packages/url_launcher/ios/Classes/UrlLauncherPlugin.m

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,33 +61,16 @@ @interface FLTUrlLauncherPlugin ()
6161

6262
@end
6363

64-
@interface FLTUrlLauncherPlugin ()
65-
66-
@property(strong, nonatomic) UIViewController *viewController;
67-
68-
@end
69-
7064
@implementation FLTUrlLauncherPlugin
7165

7266
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
7367
FlutterMethodChannel *channel =
7468
[FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/url_launcher"
7569
binaryMessenger:registrar.messenger];
76-
UIViewController *viewController =
77-
[UIApplication sharedApplication].delegate.window.rootViewController;
78-
FLTUrlLauncherPlugin *plugin =
79-
[[FLTUrlLauncherPlugin alloc] initWithViewController:viewController];
70+
FLTUrlLauncherPlugin *plugin = [[FLTUrlLauncherPlugin alloc] init];
8071
[registrar addMethodCallDelegate:plugin channel:channel];
8172
}
8273

83-
- (instancetype)initWithViewController:(UIViewController *)viewController {
84-
self = [super init];
85-
if (self) {
86-
self.viewController = viewController;
87-
}
88-
return self;
89-
}
90-
9174
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
9275
NSString *url = call.arguments[@"url"];
9376
if ([@"canLaunch" isEqualToString:call.method]) {
@@ -153,9 +136,9 @@ - (void)launchURLInVC:(NSString *)urlString result:(FlutterResult)result API_AVA
153136
self.currentSession.didFinish = ^(void) {
154137
weakSelf.currentSession = nil;
155138
};
156-
[self.viewController presentViewController:self.currentSession.safari
157-
animated:YES
158-
completion:nil];
139+
[self.topViewController presentViewController:self.currentSession.safari
140+
animated:YES
141+
completion:nil];
159142
}
160143

161144
- (void)closeWebViewWithResult:(FlutterResult)result API_AVAILABLE(ios(9.0)) {
@@ -165,4 +148,36 @@ - (void)closeWebViewWithResult:(FlutterResult)result API_AVAILABLE(ios(9.0)) {
165148
result(nil);
166149
}
167150

151+
- (UIViewController *)topViewController {
152+
return [self topViewControllerFromViewController:[UIApplication sharedApplication]
153+
.keyWindow.rootViewController];
154+
}
155+
156+
/**
157+
* This method recursively iterate through the view hierarchy
158+
* to return the top most view controller.
159+
*
160+
* It supports the following scenarios:
161+
*
162+
* - The view controller is presenting another view.
163+
* - The view controller is a UINavigationController.
164+
* - The view controller is a UITabBarController.
165+
*
166+
* @return The top most view controller.
167+
*/
168+
- (UIViewController *)topViewControllerFromViewController:(UIViewController *)viewController {
169+
if ([viewController isKindOfClass:[UINavigationController class]]) {
170+
UINavigationController *navigationController = (UINavigationController *)viewController;
171+
return [self
172+
topViewControllerFromViewController:[navigationController.viewControllers lastObject]];
173+
}
174+
if ([viewController isKindOfClass:[UITabBarController class]]) {
175+
UITabBarController *tabController = (UITabBarController *)viewController;
176+
return [self topViewControllerFromViewController:tabController.selectedViewController];
177+
}
178+
if (viewController.presentedViewController) {
179+
return [self topViewControllerFromViewController:viewController.presentedViewController];
180+
}
181+
return viewController;
182+
}
168183
@end

packages/url_launcher/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for launching a URL on Android and iOS. Supports
33
web, phone, SMS, and email schemes.
44
author: Flutter Team <[email protected]>
55
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher
6-
version: 5.1.2
6+
version: 5.1.3
77

88
flutter:
99
plugin:

0 commit comments

Comments
 (0)