In the last lesson, we wrote the networking logic for our app, and we were wondering how to show our results 1
on the screen. 2
How can we pass the results from our network manager to the List inside the ContentView? 3
Well, the simplest way of doing this is by making our NetworkManager conform to a protocol called 4
ObservableObject. 5
And this means that it can actually start to broadcast one or many of its properties to any interested 6
parties. 7
So let's create a property code posts and initialize it as a new array of Post objects. 8
And once our networking completes and we get hold of the data from the API inside our constant code Results, 9
well then we can set our posts to equal the results.hits. 10
And notice how hits is, of course, an array of Post objects which matches perfectly with all 11
variable code posts. 12
The only thing we have to do is to change the posts to add the self.posts because we're inside 13
a closure. So, now that we've got this posts which stores all of the results hits, 14
so essentially this array here of all the Post objects, 15
the next thing to do is to actually publish our posts to any interested parties. 16
We do that using a property wrapper code @Published. So, it's kind of like your RSS feeds if you will. 17
If you subscribe to this property code posts, then you'll be able to hear from it whenever the contents 18
change. And in order to listen to it in our ContentView, we're going to create a object from that 19
Network Manager class. 20
So it's going to be called networkManager and it's going to be initialized from NetworkManager, 21
and then I'm just going to add the parentheses to initialize that. And this NetworkManager is going to be 22
marked with a property wrapper code @ObservedObject. 23
So notice how there is a ObservableObject which is the protocol here, 24
so it makes the NetworkManager observable. And then one or many of its properties can be published 25
to say that whenever it has changes to notify all of the listeners. And to set up a property as a listener, 26
we add the @ObservedObject property wrapper. 27
In this way, we're subscribing to the updates from the NetworkManager. 28
So, now whenever the networkManager updates, 29
this is going to trigger. And we can use the networkManager.posts properties to update our list. 30
So inside here, instead of using the posts which comes from this static list which are common out, 31
we're going to be using the networkManager.posts. And that is, of course, our published property right here. 32
So whenever post changes, then it's going to trigger a rebuild of our list updating everything that's 33
inside. 34
Now, notice there's just one thing missing. 35
No where do we actually call this fetchData. 36
So where can we do that in our SwiftUI ContentView? 37
Well, with every ContentView, there is a method called onAppear. 38
And this onAppear is almost like our viewDidLoad that we've gotten used to in our UIKit world. 39
So if we call this onAppear method with a perform property, then we can pass a function in here that 40
will be performed when this body view appears on the screen. 41
So in this case, the perform is, again, going to be a closure, so we can select this placeholder and hit 42
enter to turn it into a trailing closure. And inside these curly braces, we're going to get 43
our networkManager to trigger the fetchData method. 44
And, of course, because we're inside a closure, we have to add "self" in front. So the whole sequence of events 45
now is our view loads up, a NavigationView with a list, and a navigation title. And as soon as it appears, 46
we trigger the NetworkManager's fetchData method. And this will take a little while depending on the 47
internet speed to fetch the data from 48
the Algolia Hacker News API. 49
And once we get the data back, we decode the data. 50
If there were any errors, then we captured and imprinted. 51
But if there were no errors, then we go ahead and save the results.hits which contains an array of 52
post objects to all Posts property here. And because this post property is published, it means that anybody 53
who is subscribed to the observed object, so the network manager will have the post property updated 54
in real time, and the UI will update accordingly. 55
Now, there's just one last thing that we have to do which is the point when we use @Published, 56
we always have to make sure that we fetch the main thread. So we have to tap into the dispatchQueue 57
and we're going to tap into .main.async. And inside this closure, we're going to set the published 58
property. 59
So if you don't, you'll get an error in the console. But, effectively, it's because this property is a property 60
that other objects are listening to. This update for it must happen on the main thread. If it happens 61
at the background, then our content view will get notified in a timely fashion. 62
So, now all that's left to do is to go ahead and run our app and see whether if we're able to get our 63
post title showing up from the API. 64
And when we run our app, you can see that there are parts of our app which are working just fine, 65
but our list is not rendering and the error that we're getting is something called valueNotFound. 66
It's telling us that our URL property seems to have a value of nil, 67
so we expect it to have a string value but found null instead. 68
So what's going on here? 69
If we take a look at the data that's being rendered from the results of the API call, you can see that 70
the URL property tends to have a string value. But there are certain cases, especially the 71
Ask Hacker News posts where there is actually no URL at all. 72
It's just a text post with a question and a whole bunch of comments and answers. 73
So in this case, because URL is null, our decoder actually fails and we catch the error by printing 74
it out. 75
So what can we do? 76
Well, we can change our URL to an optional string to allow it to be null in certain cases. 77
And now if you rerun the app, 78
you'll see that our list is now being rendered and we're getting all of the titles that are from our 79
live API data. 80
So let's jazz up our list a little bit. Instead of just having a single piece of text, 81
why don't we add our post title as well as the number of points the post received, 82
so the number of upvotes, and we can nest this inside a HStack. 83
The first thing that we're going to show is the number of points. So we can either turn it into a string 84
by using the string initializer, and then tapping into post.points. 85
Alternatively, you can also use string interpolation, but both ways work the same. 86
So let's run our app again and see if we can get the points property rendered on screen. 87
So there we go. 88
We've got our points now showing up on the left, our titles showing up in the middle, and each cell in 89
the list is being adjusted to be able to show all of the text. 90
So that's pretty neat. And you could stop here if you wish. 91
But what if we wanted to be able to show each of the links inside our Hacker News app? And that's exactly 92
what we'll do in the next lesson. In the next lesson, 93
we'll add the finishing touches to our app by making the links open up inside a web view from within 94
our app. 95
Also we'll handle the navigation between the list of Hacker News items and those web views. For all of that 96
and more, 97
I'll see you in the next lesson.