How to add UIKit component on your SwiftUI project
Tags: swift, ios, Xcode, uikit
Published: 2020-05-06 19:32:30

A brief to how to add WKWebView on your SwiftUI view
First of all, there is no WebView component write in SwiftUI, so, how I add this component?

Yes, we need to add an UIKit component to a SwiftUI view 🤔
Ok, let's build a simple app in SwiftUI.

![Creating Project on Xcode](https://dev-to-uploads.s3.amazonaws.com/i/6ajcdpys2aajfpnn894h.png)

Xcode auto-generate a Hello World project, it's awesome, because it pretty easy to add WebView now!

![Initial State](https://dev-to-uploads.s3.amazonaws.com/i/60uojemd0wmvhxwkvy1m.png)
Ok, finally lets work on some code

We need to create a ViewModel to treat the webview statement.

```
import Foundation
import WebKit

public class WebViewViewModel: NSObject {
    
    private let stringUrl: String
    public let webView: WKWebView
    
    init(stringUrl: String) {
        self.stringUrl = stringUrl
        self.webView = WKWebView()
    }
}
```

We create a ViewModel called *WebViewViewModel* with **url** and **webview** initializers. But, why?

**url** — is a string URL to you web site e.g google.com

**webview** — is a WKWebView object to store and control your component

and after this we need to perform a webview request to load the website, so add this on your ViewModel

```
public func request() {
    guard let url = URL(string: stringUrl) else {
        return
    }
    let urlRequest = URLRequest(url: url)
    webView.load(urlRequest)
    if webView.navigationDelegate == nil {
        webView.navigationDelegate = self
    }
}
```

And last but not least add WKNavigationDelegate to your ViewModel

```
extension WebViewViewModel: WKNavigationDelegate {
    public func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        
    }
    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        
    }
}
```
Our ViewModel is completed! Now we need to add this webview on our SwiftUI view, back to ContentView class and add this **UIViewRepresentable**

```
struct WebView: UIViewRepresentable {
    
    let viewModel: WebViewViewModel
    
    func makeUIView(context: Context) -> WKWebView {
        return viewModel.webView
    }
    func updateUIView(_ uiView: WKWebView, context: Context) {
        viewModel.request()
    }
}
```
But… Whats is **UIViewRepresentable?** Basically is a instance to create and menage UIKit components, you can read more [here](https://developer.apple.com/documentation/swiftui/uiviewrepresentable) and [here](https://developer.apple.com/documentation/swiftui/uiviewrepresentable/3278050-updateuiview).

Let's understand what that code does. 

The function **makeUIView** is responsable to return your component.

The function **updateUIView** is responsable to tells your app state change.

Finally, the last thing we need to do is add our webview to our main view, like this:

```
struct ContentView: View {
    var body: some View {
        WebView(viewModel: WebViewViewModel(stringUrl: "https://tinyurl.com/w498z2l"))
    }
}
```
Yes, is simple like that!

[You can download the source code here](https://github.com/fabriciomasiero/WebViewSwiftUI/tree/master)

I hope you enjoyed.
Bye bye =D