Scripting a process for the Example Code Xcode Project

An update to the Example Code workspace what we use on Step Into Vision.

Background:

When working on Example Code for this website, I generally don’t want to make an entire Xcode project just to teach a simple concept. Prior to starting Step Into Vision I cobbled together a simple project structure. I’ve been using that for Example Code and Labs. I create a Swift file for each Example or Lab (separate Xcode projects). I do all the work for the example in that file. This works well for me, but the way I set up the project meant that I had to do a handful of things each time.

  • Create the swift file, normally using a file template and serialized name (Example001, Example002,…)
  • Update a router to add a new case to a switch statement (case "Example 001": Example001()…)
  • Create a new entry in the directory. See below.
  • Update file metadata at the top of the file. I normally do this at the end when adding comments and notes.
// Example struct
struct Example: Identifiable {
    let id = UUID()
    var type: ExampleType
    var isFeatured = false
    var date: Date
    var title: String
    var subtitle: String
    var description: String
    var success: Bool = true

    init(title: String, type: ExampleType, date: Date, isFeatured: Bool = false, subtitle: String, description: String, success: Bool = true) {
        self.title = title
        self.type = type
        self.isFeatured = isFeatured
        self.date = date
        self.subtitle = subtitle
        self.description = description
        self.success = success
    }
}
// Example Examples
class ModelData {
    var exampleData: [Example] = [

        Example(title: "Example 001",
                type: .WINDOW,
                date: Date("10/15/2024"),
                isFeatured: false,
                subtitle: "Open a 2D Window",
                description: "Testing out the window")

        ,Example(title: "Example 002",
                 type: .VOLUME,
                 date: Date("10/15/2024"),
                 isFeatured: false,
                 subtitle: "Open a Volume",
                 description: "Testing out the volume")

        ,Example(title: "Example 003",
                 type: .SPACE,
                 date: Date("10/15/2024"),
                 isFeatured: false,
                 subtitle: "Open Immersive Space",
                 description: "Testing out the immersive space")
    ]
}           

The data that shows up in the UI lives in ModelData. The title is also used for the switch statement in the router. This process has worked well, but I’ve wanted to improve it for some time. The main issue is that at some point we actually have to use the SwiftUI file for each example. Swift won’t let us compute the name of a View at runtime. My workaround to this was the Directory (data) and Router (turning data into Views).

I’ve been tinkering on a new process that replaces (or automates) this based on the metadata in the header of each Example file.

//  Step Into Vision - Example Code
//
//  Title: Example132
//
//  Subtitle: Spatial SwiftUI: Preferred Surroundings Effect
//
//  Description: We can use this SwiftUI modifier to adjust the lighting and tint color for the passthrough feed.
//
//  Type: Window
//
//  Featured: true
//
//  Created by Joseph Simpson on 12/8/25.

A new script will read the metadata from all the Swift files in the Examples folder. It will generate a new ExampleRegistry with all the data the UI needs. The comments above becomes this:

    Example(
        title: "Example 132",
        type: .WINDOW,
        date: Date("12/8/2025"),
        isFeatured: true,
        subtitle: "Spatial SwiftUI: Preferred Surroundings Effect",
        description: "We can use this SwiftUI modifier to adjust the lighting and tint color for the passthrough feed.",
        makeView: { AnyView(Example132()) }
    )

Which then becomes this in the app:

The UI for the Example Code app

The obvious downside to this process is that the data is in comments instead of code. I can live with it.

Video Tour

I recorded a short video to show this in action. This provides a bit more background, an example of changing a file, and an example of creating a new one.

You can take a look at the script. Codex did most of the work on this one. I just made a few small changes to replace depreciated features.

The updated readme contains the process to run this script from the terminal. I also worked on a new Build Phase script to run this with each build. It took some trial and error but I have it working (again, thanks to Codex).

The key here was set User Script Sandboxing to No.

The next steps will be to port this to the Xcode projects for Labs and Dark Spaces. I’d also like to make an empty Xcode project template so we can use this for other topics.

Feel free to download the entire Example Code project. Let me know if you run into issues building it with the new script.

Questions or feedback?