OpenURL Action in SwiftUI

DevTechie Inc
Jul 18, 2023

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."
            }
        }
    }
}