OpenURLAction in SwiftUI
OpenURL environment variable provides ability to open URLs from SwiftUI views. We can use it to open website, email form, deep-link embedded in the app or settings app on the device.
The OpenURL structure is defined in app’s Environment and it gives us access to its instance for app’s current Environment via environment variable. We use it to open a URL in response to some action performed by the user or the app.
Let’s look at an example by opening DevTechie.com via openURL
import SwiftUI
struct OpenURLExample: View {
@Environment(\.openURL) var openURL
var body: some View {
Button(action: openDevTechie) {
Text("Checkout DevTechie.com")
Image(systemName: "globe.americas.fill")
}
}
func openDevTechie() {
guard let url = URL(string: "https://www.devtechie.com") else {
return
}
openURL(url)
}
}
We can open settings app using openURL
import SwiftUI
struct OpenURLExample: View {
@Environment(\.openURL) var openURL
var body: some View {
Button(action: openDevTechie) {
Text("Checkout DevTechie.com")
Image(systemName: "globe.americas.fill")
}
Button(action: openSettingsApp) {
Text("Open Settings App")
Image(systemName: "gear.circle.fill")
}
}
func openDevTechie() {
guard let url = URL(string: "https://www.devtechie.com") else {
return
}
openURL(url)
}
func openSettingsApp() {
guard let url = URL(string: UIApplication.openSettingsURLString) else {
return
}
openURL(url)
}
}
OpenURL also supports trailing completion closure giving us access to a Boolean variable which indicates whether the URL can be opened. We can use this method when attempting to asynchronously open a URL. The result indicates whether the system was able open the URL. The completion runs after the system decides that it can open the URL.
Let’s add a function in our example. In this case, we will try to open mail url on simulator, since simulator doesn’t have mail app installed the opening of URL will fail and we will get message in console.
func openMailApp() {
guard let url = URL(string: "devtechieInc@gmail.com") else {
return
}
openURL(url) { result in
print("Opening mail app success: \(result)")
}
}
Complete code:
import SwiftUI
struct OpenURLExample: View {
@Environment(\.openURL) var openURL
var body: some View {
Button(action: openDevTechie) {
Text("Checkout DevTechie.com")
Image(systemName: "globe.americas.fill")
}
Button(action: openSettingsApp) {
Text("Open Settings App")
Image(systemName: "gear.circle.fill")
}
Button(action: openMailApp) {
Text("Send email to DevTechie")
Image(systemName: "envelope.open")
}
}
func openDevTechie() {
guard let url = URL(string: "https://www.devtechie.com") else {
return
}
openURL(url)
}
func openSettingsApp() {
guard let url = URL(string: UIApplication.openSettingsURLString) else {
return
}
openURL(url)
}
func openMailApp() {
guard let url = URL(string: "devtechieInc@gmail.com") else {
return
}
openURL(url) { result in
print("Opening mail app success: \(result)")
}
}
}
Console output:
Let’s update our code to include a failure message on screen.
import SwiftUI
struct OpenURLExample: View {
@Environment(\.openURL) var openURL
@State private var message = ""
var body: some View {
Button(action: openDevTechie) {
Text("Checkout DevTechie.com")
Image(systemName: "globe.americas.fill")
}
Button(action: openSettingsApp) {
Text("Open Settings App")
Image(systemName: "gear.circle.fill")
}
Button(action: openMailApp) {
Text("Send email to DevTechie")
Image(systemName: "envelope.open")
}
if !message.isEmpty {
Text(message)
.font(.body)
.foregroundStyle(Color.pink.gradient)
}
}
func openDevTechie() {
guard let url = URL(string: "https://www.devtechie.com") else {
return
}
openURL(url)
}
func openSettingsApp() {
guard let url = URL(string: UIApplication.openSettingsURLString) else {
return
}
openURL(url)
}
func openMailApp() {
guard let url = URL(string: "devtechieInc@gmail.com") else {
return
}
openURL(url) { result in
if !result {
message = "Failed to open the URL."
}
}
}
}