CS 4153-5153 Update: Live Preview on Xcode using UIKit

If you are using UIKit, then the current Xcode version you are using may not have the (Live) "Preview" option that Dr. Mayfield uses in Video "12.04 Demo - Auto Layout". If so, you can carry out the following steps to access the same functionality. 

Currently, Live Preview is carried out by SwiftUI. The following code allows you to wrap a SwiftUI ViewController inside UIViewController.

Step 1: In the Project Navigator on Xcode (for students in CS 4153–5153, Spring 2023, OSU, the project name will be “Stack View Demo”), right click on the project name and select "New File" from the drop down menu.

Step 2: That should bring up the dialogue box shown below. Select "Swift File" and hit "Next". I am naming this file "ControllerPreview".


Step 3: This new file will probably have only line of code "import Foundation". Delete that. Then copy paste the following into your code. This acts as an extension file and allows us to create multiple previews by reusing the code. Make sure to save the file.

import UIKit


#if DEBUG

import SwiftUI


@available(iOS 13, *)

extension UIViewController {

    private struct Preview: UIViewControllerRepresentable {

        // this variable is used for injecting the current view controller

        let viewController: UIViewController


        func makeUIViewController(context: Context) -> UIViewController {

            return viewController

        }


        func updateUIViewController(_ uiViewController: UIViewController, context: Context) {

        }

    }


    func toPreview() -> some View {

        // inject self (the current view controller) for the preview

        Preview(viewController: self)

    }

}

#endif


Step 4.1: In projector navigator, click on the "Main" (aka. storyboard) file. Click on the "header" of the storyboard and make sure it gets outlined in blue (this is very important). Next open on the Inspector deck (as shown below) and click on the "Identity Inspector". On this deck, under "Identity" there is a subfield called "Storyboard ID"; enter the name of your ViewController file here (in our example the name of the file is "ViewController" as well).

Step 4.2: Go back to the project navigator and open the "ViewController" file. Modify the file as shown below. 

import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view.

    }



}




#if DEBUG

import SwiftUI


@available(iOS 13, *)

struct VCPreview: PreviewProvider {

    static var devices = ["iPhone SE", "iPhone 11 Pro Max"]

    

    static var previews: some View {

        ForEach(devices, id: \.self) { deviceName in

            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: 

"ViewController").toPreview().previewDevice(PreviewDevice(rawValue: deviceName))
.previewDisplayName(deviceName)  

        }

    }

}

#endif


Step 5: Save and then hit "command+option+enter" keys together. Doing so should create the dynamic previews for  iPhone SE and iPhone 11 Pro Max as shown below.

Step 6: To change the iPhone versions you want to preview, modify the devices variable. Currently, it is set to preview only iPhone SE and iPhone 11 Pro Max. To include, say iPhone 8 preview, change the code to following:

devices = ["iPhone SE", "iPhone 11 Pro Max", "iPhone 8"]

and this should add an additional Preview window as follow: