Skip to content
Home » Safari view in SwiftUI

Safari view in SwiftUI

[This article is not yet done]

You started playing around with SwiftUI, and you want to present a Safari(WebView), you search in the documentation, and…, SwiftUI has no native way to display a WebView!

To use Safari (SFSafari) you need to create a custom UIViewControllerRepresentable which is needed to use ViewControllers in SwiftUI.

This post contains, 3 sections,
1. The code in steps
2. The code (complete)
3. Example on how to use.

Full source code of our UIViewControllerRepresentable.


import SwiftUI
import SafariServices
import UIKit


/// Make a Safari View for SwiftUI
public struct SafariView: UIViewControllerRepresentable {
    typealias UIViewControllerType = SFSafariViewController

    /// Create a binding for our URL String
    @Binding var urlString: String

    /// Public initializer.
    public init(url: String) {
        _urlString = url
    }

    /// Make a UIViewController for SwiftUI.
    public func makeUIViewController(
        context: UIViewControllerRepresentableContext<SafariView>
    ) -> SFSafariViewController {
        // Check if the url is valid, otherwise fatalError.
        guard let url = URL(string: urlString) else {
            fatalError("Invalid urlString: \(urlString)")
        }

        // Generate the SFSafariViewController.
        let safariViewController = SFSafariViewController(url: url)

        // Optional, set int/accentcolor.
        safariViewController.preferredControlTintColor = UIColor(Color.accentColor)

        // We want our view to have a close button instead of 'done'
        safariViewController.dismissButtonStyle = .close

        // Return the view
        return safariViewController
    }

    public func updateUIViewController(
      _ safariViewController: SFSafariViewController, 
      context: UIViewControllerRepresentableContext<SafariView>) {
        return
    }
}

How to use:

struct CodeView: View {
    // whether or not to show the Safari ViewController
    @State var showSafari = false

    // initial URL string
    @State var urlString = "https://wdg.codes"

    var body: some View {
        VStack {
            Button("Open This article") {
                self.urlString = "https://wdg.codes/swiftui/safari-view-in-swiftui"

                showSafari = true
            }
        }
        .popover(isPresented: $showSafari, content: {
            SafariView(urlString: $urlString)
        })
    }
}

// MARK: Preview
struct CodeView_Previews: PreviewProvider {
    static var previews: some View {
        CodeView()
            .previewLayout(PreviewLayout.sizeThatFits)
            .padding()
            .previewDisplayName("Code Preview")
    }
}