Wesley de Groot's Blog
Safari in SwiftUI

Safari in SwiftUI

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>) {

How to use:

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

    // initial URL string
    @State var urlString = ""

    var body: some View {
        VStack {
            Button("Open This article") {
                self.urlString = ""

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

// MARK: Preview
struct CodeView_Previews: PreviewProvider {
    static var previews: some View {
            .previewDisplayName("Code Preview")
x-twitter mastodon github linkedin discord threads instagram whatsapp bluesky square-rss sitemap