3.3 Code the Reminder List
While it is nice to see your beautiful list in the design view, it isn't very helpful to the end users if you can't show them meaningful data. In this lesson, we'll get programmatic access to the UI and populate the list with actual data.
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.3 Code the Reminder List
All right, let’s start to programmatically get some access to the things that are going on within our new reminders table. So like we did in a previous lesson, the first thing we wanna do is we want to create a Swift file that we can use as a subclass to get ahold of this interface controller. So let's go ahead and see what we are going to do to kind of fulfill that requirement. So let's go ahead and select our extension folder here. And then we'll select File > New > File. And then within here let's make sure that we've selected watchOS and WatchKit class. We'll select Next, and then in here, let's go ahead and call this something a little bit more meaningful. Maybe we'll call this ReminderTableInterfaceController, and the subclass is going to be the WKinterfaceController. The language is going to be Swift. So let's go ahead and click Next. And we want this to be within WatchKit extension, using the WatchKit extension target. We'll click Create and now within here, if I go into my interface controller, I can now select this interface controller, come up to my custom class. And now I wanna select my Reminder Table Interface Controller. Okay, that's good, but now what I also wanna do is I wanna get programmatic access to this table right here so that I can do things with it like populating it with the different reminders that I have within the system. So let's go ahead and get ahold of that. So we're going to open up our assistant editor again, and let's close out some of this stuff so we can get some added room. So now what I need to do is I need to select this table. Not necessarily the row, we're gonna deal with the row in the upcoming lesson, but in this case I wanna get access to the table. So you've seen before where we've clicked and dragged or we have Ctrl+Clicked and dragged from the user interface, but you can also do the same thing from the document outline. So if I go ahead and Ctrl+Click from here and I drag from my table down into my ReminderTableInterfaceController, then I can let go here. I'm going to create an outlet, and this is going to be my remindersTable, or something like that. In this case, we want to change the Type to make sure that it's WKInterfaceTable, and storage Weak is fine. So we'll go ahead and click Connect there. Okay, so that's pretty good. Now I have access to the table that's in there, so what do I wanna be able to do now? Well, what I'd like to be able to do is I'd like to modify what is actually showing up in here, or more specifically, the amount of rows that are showing up within my table. And it's actually pretty simple. So what we can do just to show a simple example here, is I can come down into my awake function. And this is kind of, like I've said before, one of those first opportunities that you can really start to add in some UI components to your InterfaceController as your App is kind of waking up as it were, so that you can do things with it. So what you can do in here is you can actually use your remindersTable and you can use a function on there called Set Number of Rows. And so just as a quick example, we'll say set number of rows going to be, we'll say, 5. And then with type, so withType is something that we need to talk about for just a moment here. So before I set that, if I were to come into my Table Row Controller, and if I were to select this and come back into my properties, you're gonna see in the Attributes Inspector that I have this identifier. And this identifier is gonna become very important, in that what I can set in here, what I can use as my identifier here, is something that I can refer to all the different rows as within my interface for this table. So what I'm gonna call this is a ReminderRow. So that's gonna be the identifier for each of the rows found within the table. So then once I've done that I can go back into here, and that's what this width row type is asking for. What's the row type I'm looking for? The row type I'm looking for is going to be ReminderRow, just like that. Okay, so we'll go ahead and save that. So now, if I were to run my application, I would anticipate seeing five rows show up in my table of type ReminderRow. So let's go ahead and give that a shot. So let's stop debugging here if you already are, and then we'll go ahead and run this. And then once X code has had a moment to compile everything and make sure everything builds properly, it will bring up the simulators. And as you can see here, we have our Apple Watch simulator. It's going to pop up. And with a little bit of luck, we will see five rows show up within this table. So we see one, two, three, four, and then the fifth one hiding down below, so that's pretty good. And the reason that that all works is because we were able to define a subclass of our interface controller, get access to our actual RemindersTable. And then be able to say within that RemindersTable how many rows do I wanna add. So we've been able to do all of that, but the problem we're having right now is what about the actual reminders themselves? Okay, so let's take a moment to handle that. So what I wanna do now is I want to, I'm gonna fake this a little bit for simplicity's sake. But really, your rows or your reminders can be coming from anywhere. You could have them on your iPhone app. You could be retrieving them from a web service, from a database, whatever have you, but in this case I'm gonna keep things relatively simple and I'm just gonna hard code a couple. So what I'm gonna do is within this table interface controller, I'm simply going to create a list of reminders and that's what I'm gonna use to store all of these. We'll say Reminders and we'll initialize it that way. And then we'll also want to populate those, load up some sample data. But if you try to do this, you're gonna see that you're gonna get a little bit of a problem. So if I were to click on this little red exclamation point here, it's gonna say use of unresolved identifier reminders. And it's gonna say I don't know what that is, I don't have reminders. But even if I were to get rid of the the s, it doesn't know what reminder is either. But I created that, didn't I? This is one of those things you have to be very careful of, not only in WatchKit apps, but in iOS apps in general. So let's go ahead and fix this little bit of a problem. So if I open up the left-hand panel here, and I come into RemindMe, into my Models and take a look at the reminder.swift here. Now I do have this file, and it is in this folder, so why can't it see? Well, let's go back to our standard editor here. Let's open up the right-hand panel as well, and if you were to select this little page here, the file inspector, and come down to target membership. You're gonna see here that by default, you're only going to get target membership of the target that you created that file in its folder structure. So in RemindMe, because I created it in here, I get the RemindMe target membership. But the problem with that is, I need to get that target membership in my extension, so it's very simple to add it in. All I have to do is check this little check box right here next to WatchKit Extension, and I could save that. And I can already tell you that I'm probably gonna need to do the same thing with Stage, because I did the same thing. So if you're ever working on a file or trying to use a file, or a class, or a type, somewhere in your application that you know you created, but for some reason you can't get access to it. You should definitely check the Target Memberships, to see if that's accessible from where you're trying to get a hold of it. Okay, so once I've done that, I should be able to come back to my ReminderTableViewController where I didn't know what reminder was before it now does. Okay, so that's pretty good. So what I'd like to do now is I'd also like to load up some sample reminders or maybe just a sample reminder. So let's go ahead and come down to the bottom, and we'll just create a really quick private function. And we'll just call this load sample reminders, or something like that. So all I really wanna do, is I wanna put some together here. So let's go ahead and create a very simple reminder here. We'll say this is going to be, actually we'll do let reminder = Reminder now that we can see that. And we're gonna need to give this a name. And we'll just call this maybe the Morning Wakeup or something like that. And then let's add a couple of stages. So first we're create a stage and we're gonna have that be equal to a new Stage. And then within here we need to give it a name and the duration. So let's say in the first thing in the morning I wanna wake up and I wanna stretch. And let's say I wanna do that for maybe 20 seconds. Now obviously these are just simple values. You can obviously change these to be anything that you want, or make them more specific to your needs. And then the second one, maybe we'll say, let's do a light jog. Maybe around the neighborhood or around the house or something like that, depending on if you have kids. I don't know, maybe have that be for maybe 60 seconds or something like that. Just get the blood flowing, and that would be fine. So what we now have is a reminder and we have two stages, but now we need to combine those things. So let's go into Reminder, and let's go ahead and say stages and we want to append. Let's append Stage1 and we will also do stages.append, and we'll append stage2, just like that. Okay, so now we have created those. And then all we wanna do is go into our Reminders collection that we created up here above. And let's just go ahead and add this reminder to that list. Okay, so let's go ahead and save this. So now I have this sample collection of reminders, but I've got this hard-coded 5 here. So let's change this because that doesn't seem to make any sense anymore. I'm more interested in my reminders, and more than that, I'm more interested in my reminders.count. So let's go ahead and save that. So one more time we'll run our application. And we're once again gonna get our same problem here with our SecondsContainer. So let's come back in here to our SecondsContainer. Let's make sure this has WatchKit Extension access and as well as our SecondsContainerExtension. So let's go ahead and save all of those and then we will try to rerun our application. Let's see what we get this time. Looks like everything is looking a little bit better. Let's minimize the iPhone. Let's open up the Apple Watch. And we should get one row. And for some reason we did not. So let's go ahead and do a little bit of debugging. So we'll come down into our Reminders Controller here. And the reason that we didn't get anything is because we never called our function. So we'll load SampleReminders and go ahead and run that. And now this time, once everything comes up and starts running again, we should this time get a single row in our table. But you're gonna notice very quickly that the problem here is we're only getting the kind of design time information with the name and the duration. We're not actually getting the information that we want. And then in the next lesson, I'll show you how you can now start to get programmatic access to all of the rows within your table.