Build a SwiftUI PreviewProvider for UIKit Views
Tags: ios, swift, swiftui, uikit
Published: 2022-08-02 10:32:00

## Build a SwiftUI PreviewProvider for UIKit Views
**A simple way to see your UIKit ViewController changes instantly — live and on-demand**

Have you ever tried the SwiftUI? Haven’t you found it so delightful and easy to work with?

However, in UIKit views, if you are prototyping a design in your codebase, you have to recompile and build your project every time to see the results in the simulator. But in SwiftUI it’s so pleasant to view changes on-demand without rebuilding.

What if we can do that something similar to it for our UIKit Components? Like previewing or hot reloading the UIKit changes immediately without the time-consuming build and compile process.

Essentially, we’re looking to create a live preview system for our UIKit views using SwiftUI.

---------

There are many ways to make this process easier such as simple annotations like `@IBDesignable`, `@IBInspectable` and etc.

But if you have experience using these sometimes it gets buggy and causes some compile errors for rational reasons and sometimes it’s not the best approach.

So in this article, you will learn a new and way simpler way to see your changes instantly. if you used SwiftUI you already know it but we add a little trick to it so it will work with UIKit.

## SwiftUI: PreviewProvider
[`PreviewProvider`](https://developer.apple.com/documentation/swiftui/previewprovider) is a protocol type that produces view previews in Xcode. It contains an associated type called `Previews` which is of type `View`. `View` is a SwiftUI view that we’ll return for the `PreviewProvider` to display — we’ll see this later.

After creating an object which is conforming to this protocol, we’ll pass the view we want to see in our preview. It’ll automatically pop up a split view like the picture below.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ye4g40i2xm9vwd92akvm.png)

If the preview doesn’t load, worry not: simply use the below keyboard shortcut to see the reset the live preview:

> **⌘ + ⌥ + Return (Command + option + Return)**

Note: Make sure to click on the resume button that appears in the upright corner of the preview content if you won’t see that it means it is working and showing you the live content.

## UIKit: PreviewProvider
So now that we know about the `PreviewProvider` and how it works in SwiftUI, how can we achieve this in UIKit?

The answer is simple: We have to convert our UIKit codebase into something that SwiftUI understands and use the SwiftUI PreviewProvider to see the live simulation of the content. Any guesses how?

## How to convert UIKit content to SwiftUI Content?
It is way easier than you think. Don’t make it complicated. All we need is the popular `UIViewControllerRepresentable` protocol.

`UIViewControllerRepresentable` acts as a bridge to help convert the UIViewController to SwiftUI view. Have you guessed what are we planning to do yet?

## Implementation
Now that we know about `UIViewControllerRepresentable` and `PreviewProvider` in SwiftUI, Let’s get our hands dirty and use them in a practical way.

## UIKit Controller
Let’s create a simple UIKit controller (`UIViewController`) which contains some UI modifications:

``` 
class ViewController: UIViewController {
    
    @IBOutlet var imageView: UIImageView!
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var confirmBtn: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        setupView()
    }
    
    private func setupView() {
        imageView.layer.cornerRadius = imageView.frame.height / 2
        imageView.clipsToBounds = true
        imageView.layer.borderWidth = 1
        imageView.layer.borderColor = UIColor.red.cgColor
        
        titleLabel.text = "This is a test ViewController to see if we can use swiftUI previews for UIKit Controllers"
        
        confirmBtn.setTitle("Confirm", for: .normal)
        confirmBtn.backgroundColor = .cyan
        confirmBtn.clipsToBounds = true
        confirmBtn.layer.borderWidth = 1
        confirmBtn.layer.borderColor = UIColor.blue.cgColor
        confirmBtn.layer.cornerRadius =  20
    }
 }
```

If we run this `ViewController` you will see something like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2bh620luabfxhx2j7i63.png)

Now let's create a SwiftUI `Preview`. Any changes we’ll make in the UIKit UI could be simply displayed in real-time and we won’t have to build and compile like earlier.

## Convert this UIViewController to SwiftUI Controller
We simply make an object from our controller which is conforming to `UIViewControllerRepresentable` to make it readable for SwiftUI.

```
import Foundation

#if canImport(SwiftUI) && DEBUG
import SwiftUI

struct ViewControllerRepresentable: UIViewControllerRepresentable {
    
    func makeUIViewController(context: Context) -> some UIViewController {
        return UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()!
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
}
#endif
```

In the code above:

- `canImport(SwiftUI)` is used to ensure it will compile only for the iOS versions which support SwiftUI .

- `DEBUG` makes sure it is running in our debug environment only.
Inside the `MakeUIViewController(context: Context)` function, you should simply instantiate the Controller you want to see in previews.
Here I just instantiated my `Main` Storyboard.

## Preview our `UIViewController` using PreviewProvider
Now that we have the UIViewController and have already converted it to SwiftUI Controller we just have to add a few lines of code for our `PreviewProvider`.

Add the following lines of code before the #endif:

```
struct ViewController_Preview: PreviewProvider {
    static var previews: some View {
         ViewControllerRepresentable()    
    }
}
```

The full code should look like this:

```
import Foundation

#if canImport(SwiftUI) && DEBUG
import SwiftUI

struct ViewControllerRepresentable: UIViewControllerRepresentable {
    
    func makeUIViewController(context: Context) -> some UIViewController {
        return UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()!
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
}

struct ViewController_Preview: PreviewProvider {
    static var previews: some View {
        ViewControllerRepresentable()
    }
}
#endif
```

Now that we have the full codebase, you can see the live preview of the `UIKit` UIViewController on-demand. Try modifying the UI slightly and notice the instant results. Say goodbye to the time-consuming building process.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w76vsw7ster1g4eezlro.png)

That’s all for now. Thanks for reading. You can check the full source code below:

{% embed https://github.com/EmadBeyrami/UIKitPreviews %}

## Buy me a coffee ☕️:
{% embed https://www.paypal.com/donate/?hosted_button_id=FRY432D75E4Q2 %}
{% embed https://nowpayments.io/donation/emad %}

### Refrences:
My Medium: {% embed https://medium.com/better-programming/swiftui-preview-provider-for-uikit-3dd089d77915 %}