I have a deep linking feature in my app that works fine beside one case. I have a 3 different onboarding pages according to the url that opened the app. So when the app is launched i need to know what link(if any) opened the app and then present the right onboarding page. The problem is that i need to know what screen to present in the method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
but i can only know if a deep link opened the app in
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
which gets called 5 seconds after did didFinishLaunchingWithOptions
is called(i counted the seconds). So i have 5 seconds that i see a wrong onboarding page untill openURL
is called(if it will be called) .
So my question is: is there any way to know if the app was launched from a url before or during didFinishLaunchingWithOptions
?
By the way launchOptions
in didFinishLaunchingWithOptions
is nil when the app opens from a deep link
The launch option key your are looking for is UIApplicationLaunchOptionsURLKey
(Objective-C) / UIApplicationLaunchOptionsKey.url
(Swift).
If you're targeting iOS 9 and upwards you only have to intercept a launch URL from
application:didFinishLaunchingWithOptions:
(in case the app is not in memory yet) application:openURL:options:
(in case the app is already in the background). Here's a minimalistic implementation of UIApplicationDelegate
that should cover both cases - please note that a lot unrelated logic has been omitted for clarity:
Objective-C:
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *url = launchOptions[UIApplicationLaunchOptionsURLKey];
if (url) {
// TODO: handle URL from here
}
return YES;
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
// TODO: handle URL from here
return YES;
}
@end
Swift 5:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let url = launchOptions?[.url] as? URL {
// TODO: handle URL from here
}
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// TODO: handle URL from here
return true
}
}
I just had a similar problem in iOS 13, but things have changed in iOS 13 because the UIWindowSceneDelegate has been introduced and may now do some of the work previously done by UIApplicationDelegate
(depending on your app settings).
The answer by @Olivier in this thread was still very useful to me because it points out the two scenarios in which the URL scheme gets handled; namely when the app is not in memory yet, which calls for application:didFinishLaunchingWithOptions:
, and when the app has already been loaded and is in the background, which second case calls for application:openURL:options:
.
So, as I'm mentioning above, things are a little different since iOS 13 if you are using the default application template generated by XCode 11. I won't get into the details here, so here's an informative tutorial on the topic: Understanding the iOS 13 Scene Delegate.
But the key methods to modify if you are using the new approach with scenes are scene(_:willConnectTo:options:)
(docs here) and scene(_:openURLContexts:)
(docs here). The former is where to act upon the URL scheme when the app was not already loaded (so it kind of replaces application:didFinishLaunchingWithOptions:
), and the latter is where to get the URL when the app was already in the background when the URL scheme was called (so this one replaces application:openURL:options:
).
With scene(_:willConnectTo:options:)
, you can look for the URL of the URL scheme (if any) doing something like this:
if let url = connectionOptions.urlContexts.first?.url {
// handle
}
For scene(_:openURLContexts:)
, you can look inside the URLContexts
set.
I hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With