3.4 Code the Reminder Rows
In the previous lesson, you learned how to populate your new table with some rows based on a list of reminders. The only problem was that you weren't able to actually put any meaningful data in each row. In this lesson, we are going to fix that problem using a similar solution to the one we just used with the list.
1.Introduction2 lessons, 05:00
2.Building the Foundation3 lessons, 27:38
3.Creating the User Interface7 lessons, 1:06:19
4.Application Logic6 lessons, 37:10
5.Conclusion1 lesson, 00:38
3.4 Code the Reminder Rows
When we last left off, we had gotten to the point where we could programmatically add rows to our reminder row table, which is pretty nice. And now using our reminder table interface controller, we are able to load up some sample data, in the form of a single reminder with two stages. And be able to set the number of rows on our reminders table, but then the problem we had was that we were now seeing, within our simulator, basically this exact view. Where we weren't getting any details about the actual reminder in the rows, we were just getting this placeholder text. Now in this lesson we want to adapt that a little bit to actually get the reminder information in there. So how are we going to do that? Well we're going to do that in a very similar fashion to how we did with the table interface controller, so let's take a look at our document outline here. And what we wanna do is, we wanna get a hold of this reminder row, so we wanna sub class this so that we can then start to create outlets between the user interface and some codes. So that we can update it programmatically. So let's go ahead and start that process. We're gonna start by selecting our Watch Kit extension folder here. Let's create a new file. So we're gonna say, New File, then within here let's go ahead and select a Swift file, because this is gonna be kind of a generic class that we're gonna add in there. Not necessarily a watch kit class. And let's go ahead and select Next. Now we wanted to do a couple things, we wanna make sure that we have the watch kit extension target selected, and then we need to give this a file name. Now you could basically pick anything you want, but what we're looking for here is basically a row controller, or more specifically, a reminder row controller, so let's go ahead and call it that. Reminder Row Controller, just so that the name makes sense. Okay, so now we have this file, so we're gonna have to do a couple of things. We're gonna need to get access to some outlets that are gonna have types that are based on watch kit types. So we're gonna have to add an import statement, we wanna import watch kit. Now we're gonna go ahead and create a class, we're gonna call this the Reminder Row Controller, and this is simply going to inherit from NSobject. And that's where we're gonna leave it for the time being. So let's go ahead and save those changes. Then we can head back over to our interface controller, and what we wanted do now is, we want to enlist the help of our assistant editor again. So the way we did that before is we hit these little two circles, and let's kind of clear out the left hand panel here. Now, this is going to show up because I was manually playing with this earlier. But you may run into a situation where if you try to select something on your user interface, on your actual scene, it may not come up with the proper file. Xcode is gonna try very hard to find the proper file for you, but that's not always going to happen. So, the next thing that you can do, is you can find whatever sort of user interface component that you have within your document outline, in this case, our Reminder Row. And then try to find the appropriate assistant editor code file that way. Now, that may not work as well, so then, what we're gonna have to do is we're gonna have to open up our right hand side, our Properties. And we're gonna make sure we have our Reminder Row selected here. And then we need to select that in the Custom Class. So we're gonna say that this is going to be our Reminder Row Controller. Now, even doing that, which we have to do anyway, may not always necessarily guarantee that, once again, Xcode is going to be able to find the appropriate code file in the assistant editor. But the good news is we can help it out a little bit. So on the top here, on the right-hand side, you're gonna see where it says manual for me right now, it may say automatic for you. And if does say automatic there's high probability that you're going to see the reminder table interface controller here. Which unfortunately, is not what we're looking for, that was for our actual table that we were using up above. Which is obviously not what we want right now. So in order to select the proper code file here, you may have to switch over to manual. Which is going to allow you to browse through all the different code files in your project, which is pretty nifty. So I'm going to select Remind Me, I'm going to come down to watch kit extension, and then I'm going to select the reminder row controller. Which is gonna take us exactly where we wanna be, and why do we wanna be here? Because we wanna create some IB outlets, so let's go ahead and expand our interphase here a little bit and what I want do is, I want to grab these labels here. And I want to drag them across over to our interface, and let's give them some names. This is going to be the reminder name label. And this is going to be a wash kit interface label, so we'll connect that. And then we'll do the same thing for the durations. So we'll put that underneath, and we're going to call this the reminder duration label like that, and select, Connect. Okay, so that's pretty good, so now we can get programmatic access to those labels, which is good, but what are we gonna bind them to? Well, we're gonna bind them to a reminder, obviously. So the way that we're gonna handle that is, is we're gonna create a reminder property, which is going to be of type reminder. But, I can't just leave it like this because if I leave it like this, Xcode is going to require me to create an initializer, and that's what this is complaining about right now. Because this is a property that needs to be set. So in order to get past that, we can make this optional like this, so we won't have to create an initializer. And I'm going to show you why we can't create a initializer just yet. So, let's go ahead and save that. Now we'll switch back over to our panel on the left-hand side and let's take a look at our reminder table controller again. We'll go back into our standard editor. Now, what we wanna do, cuz we wanna get to a point where in our awake function we set the number of rows, like we've done here, because this is the proper way to do it. But now I wanna be able to get each one of the rows that I'm cycling through, and pair it with an actual reminder that we're getting from our sample reminders. So we can do that using a loop. So we'll just create a simple for loop. We'll say for index in, and I want to create a loop and I want to loop through everything up to from zero, up to reminder table That number of rows. So I can get all the indexes found within that particularly collection and then I can use it to look up my rows and all of the reminders that I'm going to need. So let's go ahead and see how we, We can now bind these things together. Now the nice thing about finding the indexes within here is that we're able to get a row controller for all of the rows at particular indexes. So the way that we're gonna do that, Is we're gonna use a guard let, and then we'll say guard let controller = remindersTable. and we'll say rowController(at: a particular index. So what we've been able to do now is we can Because we bound the row to a rowController, we can get that rowController at a particular index just like this. But, I don't just want that, I need to get it as a reminder rowController so I can have access to that reminder property So we're gonna try to cast this to a reminder row controller but if for some reason something bad happens and we're not able to get it or maybe it doesn't case a reminder in the row controller maybe it's something else then we don't want this line to bomb out that's why we're using a guard let so if something bad happens we can say else we can just continue. So we'll just skip over that one we don't care about it anymore. And now we can continue on our merry way. So now what we can do is we can use that controller because we can know it's a reminder road controller and then we can set that reminder equal to reminders index. Okay now let's save that. Now this is nice and we're getting a little bit closer but there still is a little bit of a problem. There's nothing that's actually going to be setting. The properties at that rollControler. So you can see we're setting this reminder but we're not actually doing anything with these two labels, these two IV outlets. So, how can we fix that? Well, the reason why we didn't use initializers because we don't actually get the opportunity to do that, we're using the remindersTable.rowController function to get an instance but we're not in control of that instance so what can we do to bind this new reminder that we have to these. Well the answer is in the cool little feature of Swift known as property observers so we're going to come down in here to this reminder and we're going to use a property observer Called didSet. Now didSet is an observer that's going to fire when anything within our application, when anything in our code sets the property of this. And so what we want to do at the point where it's set, well, if it's set with a valid reminder then I want to set these labels right here. So the first thing we'll do is we'll do a guard let. And we'll say if reminder is equal to Reminder, then else, which basically just means that this gets set properly. And if it did, then I want to use my reminderNameLabel.setText to reminder. Name and then I want to use my reminder duration label to set the text here of reminder.duration. Now we'll save that. Now we'll go ahead and run our application again and Xcode is going to build it all for us and if we have everything Wired up correctly, we should be able to see not only that we have a reminders table that's being populated properly. But we're also getting rows that get the proper information set. So, as you can see here, I had a single Reminder in my list called Morning Wakeup. And now I'm getting that formatted duration that we used that protocol extension for. And just to show you that we're not cheating here we can come back into our reminder table. Let’s go ahead and add in one more. So, we’ll grab these, and we will come down here, we will paste that and we we’ll say that this is going to be reminder two, and we’ll just call Call this our Evening Winddown, maybe, something like that, if that's a word. And then we'll go ahead and set this to be stage3 and stage4. And then we'll have a stretch And then we'll have a snack maybe, just for the end of the night, and these maybe don't require time but you never really know. So then we'll come into our reminder two and then we'll go ahead and go into stages and will simply append a new element. We'll append stage three, and we'll do reminder two.stages, append, and we'll append stage four, and then we can now add this guy in as reminder To. Let's go ahead and save that and one more time we'll run and now we should see two different reminders in our list and these are gonna have the same times because I didn't change them but you will see that we can add dynamically at any point when our reminder list grows. So there you go. So now we're able to populate the. Table with rows and then bind directly to them, but now we're not able to do anything with this. I can select these and nothings happening, now we need to start building the rest of our application where we actually start to go to a new scene within our watchkit app, and start to display some new data.