I’m Only Happy When It’s MVVM — Part II
Preface
Last time, we built a bog standard “Hello, World!” MVVM based app in SwiftUI using Combine. In this post, we’re going to query an API for some items, and render them in a grid.
We will use our existing files, as well as make more. So, open up the project we built last time, and let’s get going!
(NB: This series will focus on using SwiftUI components to achieve everything where possible, and I will try to avoid wrapping UIView objects.)
Prerequisites
Let’s Fly!
To better separate our concerns, go ahead and make a new file for our ViewModel
protocol, and move its definition in there if you haven’t already done so. We skipped doing this in Part I for the sake of brevity. However as this post is expanding upon the foundation we established last time, we should introduce some better practices.
Next, make a new Swift file and call it ServiceType
. In here, we want a protocol which defines the bare minimum we’ll need to query most RESTful APIs, and an extension of the protocol to provide a default implementation of getting our data.
An example to copy pasta is attached below:
Hold up…errors?
That’s right, we haven’t defined ServiceError
or RequestType
yet. Let’s not forget to put each of these declarations in separate files to prioritise separation of concerns.
Lastly, before we define our service to query all emoji, we need to head over and look at the documentation. Why? We’re going to define a data model! This will be used by our service, and subsequently by our ViewModel
to render the view.
The documentation tells us that a returned emoji is comprised of six separate String types in a JSON object, and that the entire list is an Array. This is why our EmojiListRequest
defines its Response
as [Emoji]
.
Servicing The Engine
It’s time to build our service! Thanks to the protocol, it’s very straightforward. We need to define our baseURLString
, our array of AnyCancellable
, an initialiser which calls our binding function. If you hadn’t already cottoned on, it’s just like our ViewModel
from Part I.
Make sure to read all the comments to understand what’s going on in more detail. Since they’re included in the gists, details have been excluded from the article to keep things brief and exciting. 😉
If there’s a better way to handle something like this in SwiftUI/Combine-land, please drop me a line!
Updating The View Model
Go ahead and replace the ViewModel
from last time with the following copy pasta. We’re solely listening to our service, and taking the values into our view model.
Once you’ve done that, it’s time to update our view!
viewDidAppear 😉
Go ahead and replaceContentView
with the following copy pasta.
We can see that because we are using a LazyVGrid
, we’ve needed to define an array of columns. It’s set to four, because the performance of the component with more columns was a little…meh. Maybe it’s the simulator, maybe it’s SwiftUI itself. Time will tell…
Errors?
Read them carefully, and make sure the Emoji
type conforms to what it doesn’t yet. You’ll need a couple in there… a good id
ea is to the make the id
property the codeString
for better reuse.
If we go ahead and run the app now, we’ll see a navigation bar, and shortly after that, a list of emoji!
(NB: Some emoji don’t render, but that could be because the host Simulator is running iOS 14.1, not iOS 14.2)
In Conclusion
With the completion of Part II, we’ve have taken a basic “Hello, World!” MVVM app, and turned it into a semi-functional real app. We copied and pasted aaaaaall the code, and that’s haaaaaaaaaaard work y’all!
If you enjoyed this post, please let me know what you think.
Catch you in Part III