This is based on a post on my Substack, but I’ve expanded it into a working example.
I haven’t worked with Combine much, but I wanted an easy way to get data into my SwiftUI project without using the conventional
Instead of creating a
Publisher in my
ObservableObject, I decided to create an extension of
URL that would assign a
dataTaskPublisher to one of my existing
The function has a generic parameter, but the parameter has to conform to the
Codable protocol. This means that it can be created from the data that the
dataTaskPublisher returns, provided that the data matches the expected structure.
Because this is an extension of Apple’s provided
URL class, we already have access to a URL in the form of the current instance
self. We need the code to run on the main queue, as otherwise the
@Published property would not update the SwiftUI views displaying the data.
.map(\.data) is used to reduce the results to the data alone as otherwise we would also have access to the server response to the request. Now we can actually decode the data into the
Codable structure, as we know that the type we’ll be returning conforms to that protocol.
assertNoFailure in order to ensure that there are no errors at this stage. Without doing this, I would not be able to assign the resulting structure back to the
@Published property that was passed to the function.
The data we’ll be retrieving is from the API for the webcomic XKCD.
Most of these properties won’t be used in our example, but it’s useful to have the data in case you want to try displaying the other information.
DataModel class has a
@Published property that stores the
XKCD data, but it is
nil by default. In the initialiser for the
DataModel class, I call my
getFromPublisher function on a URL. This will give us the data, but we also need to set the image. The image will be set by the getImage function, which will be called in the SwiftUI.
The last thing we need to do is display the data, which is what SwiftUI is for!
As you can see, the SwiftUI is not displayed until the XKCD data has been loaded. When it is loaded, the title is displayed at the top. When the title appears it calls
dataModel.getImage() and, when the image is set it is displayed underneath.
This particular endpoint only shows the latest comic, but feel free to add more functionality if you want.