Hey, guys. In this lesson, we're gonna be talking about the UITableView 1
which you see pretty much all across iOS and it's one of the bread and butter skills 2
that any iOS developer need to have. 3
So how do we create such a nice scrollable table view? 4
Well, you get started by adding it from the object library, of course. 5
So if you search in here for table view, then you'll be to find this component, and you can drag it onto 6
a screen. 7
So let me just create a new dummy screen. So let's search for a view controller. And go ahead and drop 8
that there. 9
And if I wanted part of it to be covered with a table view, then I could select this table view component, 10
drop it on here. And just as what we've done with that image views or other types of views, we're just gonna 11
put it onto the screen in these sort of dimensions that we want. 12
So in this case, I only want half the screen to be covered by a table view. 13
Now, the other key component of a table view is a table view cell. 14
And even though we only have one cell, it's actually what's called a prototype cell. 15
So it's a cell that's going to be reused lots and lots of times in order to populate every single cell 16
in the table view. 17
So notice if you look in your mail app, every single one of these cells are structured pretty much the 18
same. 19
They have a title that's in bold. 20
They have a subtitle which is the body of the message, and then they've got a disclosure indicator on 21
the right as well as a little bit of gray text here indicating when the message was sent. 22
And then here they've got the capability of a little blue dot. 23
So, essentially, all of these cells are identical other than what's gone into each of these fields. 24
And that's created from these prototype cells. 25
So you can, for example, add a disclosure indicator to all of the cells, or you could make it not selectable, 26
or blue selection, grey selection, you can change the style of it so that it has a title and subtitle, 27
or you can have it with a right detail, left detail, but I'm actually going to keep it as the original 28
which is the custom cell. And I'm going to get rid of that disclosure indicator. But what's really important 29
when you create a prototype cell is to give it an identifier. 30
This is the identify that we're going to be using inside our code to identify which cell we want displayed 31
in our table view. 32
So notice how in the presetup ChatViewController, we've already got an identifier called ReusableCell. 33
And if you look inside the Constants.swift, you also have a type property code cellIdentifier 34
which is set to equal that string. 35
So they should be the same. 36
Now, notice how when you look inside the Object library, there's also such a thing as a Table View Controller. 37
And this is sort of a more specialized view controller namely one that can only really show a table 38
view. 39
So I tend to prefer the flexibility of a normal view controller and I can put in a table view to either 40
cover the entire screen or part of the screen or however I like to lay it out, but I don't actually enjoy 41
using the Table View Controller too much because it's a little bit more limiting. 42
So I'm going to delete both of these screens and head back to my previous design that you should all 43
have. 44
And we're going to get started putting some content into our table view. And the first step is to create 45
a model. 46
So we're going to be creating a model for our messages. 47
So we're gonna be selecting a iOS Swift File and this is going to be called a Message, 48
so singular, 49
and go ahead and click Create. Now, the Message.swift file is going to contain a struct code Message, 50
so exactly the same. 51
And inside here where we've got the field's placeholder, I'm going to replace it with the properties 52
that every method should have. 53
One is a sender. 54
So this is going to be a string data type because it's going to contain the email address of the person 55
who sent the message. 56
So, for example, it'll be 1@2.com or one of the other uses that I've registered. 57
And the second property is going to be something called body, which is going to contain the body of the 58
message, 59
and this, of course, also should be a string. 60
So that's it. 61
We've created our message structure which is going to be the model for creating messages from now on. 62
So if we head back into our ChatViewController, at the very top just below the IBOutlets, I'm going 63
to create a new variable which is going to be called messages. And this is going to contain an array 64
of message objects. 65
So let's go ahead and set that to equal a new array. And inside this array, I'm going to populate it with 66
just three messages to begin with. 67
So the sender for the first one is going to be 1@2.com. And the body of the first message 68
is just going to be "Hey!!" Now, I'm going to add a comma to separate the first item from the rest of them. 69
Now, I'm going to populate it with two more messages that I've written already, 70
so you don't have to watch me type. But, essentially, we've got two senders here, 1@2.com. 71
who's talking to a@b.com. 72
And the 1@2 said, "Hey!" and then got the reply of "Hello!" and then said "What's up.?" 73
So that's all we've got, three items in our messages array which has a data type of Message which is 74
the data type that we've used to structure our messages so they can have a sender and a body. 75
So how do we get these displayed in our table view? 76
Notice how I've already linked up the tableView as an IBOutlet. 77
And if you need to do this in the future when you're creating your own table views, then it's done exactly 78
the same way as you've done before where you simply select the table view, either in the document outline 79
or in the Interface Builder, hold down control and drag, and then you'll end up creating an Outlet. 80
So this Outlet is connected to our tableView and the ChatViewController and its name is tableView. 81
So, now we can access this tableView and we can populate it with some data. 82
The way that you populate data in a tableView is slightly different from how you might imagine it to 83
be. 84
So you might think that somewhere in viewDidLoad or somewhere else, you might say a tableView.cell, 85
et cetera, but actually it works with delegation. 86
Let's scroll down to the very bottom of our file and outside of our existing ChatViewController, 87
let's create an extension, and we're going to extend our ChatViewController so that it can adapt the 88
UITableViewDataSource protocol. 89
So that means that when our tableView loads up, it's going to make a request for data. and in 90
our viewDidLoad, 91
we're going to say that the tableView's data source is going to be set as "self." 92
So it's going to look to our ChatViewController and trigger the delegate methods in order to get the 93
data that it needs. 94
That's why down here, we've got some methods that are required in order to conform to this protocol. 95
So let's click Fix so that it will automatically insert the methods that we need. 96
The first one is table View numberOfRoseInSection, 97
so how many rows or how many cells do you want in your tableView. 98
And it expects a output. 99
So you have to return an integer in this delegate method and that integer will be used by the tableView 100
to allocate the required number of cells or number of rows. 101
In our case. we know that we've only got three messages, so you could simply return three. But this is 102
pretty bad because it's hardcoded. And in the future, when we have new messages, it's not going to adapt. 103
So let's change this instead to use the messages array and use the count property to return a number 104
dynamically depending on how many messages there are in this array. 105
So that's the first delegate method tackled. The next one is tableView cellForRowAt indexPath. 106
So the indexPath is the position. 107
So, essentially, this method is asking us for a UITableViewCell that it should display in each and 108
every row of our table view. 109
So here we have to create a cell and return it to the tableView. 110
So let's do that now. 111
Let's create a cell and we're going to set it to = tableView.dequeueReusableCell withIdentifier 112
for index. 113
So what this does is it returns a reusable cell object for the specified reuse identifier and adds it 114
to the table. 115
So what is the reuse identifier? 116
Well, that, remember is what we set in our table view prototype cell. 117
So if you select the ReusableCell and you go to the Attribute Inspector, you should see it right here. 118
And I've also included that in the constants. So we can access it simply by accessing our struct K 119
cellIdentifier. 120
Let's do that right here K.cellIdentifier 121
and that will be our cell's identifier. 122
And then the index path is simply the current one that the tableView is requesting some data for. 123
So this method is going to get called for as many rows as you have in your tableView. 124
So currently, our message.count is three. 125
So this is going to return three which means that this method is gonna be called three times and each 126
time it's asking for a cell for a particular row. 127
Now, let's go ahead and add the indexPath property that came from this delegate method in here, and we've 128
now created a brand-new tableView cell. 129
It's still giving us an error saying that we're missing return in a function expected to output 130
a UITableViewCell. 131
We will do that eventually, but we're not in a hurry. 132
The next step is I want to give the cell some data, right? 133
So I'm going to tap into that cell and I'm going to edit the textLabel property and that will correspond 134
to the main label in the cell. And then I'm going to tap the text property of this textLabel. 135
And for now, I'm just gonna set it to equal the word 136
"This is a cell." 137
And finally, now I'm ready to return this cell 138
and that is going to be slotted into my tableView. 139
Let's go ahead and give it a spin. 140
So let's log in and you can see we now have three cells. 141
This is a cell, this is a cell, and this is a cell. And we have three of them because of this method and 142
they have a textLabel with the text. 143
This is a cell because of this method. 144
So what if we wanted to say something different in each of the cells? For example, what if we wanted the 145
actual row number to be printed? 146
Well, we can get access to the row number by tapping into this indexPath property. So we can say 147
indexPath.row. 148
And that is going to correspond to the row number that's currently requesting for some cell data. 149
Now, because this is an integer, in order to turn it into a string, I'm going to use the string interpolation 150
method and put it inside some double quotes. So, now let's run our app again. And now you can see that 151
we're getting the row number being inserted as the textLabel's text. 152
The first row is row 0, then row 1, then row two. 153
So how can we use this indexPath. row in order to pull out the body of the message from our messages 154
array? 155
Well, that should be pretty simple. 156
All we need to do is to take our indexPath.row and put it inside a set of square brackets to subscript 157
our messages array with this number. 158
So that means when the tableView is requesting the data for the 0 row, then this is going to be equal 159
to zero, 160
and it's going to pull out the message at position 0. 161
So this one. But this is not enough because this currently has type message. 162
Instead, we actually want the body property out of this message to be put into the cell's textLabel, 163
right? 164
So, now let's run our app. And you can see we've now got all the messages that came from our messages 165
array being populated in each of these cells. Now, you might be wondering, hey, this looks a little bit 166
different from what I've seen in mail. 167
Where are the separators? 168
Well, we can actually go into our storyboard and set a setting on the tableView. 169
So if you go into the Attribute Inspector and you take a look at the Separator property, I've actually 170
said it to None. But you can, of course, set it back to default which gives you that separator that you're 171
probably familiar with from the mail app like so. 172
But in terms of our messaging app, it doesn't really make sense. 173
So I'm going to set that back to None, so that we have our messages showing up later on in speech bubbles 174
without the separators. 175
Now, the final thing I want to show you about tableViews is that in addition to a TableViewDataSource, 176
they also have a protocol called the tableViewDelegate. 177
Now, the difference here is that the data source is the protocol that's responsible for populating the 178
tableView, 179
so telling it how many cells it needs and which cells that put into the tableView. But we can also create 180
an extension for our ChatViewController that has the UITableViewdelegate's protocol adopted. 181
And in order to use this, we, of course, have to go back up to our viewDidLoad, take our tableView IBOutlets 182
which is linked to the table View in our Interface Builder and set its delegate to "self." 183
Now, what'll happen is whenever the tableView is interacted with by the user, 184
say, for example, if a particular row in the tableView was selected, then we're going to get this method 185
triggered in our ChatViewController because we've set this current class as the delegate. 186
So let's go ahead and print the indexPath.row 187
of the tableView that we're selected. 188
So let's go ahead and hit run. And what we're expecting is that when I tap or when I click in the simulator 189
on one of the cells, then it's going to print the indexPath of the cell that was tapped on. 190
So this should be cell zero. 191
So let's click that and we get zero. 192
This should be cell 2. 193
So we get 2 and this should be 1. 194
So, now that means that we can receive messages from the tableView when the user interacts with our 195
tableView and we'll get to know which cell they interacted with so that we can do things, for example, 196
so if we had a to do list, then we might check each item off, and we might change these cells, et cetera. 197
But in our messaging app, we actually don't want the user to be able to interact with each of these cells. 198
So I'm actually going to go ahead and delete all of this code here as well as setting the delegate down 199
here. And the other thing I'm gonna do is I'm going to go into my Main.storyboard, select that prototype 200
cell, and change these selection property to None. 201
So this way, when the user taps on each of those cells, instead of turning grey, but doing nothing. 202
It's actually now going to not allow any sort of interaction. 203
So when you click on it, nothing happens, which is kind of the normal behavior of a chat message. 204
So that's it. 205
In this lesson, we learned about the UITableView and how to set up the UITableViewDataSource protocol, 206
as well as the UITableViewDelegate protocol. In the next lesson, instead of having these plain old 207
messages and the bog-standard table view cells, we're going to jazz it up and we're going to create some 208
custom UI views to put in here, and we're going to create some message bubbles. 209
So all of that and more, I'll see you on the next lesson.