Embed a Webpage in SwiftUI

Embed a Webpage in SwiftUI

·

3 min read

In an iOS app, it might be useful to provide some information already available on a website without a Link. In today’s post, we’re going to look at how we can add a webpage to a SwiftUI view.

The source code of the post is available here.

Overview

Target: Create a SwiftUI view that displays a website (I’ll use Apple’s home page https://www.apple.com/ in the demo project).

Unfortunately, there still isn’t a native SwiftUI webview, however, we can create a UIView representable struct to have a UIView version embedded in a SwiftUI view. Continue reading to learn how.

Create a WebView struct

Create a SwiftUI project and add a new file called WebView. The file type should be Swift source instead of SwiftUI View which might be selected by default.

In this new file, declare a struct WebView and make it conform to UIViewRepresentable. This is a protocol in SwiftUI (so you need to import SwiftUI first if you haven't done so), with which we can define a UIView as in UIKit and use its instances as SwiftUI views. Later we’ll need WKWebView and related configurations from WebKit to populate a UIView, so we need to import WebKit as well.

import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {}

Conformance

After declaring the struct you might get an error, reminding you the type WebView does not conform to the protocol UIViewRepresentable. This is because the protocol defined two functions that needs to be implemented:

  • makeUIView(context) -> UIViewType As the name suggests, it’s used to make, or define a UIView that would be used as a SwiftUI View. In this case, we can add some configurations to the WKWebView in UIKit and return it together with the configurations.

  • updateUIView(UIViewType, context) This function will be used to modify the view further. For instance, after we defined the WKWebView, we can use it to actually send a URL request to load the view with the webpage presented.

Let’s implement the WebView as shown below.

  1. Declare an optional URL, so that we can pass in a URL of a website for the URL call.

  2. Implement the makeUIView function that returns a WKWebView. Inside the function, we need to initialize a WKWebView with a configuration of JavaScript content policy. (Set it to true to avoid webpage presentation issues.)

  3. Implement the updateView function, in which the WKWebView will be loaded with the URL request call.

import Foundation
import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    let url: URL?

    func makeUIView(context: Context) -> WKWebView {
        let prefs = WKWebpagePreferences()
        prefs.allowsContentJavaScript = true

        let config = WKWebViewConfiguration()
        config.defaultWebpagePreferences = prefs

        return WKWebView(
            frame: .zero,
            configuration: config)
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        guard let myURL = url else {
            return
        }
        let request = URLRequest(url: myURL)
        uiView.load(request)
    }
}

Back to SwiftUI

Now let’s open the ContentView file. Declare a URL property for the website. You can initiate a URL instance with the parameter of String.

private let url = URL(string: "https://www.apple.com/")

Then within the body property, simply add a WebView and pass the URL from above.

WebView(url: url)

Now you should be able to see the website in the preview. If you’d like to have the website shown in the safe area (such as the dynamic island or top-notch area), you can add a modifier .ignoresSafeArea()

struct ContentView: View {
    private let url = URL(string: "https://www.apple.com/")
    var body: some View {
        ZStack {
            WebView(url: url)
                //.ignoresSafeArea()
        }
    }
}