So today I spent quite some time puzzling over why I was always getting nil
launchOptions
argument in func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
and then finally found a solution.
The reason
The culprit is the new project structure for iOS 13 and above. In the past we were used as AppDelegate
as the only class to handle app lifecycle events and responding to shortcuts, URL schemes and what not.
But with iOS 13 and more specifically iPadOS came the push to better support multiple screens for apps we got the SceneDelegate
where most of the events now moved.
So even though the didFinishLaunchingWithOptions
still looks the same:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
}
You don't get any launchOptions
here. It would be better if Apple simply changed the signature but for some reason (lets hope there at least is a reason) the argument is still present but always nil
.
The solution
The solution to correctly getting launchOptions
in iOS 13 and above is
to use SceneDelegate
and the willConnectTo session
which is automatically there with some basic code.
The full signature looks like this:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
And the connectionOptions
is new "reincarnation" of the trusty old launchOptions
. To be fair to apple, this is much better to work with.
Say you want to respond to launch from shortcut item (the quick action available with long press on app icon). Previously you would have to reach into the options dictionary and do a cast.
Now it looks like this:
if let shortcut = connectionOptions.shortcutItem {
// handle shortcut here
}
What about reacting to URL scheme? We have urlContexts
set available and can simply pull the first item for basic implementation:
if let firstUrlContext = connectionOptions.urlContexts.first {
// handle firstUrlContext.url
}
And that is it!
Hope this will save you some time when implementing this and you won't have to go full Sherlock 🕵 finding what is wrong...
One last thing
Since I have shown you how to react to shortcuts and URLs, let's see how to do these tasks when app is already running in the background.
We have this method to handle shortcuts:
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
}
And this one to handle URL launch:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
}
Once again, this is much better than prior to iOS 13 changes. 🙂
Thanks for reading!
Top comments (7)
@nemecek_f have you found an alternative for UIApplication.LaunchOptionsKey.location in the above case.
I'm monitoring significant location updates and the app is being launched but with nil launch options and in scendelegate ConnectionOptions doesnt have a proper alternative.
Hi! Maybe it is hidden in
connectionOptions.userActivities
? But I havent used this personally. Kind of frustrating that Apple does not document this better.. I would expect some info in the docs but no - developer.apple.com/documentation/...I'm coding right now as we chat here! I'm going with a workaround: I don't care the location key is nil or not every time the app is launched I do operations that I need. And I control it with an if-case and decide whether to actually do it nor not!
Very frustrating. I'm sure many apps are relying on the launch options!!
I will update here by the end of the day, what I end up doing.
@dksmarttech Hi, I am having the same issue. iOS 14.4.2.
Did you find a proper solution for this?
I've found one particular case when it doesn't equal nil. It happens when the app is not launched and you do it by deeplinking. In that case, it contains a URL.
Interesting! Thanks for the info but it is kind of strage, that this (possibly) one case is still in the
AppDelegate
Some comments may only be visible to logged-in visitors. Sign in to view all comments.