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

Commit c762720

Browse files
committed
Update FlutterAppDelegate.mm
1 parent 842cf25 commit c762720

File tree

2 files changed

+107
-50
lines changed

2 files changed

+107
-50
lines changed

shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,14 @@ - (void)userNotificationCenter:(UNUserNotificationCenter*)center
134134
}
135135
}
136136

137-
- (BOOL)openURL:(NSURL*)url {
137+
- (void)openURL:(NSURL*)url
138+
options:(NSDictionary<UIApplicationOpenExternalURLOptionsKey, id>*)options
139+
completionHandler:(void (^)(BOOL success))completion {
138140
NSNumber* isDeepLinkingEnabled =
139141
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"];
140142
if (!isDeepLinkingEnabled.boolValue) {
141143
// Not set or NO.
142-
return NO;
144+
completion(NO);
143145
} else {
144146
FlutterViewController* flutterViewController = [self rootFlutterViewController];
145147
if (flutterViewController) {
@@ -149,29 +151,46 @@ - (BOOL)openURL:(NSURL*)url {
149151
if (didTimeout) {
150152
FML_LOG(ERROR)
151153
<< "Timeout waiting for the first frame when launching an URL.";
154+
completion(NO);
152155
} else {
156+
// invove the method and get the result
153157
[flutterViewController.engine.navigationChannel
154158
invokeMethod:@"pushRouteInformation"
155159
arguments:@{
156160
@"location" : url.absoluteString ?: [NSNull null],
157-
}];
161+
}
162+
result:^(id _Nullable result) {
163+
BOOL success = [result isKindOfClass:[NSNumber class]] &&
164+
[result boolValue];
165+
if (!success) {
166+
// Logging the error if the result is not successful
167+
FML_LOG(ERROR)
168+
<< "Failed to handle route information in Flutter.";
169+
}
170+
completion(success);
171+
}];
158172
}
159173
}];
160-
return YES;
161174
} else {
162175
FML_LOG(ERROR) << "Attempting to open an URL without a Flutter RootViewController.";
163-
return NO;
176+
completion(NO);
164177
}
165178
}
166179
}
167180

168181
- (BOOL)application:(UIApplication*)application
169-
openURL:(NSURL*)url
170-
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options {
182+
openURL:(NSURL*)url
183+
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options
184+
completionHandler:(void (^)(BOOL success))completion {
171185
if ([_lifeCycleDelegate application:application openURL:url options:options]) {
172-
return YES;
186+
completion(YES);
187+
} else {
188+
[self openURL:url
189+
options:options
190+
completionHandler:^(BOOL success) {
191+
completion(success);
192+
}];
173193
}
174-
return [self openURL:url];
175194
}
176195

177196
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
@@ -208,13 +227,19 @@ - (BOOL)application:(UIApplication*)application
208227
continueUserActivity:(NSUserActivity*)userActivity
209228
restorationHandler:
210229
(void (^)(NSArray<id<UIUserActivityRestoring>>* __nullable restorableObjects))
211-
restorationHandler {
230+
restorationHandler
231+
completionHandler:(void (^)(BOOL success))completion {
212232
if ([_lifeCycleDelegate application:application
213233
continueUserActivity:userActivity
214234
restorationHandler:restorationHandler]) {
215-
return YES;
235+
completion(YES);
216236
}
217-
return [self openURL:userActivity.webpageURL];
237+
238+
[self openURL:userActivity.webpageURL
239+
options:@{}
240+
completionHandler:^(BOOL success) {
241+
completion(success);
242+
}];
218243
}
219244

220245
#pragma mark - FlutterPluginRegistry methods. All delegating to the rootViewController

shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,48 @@ - (void)testLaunchUrl {
6262
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
6363
.andReturn(@YES);
6464

65-
BOOL result =
66-
[self.appDelegate application:[UIApplication sharedApplication]
67-
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
68-
options:@{}];
69-
XCTAssertTrue(result);
70-
OCMVerify([self.mockNavigationChannel
71-
invokeMethod:@"pushRouteInformation"
72-
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}]);
65+
OCMStub([self.mockNavigationChannel
66+
invokeMethod:@"pushRouteInformation"
67+
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
68+
.andReturn(@YES);
69+
70+
[self.appDelegate application:[UIApplication sharedApplication]
71+
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
72+
options:@{}
73+
completionHandler:^(BOOL success) {
74+
XCTAssertTrue(success);
75+
}];
76+
77+
OCMVerifyAll(self.mockNavigationChannel);
78+
}
79+
80+
- (void)testLaunchUrlWithNavigationChannelReturningFalse {
81+
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
82+
.andReturn(@YES);
83+
84+
OCMStub([self.mockNavigationChannel
85+
invokeMethod:@"pushRouteInformation"
86+
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
87+
.andReturn(@NO);
88+
89+
[self.appDelegate application:[UIApplication sharedApplication]
90+
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
91+
options:@{}
92+
completionHandler:^(BOOL success) {
93+
XCTAssertFalse(success);
94+
}];
7395
}
7496

7597
- (void)testLaunchUrlWithDeepLinkingNotSet {
7698
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
7799
.andReturn(nil);
78100

79-
BOOL result =
80-
[self.appDelegate application:[UIApplication sharedApplication]
81-
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
82-
options:@{}];
101+
[self.appDelegate application:[UIApplication sharedApplication]
102+
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
103+
options:@{}
104+
completionHandler:^(BOOL success) {
105+
XCTAssertFalse(success);
106+
}];
83107
XCTAssertFalse(result);
84108
OCMReject([self.mockNavigationChannel invokeMethod:OCMOCK_ANY arguments:OCMOCK_ANY]);
85109
}
@@ -88,40 +112,47 @@ - (void)testLaunchUrlWithDeepLinkingDisabled {
88112
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
89113
.andReturn(@NO);
90114

91-
BOOL result =
92-
[self.appDelegate application:[UIApplication sharedApplication]
93-
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
94-
options:@{}];
115+
[self.appDelegate application:[UIApplication sharedApplication]
116+
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
117+
options:@{}
118+
completionHandler:^(BOOL success) {
119+
XCTAssertFalse(success);
120+
}];
95121
XCTAssertFalse(result);
96122
OCMReject([self.mockNavigationChannel invokeMethod:OCMOCK_ANY arguments:OCMOCK_ANY]);
97123
}
98124

99125
- (void)testLaunchUrlWithQueryParameterAndFragment {
100126
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
101127
.andReturn(@YES);
102-
103-
BOOL result = [self.appDelegate
104-
application:[UIApplication sharedApplication]
105-
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test#fragment"]
106-
options:@{}];
107-
XCTAssertTrue(result);
108-
OCMVerify([self.mockNavigationChannel
109-
invokeMethod:@"pushRouteInformation"
110-
arguments:@{@"location" : @"http://myApp/custom/route?query=test#fragment"}]);
128+
OCMStub([self.mockNavigationChannel
129+
invokeMethod:@"pushRouteInformation"
130+
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
131+
.andReturn(@YES);
132+
[self.appDelegate
133+
application:[UIApplication sharedApplication]
134+
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test#fragment"]
135+
options:@{}
136+
completionHandler:^(BOOL success) {
137+
XCTAssertTrue(success);
138+
}];
139+
OCMVerifyAll(self.mockNavigationChannel);
111140
}
112141

113142
- (void)testLaunchUrlWithFragmentNoQueryParameter {
114143
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
115144
.andReturn(@YES);
116-
117-
BOOL result =
118-
[self.appDelegate application:[UIApplication sharedApplication]
119-
openURL:[NSURL URLWithString:@"http://myApp/custom/route#fragment"]
120-
options:@{}];
121-
XCTAssertTrue(result);
122-
OCMVerify([self.mockNavigationChannel
123-
invokeMethod:@"pushRouteInformation"
124-
arguments:@{@"location" : @"http://myApp/custom/route#fragment"}]);
145+
OCMStub([self.mockNavigationChannel
146+
invokeMethod:@"pushRouteInformation"
147+
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
148+
.andReturn(@YES);
149+
[self.appDelegate application:[UIApplication sharedApplication]
150+
openURL:[NSURL URLWithString:@"http://myApp/custom/route#fragment"]
151+
options:@{}
152+
completionHandler:^(BOOL success) {
153+
XCTAssertTrue(success);
154+
}];
155+
OCMVerifyAll(self.mockNavigationChannel);
125156
}
126157

127158
- (void)testReleasesWindowOnDealloc {
@@ -145,7 +176,10 @@ - (void)testReleasesWindowOnDealloc {
145176
- (void)testUniversalLinkPushRouteInformation {
146177
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
147178
.andReturn(@YES);
148-
179+
OCMStub([self.mockNavigationChannel
180+
invokeMethod:@"pushRouteInformation"
181+
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
182+
.andReturn(@YES);
149183
NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:@"com.example.test"];
150184
userActivity.webpageURL = [NSURL URLWithString:@"http://myApp/custom/route?query=test"];
151185
BOOL result = [self.appDelegate
@@ -154,9 +188,7 @@ - (void)testUniversalLinkPushRouteInformation {
154188
restorationHandler:^(NSArray<id<UIUserActivityRestoring>>* __nullable restorableObjects){
155189
}];
156190
XCTAssertTrue(result);
157-
OCMVerify([self.mockNavigationChannel
158-
invokeMethod:@"pushRouteInformation"
159-
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}]);
191+
OCMVerifyAll(self.mockNavigationChannel);
160192
}
161193

162194
@end

0 commit comments

Comments
 (0)