Shoehorning SwiftUI and Create ML — Part 1
My recent journey trying to learn two WWDC 2019 things at once
This year, I completely missed keeping up with WWDC 2019… because my son was born… so I’m pretty sure I get a pass.
So now, well over a month later and after settling back into work, I decided to check out what I missed.
All three are reactive, UI -focused development frameworks, meaning they are specifically set up to make constructing UI’s as simple as possible, while also bridging the gap between them and the data they’re supposed to show.
I like this “new” way of building UI’s. To make a comparison to what I’ve known before, it’s like readable HTML or Android XML where UI and code can actually coexist.
But that’s not all that caught my eye. I also saw a demo of the new Create ML app, which makes creating ML models a bit more user-friendly.
I admit I’ve been curious, after reading only like, a gazillion clickbait article titles, about how machine learning is the future of everything. I figured, now that it seems to be click-and-draggy, I don’t really have excuses anymore.
Disclaimer: This is more of a narrative, not a step-by-step. But I will point to the code I referenced and the GitHub repo of the project.
Being impatient, I wanted to learn both at the same time.
Essentially, I’ll be generating a list of test flowers and, in their respective detail view, I’ll check to see if my ML model’s prediction is correct and whether it reactively display the results.
What we’ll need:
- macOS Catalina beta (sorry, can’t do SwiftUI or use the new Create ML without it)
- Xcode 11 Beta
- Flower data
Note that, on occasion, something in SwiftUI might share a name with another familiar Swift element (e.g.
List). I’ll denote SwiftUI elements with (SUI).
Building the App (SwiftUI)
I created a new iOS single-view project and made sure SwiftUI is checked off below where you enter a project name (side note: I went with FlowerPower).
ContentView, I created a simple
List (SUI), where the contents make up what will be our cell. The cell is an hstack with an image and text and that’s more than enough for now.
To get fancy, I CMD + clicked my hstack and chose Extract Subview, creating a new
What makes the whole SwiftUI experience that much better than my other experiences really is the Preview window.
It is very responsive to any change I make and I love that you can run the app within it.
I know React and Flutter can kind of do the same thing, but Xcode provides various degrees of seeing and testing your app (Preview, semi-built Run mode within Preview, and then traditional Run).
An important thing to note is filling in your UI with test data. Ideally, you should use the
ContentView_Previews struct, but for this screen, just have the list iterate five times and fill your cell with placeholders.
Next, in a new file, create a Flower struct that will hold the name of the flower, the classification (for comparing with our predictions), and the image name.
In the same file, there is test data originally for use with Preview, but then I realized that this is just an app for fun, so instead, I left it open so it would be static for the app as well.
The test data is a list of five flowers with images I pulled off Google images, one for each class of flower (dandelion, tulip, daisy, rose, sunflower). These images were then placed in the project Assets.
Now, back to the
ContentView, where I created a let for my test data.
I had my
List (SUI) become a for each based off the data, added a parameter to my
FlowerCell to take in a flower, and pointed the image and text to reference the flower properties.
So far, in my preview, I was seeing my results.
Knowing that I would be creating a Detail page, the last thing to do was wrap my View in a
NavigationView and my cell in a
NavigationLink. Except for having a destination to go to, my main page is complete!
For the Detail page (where I plan to also run the ML Model), I created a new SwiftUI file and called my new View
FlowerDetail with a parameter for the flower we’ll be displaying/analyzing.
Quickly, I jumped back to my
ContentView and now set my
NavigationLink destination to
FlowerDetail, passing in the cell’s flower.
FlowerDetail, I simply created a vstack with an image for our flower, spacer, text to show our results, and a button to trigger our model.
Before wrapping up part one and getting into the ML portion, I decided I would mess with a
What makes SwiftUI reactive, are the new ways to data and the UI can be synced.
Here, I created a new var called
matchResults and prefixed it with an
I set it to a default text (e.g. “Click below to run the model!”) and set my text view in the vstack to
matchResults is now set, SwiftUI will tell any view that references it, that it needs to update.
matchResults will have three States represented by three strings:
- “Click below to run the model!”: The default message set when we create the
- “Match”: The message that will show if the model finds a match.
- “Not a Match”: The message that will show if the model doesn’t find a match.