Launch apps using URL schemes in iOS by calling UIApplication.shared.open(_:options:completionHandler:) with a properly formatted URL. iOS supports built-in schemes such as tel:// for Phone, mailto: for Mail, sms:// for Messages, https:// for Safari, and facetime:// for FaceTime. Third-party apps register custom schemes like fb:// for Facebook and whatsapp:// for WhatsApp. You can also register your own custom URL scheme so other apps can launch your application with specific data.
Launch System Apps with Built-In URL Schemes
Construct a URL with the appropriate scheme and pass it to UIApplication.shared.open.
if let url = URL(string: "tel://+1743234028") {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
if let url = URL(string: "mailto:[email protected]") {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
if let url = URL(string: "https://apple.com") {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
The tel:// scheme prompts the user to confirm before dialing. The mailto: scheme opens Mail with a pre-addressed email. The https:// scheme opens Safari.
Verify URL Availability with canOpenURL
Call UIApplication.shared.canOpenURL(_:) before open to confirm the system can handle the scheme.
func launchURL(_ urlString: String) {
guard let url = URL(string: urlString),
UIApplication.shared.canOpenURL(url) else {
// Show fallback UI
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
canOpenURL returns false for unrecognized schemes. iOS 9 and later require explicit whitelisting of custom schemes through Info.plist.
Whitelist Custom URL Schemes in Info.plist
Add the LSApplicationQueriesSchemes key to Info.plist as an array of strings. Each string is a scheme your app intends to query.
LSApplicationQueriesSchemes
Item 0: fb
Item 1: whatsapp
Item 2: twitter
Without this whitelist, canOpenURL returns false for fb://, whatsapp://, and similar schemes. The console logs "This app is not allowed to query for scheme" when a whitelisted scheme is missing.
Show a Confirmation Prompt Before Launching Apps
Present a UIAlertController with Confirm and Cancel buttons to give users control.
func promptAndOpen(_ urlString: String) {
guard presentedViewController == nil else { return }
let alert = UIAlertController(title: "Open App",
message: "This will open (urlString)",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Open", style: .default) { _ in
guard let url = URL(string: urlString),
UIApplication.shared.canOpenURL(url) else { return }
UIApplication.shared.open(url, options: [:])
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
present(alert, animated: true)
}
The presentedViewController check prevents multiple alerts from stacking when called rapidly, such as from a QR code scanning delegate that fires continuously.
Register a Custom URL Scheme for Your App
Open Info.plist and add a URL Types entry. Set the URL Identifier to your app's bundle identifier. Set the URL Schemes array with a single item such as myapp.
URL types
Item 0
URL Identifier: com.example.MyApp
URL Schemes
Item 0: myapp
Your app now responds to URLs like myapp://somepath.
Handle Incoming URLs in SceneDelegate
Implement scene(_:openURLContexts:) in SceneDelegate.swift for iOS 13 and later.
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let context = URLContexts.first else { return }
let message = context.url.host?.removingPercentEncoding ?? "No message"
let alert = UIAlertController(title: "Received",
message: message,
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
window?.rootViewController?.present(alert, animated: true)
}
The host property extracts the message from a URL like myapp://HelloWorld. Call removingPercentEncoding to decode percent-encoded characters. For iOS 12 and earlier, implement application(_:open:options:) in AppDelegate instead.
Parse Query Parameters from Incoming URLs
Use URLComponents to extract structured data from complex URLs.
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url,
let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return }
let action = components.host // e.g., "profile"
let userId = components.queryItems?.first(where: { $0.name == "id" })?.value
// Navigate to the appropriate screen
}
A URL like myapp://profile?id=42 sets action to "profile" and userId to "42". URLComponents handles percent-encoding automatically.
Test Custom URL Schemes from Safari
Open Mobile Safari and type myapp://HelloWorld in the address bar. iOS displays an alert asking to open your app. Tap Open to confirm the URL scheme works. This validates both your Info.plist configuration and your SceneDelegate handler.
Best Practices for URL Schemes
Always show a confirmation prompt before launching external apps. Users expect to approve app switches. Use canOpenURL as a gate check before open to prevent silent failures. Register every custom scheme in LSApplicationQueriesSchemes. URL-encode all parameters using addingPercentEncoding(withAllowedCharacters:) when constructing URLs and removingPercentEncoding when parsing them. Implement scene(_:openURLContexts:) for iOS 13 and later and application(_:open:options:) for backward compatibility. Consider Universal Links instead of custom URL schemes for production apps because Universal Links work without whitelisting, fall back to a website when the app is not installed, and cannot be hijacked by other apps. Validate all incoming URL data and never execute untrusted content without user confirmation.
Summary
This tutorial covered the complete implementation process from setup to working code. You now have a functional implementation that you can extend and customize for your own projects. The same patterns apply to related features in the iOS ecosystem.
Frequently Asked Questions
What iOS version is required? This tutorial targets iOS 9. Most of the APIs shown work on earlier versions as well, but some newer APIs may require the version specified in the article.
What are the prerequisites for this tutorial? You need Xcode installed on a Mac and basic familiarity with Swift programming. No prior experience with the specific framework is required.