7 #import "flutter/shell/platform/darwin/common/InternalFlutterSwiftCommon/InternalFlutterSwiftCommon.h"
35 - (instancetype)init {
36 if (
self = [super init]) {
44 return [
self.launchEngine takeEngine];
47 - (BOOL)application:(UIApplication*)application
48 willFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
49 return [
self.lifeCycleDelegate application:application
50 willFinishLaunchingWithOptions:launchOptions];
53 - (BOOL)application:(UIApplication*)application
54 didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
55 return [
self.lifeCycleDelegate application:application
56 didFinishLaunchingWithOptions:launchOptions];
62 if (_rootFlutterViewControllerGetter != nil) {
63 return _rootFlutterViewControllerGetter();
65 UIViewController* rootViewController = _window.rootViewController;
73 - (void)applicationDidEnterBackground:(UIApplication*)application {
77 - (void)applicationWillEnterForeground:(UIApplication*)application {
81 - (void)applicationWillResignActive:(UIApplication*)application {
85 - (void)applicationDidBecomeActive:(UIApplication*)application {
89 - (void)applicationWillTerminate:(UIApplication*)application {
92 #pragma GCC diagnostic push
93 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
94 - (void)application:(UIApplication*)application
95 didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings {
96 [
self.lifeCycleDelegate application:application
97 didRegisterUserNotificationSettings:notificationSettings];
99 #pragma GCC diagnostic pop
101 - (void)application:(UIApplication*)application
102 didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
103 [
self.lifeCycleDelegate application:application
104 didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
107 - (void)application:(UIApplication*)application
108 didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
109 [
self.lifeCycleDelegate application:application
110 didFailToRegisterForRemoteNotificationsWithError:error];
113 #pragma GCC diagnostic push
114 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
115 - (void)application:(UIApplication*)application
116 didReceiveLocalNotification:(UILocalNotification*)notification {
117 [
self.lifeCycleDelegate application:application didReceiveLocalNotification:notification];
119 #pragma GCC diagnostic pop
121 - (void)userNotificationCenter:(UNUserNotificationCenter*)center
122 willPresentNotification:(UNNotification*)notification
123 withCompletionHandler:
124 (
void (^)(UNNotificationPresentationOptions options))completionHandler {
125 if ([
self.lifeCycleDelegate respondsToSelector:_cmd]) {
126 [
self.lifeCycleDelegate userNotificationCenter:center
127 willPresentNotification:notification
128 withCompletionHandler:completionHandler];
135 - (void)userNotificationCenter:(UNUserNotificationCenter*)center
136 didReceiveNotificationResponse:(UNNotificationResponse*)response
137 withCompletionHandler:(
void (^)(
void))completionHandler {
138 if ([
self.lifeCycleDelegate respondsToSelector:_cmd]) {
139 [
self.lifeCycleDelegate userNotificationCenter:center
140 didReceiveNotificationResponse:response
141 withCompletionHandler:completionHandler];
145 - (BOOL)isFlutterDeepLinkingEnabled {
146 NSNumber* isDeepLinkingEnabled =
147 [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"];
149 return isDeepLinkingEnabled ? [isDeepLinkingEnabled boolValue] : YES;
153 - (BOOL)application:(UIApplication*)application
155 options:(NSDictionary<UIApplicationOpenURLOptionsKey,
id>*)options {
156 if ([
self.lifeCycleDelegate application:application openURL:url options:options]) {
161 return [
self handleOpenURL:url options:options relayToSystemIfUnhandled:NO];
165 - (BOOL)handleOpenURL:(NSURL*)url
166 options:(NSDictionary<UIApplicationOpenURLOptionsKey,
id>*)options
167 relayToSystemIfUnhandled:(BOOL)throwBack {
169 if (flutterApplication == nil) {
172 if (![
self isFlutterDeepLinkingEnabled]) {
177 if (flutterViewController) {
178 [flutterViewController sendDeepLinkToFramework:url
179 completionHandler:^(BOOL success) {
180 if (!success && throwBack) {
182 [flutterApplication openURL:url
184 completionHandler:nil];
188 [FlutterLogger logError:@"Attempting to open an URL without a Flutter RootViewController."];
194 - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
195 return [
self.lifeCycleDelegate application:application handleOpenURL:url];
198 - (BOOL)application:(UIApplication*)application
200 sourceApplication:(NSString*)sourceApplication
201 annotation:(
id)annotation {
202 return [
self.lifeCycleDelegate application:application
204 sourceApplication:sourceApplication
205 annotation:annotation];
208 - (void)application:(UIApplication*)application
209 performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
210 completionHandler:(
void (^)(BOOL succeeded))completionHandler {
211 [
self.lifeCycleDelegate application:application
212 performActionForShortcutItem:shortcutItem
213 completionHandler:completionHandler];
216 - (void)application:(UIApplication*)application
217 handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
218 completionHandler:(nonnull
void (^)())completionHandler {
219 [
self.lifeCycleDelegate application:application
220 handleEventsForBackgroundURLSession:identifier
221 completionHandler:completionHandler];
225 - (BOOL)application:(UIApplication*)application
226 continueUserActivity:(NSUserActivity*)userActivity
227 restorationHandler:(
void (^)(NSArray<
id<UIUserActivityRestoring>>* __nullable
228 restorableObjects))restorationHandler {
229 if ([
self.lifeCycleDelegate application:application
230 continueUserActivity:userActivity
231 restorationHandler:restorationHandler]) {
235 return [
self handleOpenURL:userActivity.webpageURL options:@{} relayToSystemIfUnhandled:YES];
238 #pragma mark - FlutterPluginRegistry methods. All delegating to the rootViewController
241 if (_weakRegistrant) {
242 return _weakRegistrant;
244 if (_strongRegistrant) {
245 return _strongRegistrant;
253 _strongRegistrant = nil;
255 _weakRegistrant = nil;
262 if (flutterRootViewController) {
263 return [[flutterRootViewController
pluginRegistry] registrarForPlugin:pluginKey];
265 return [
self.launchEngine.engine registrarForPlugin:pluginKey];
268 - (BOOL)hasPlugin:(NSString*)pluginKey {
270 if (flutterRootViewController) {
271 return [[flutterRootViewController
pluginRegistry] hasPlugin:pluginKey];
273 return [
self.launchEngine.engine hasPlugin:pluginKey];
276 - (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
278 if (flutterRootViewController) {
279 return [[flutterRootViewController
pluginRegistry] valuePublishedByPlugin:pluginKey];
281 return [
self.launchEngine.engine valuePublishedByPlugin:pluginKey];
284 #pragma mark - Selectors handling
287 [
self.lifeCycleDelegate addDelegate:delegate];
290 #pragma mark - UIApplicationDelegate method dynamic implementation
292 - (BOOL)respondsToSelector:(
SEL)selector {
293 if ([
self.lifeCycleDelegate isSelectorAddedDynamically:selector]) {
294 return [
self delegateRespondsSelectorToPlugins:selector];
296 return [
super respondsToSelector:selector];
299 - (BOOL)delegateRespondsSelectorToPlugins:(
SEL)selector {
300 if ([
self.lifeCycleDelegate hasPluginThatRespondsToSelector:selector]) {
301 return [
self.lifeCycleDelegate respondsToSelector:selector];
307 - (id)forwardingTargetForSelector:(
SEL)aSelector {
308 if ([
self.lifeCycleDelegate isSelectorAddedDynamically:aSelector]) {
309 [
self logCapabilityConfigurationWarningIfNeeded:aSelector];
310 return self.lifeCycleDelegate;
312 return [
super forwardingTargetForSelector:aSelector];
319 - (void)logCapabilityConfigurationWarningIfNeeded:(
SEL)selector {
320 NSArray* backgroundModesArray =
321 [[NSBundle mainBundle] objectForInfoDictionaryKey:kUIBackgroundMode];
322 NSSet* backgroundModesSet = [[NSSet alloc] initWithArray:backgroundModesArray];
323 if (selector ==
@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)) {
326 @"You've implemented -[<UIApplicationDelegate> "
327 @"application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need "
328 @"to add \"remote-notification\
" to the list of your supported UIBackgroundModes in your "
331 }
else if (selector ==
@selector(application:performFetchWithCompletionHandler:)) {
333 NSLog(
@"You've implemented -[<UIApplicationDelegate> "
334 @"application:performFetchWithCompletionHandler:], but you still need to add \"fetch\
" "
335 @"to the list of your supported UIBackgroundModes in your Info.plist.");
340 #pragma mark - State Restoration
342 - (BOOL)application:(UIApplication*)application shouldSaveApplicationState:(NSCoder*)coder {
343 [coder encodeInt64:self.lastAppModificationTime forKey:kRestorationStateAppModificationKey];
347 - (BOOL)application:(UIApplication*)application shouldRestoreApplicationState:(NSCoder*)coder {
348 int64_t stateDate = [coder decodeInt64ForKey:kRestorationStateAppModificationKey];
349 return self.lastAppModificationTime == stateDate;
352 - (BOOL)application:(UIApplication*)application shouldSaveSecureApplicationState:(NSCoder*)coder {
353 [coder encodeInt64:self.lastAppModificationTime forKey:kRestorationStateAppModificationKey];
357 - (BOOL)application:(UIApplication*)application
358 shouldRestoreSecureApplicationState:(NSCoder*)coder {
359 int64_t stateDate = [coder decodeInt64ForKey:kRestorationStateAppModificationKey];
360 return self.lastAppModificationTime == stateDate;
363 - (int64_t)lastAppModificationTime {
365 NSError* error = nil;
366 [[[NSBundle mainBundle] executableURL] getResourceValue:&fileDate
367 forKey:NSURLContentModificationDateKey
369 NSAssert(error == nil,
@"Cannot obtain modification date of main bundle: %@", error);
370 return [fileDate timeIntervalSince1970];
static NSString *const kRemoteNotificationCapabitiliy
static FLUTTER_ASSERT_ARC NSString *const kUIBackgroundMode
static NSString *const kBackgroundFetchCapatibility
static NSString *const kRestorationStateAppModificationKey
__weak NSObject< FlutterPluginRegistrant > * _weakRegistrant
NSObject< FlutterPluginRegistrant > * _strongRegistrant
NSObject< FlutterPluginRegistrant > * pluginRegistrant
UIApplication * application
id< FlutterPluginRegistry > pluginRegistry()