Linking Content to the UI with Row Controllers

Looking at the interface object hierarchy in the storyboard’s Run Log interface controller (if you don’t see it, select Editor Show Document Outline), you can see that your labels are nested inside a parent group, but that instead of the group being a child of the table (which would match how it appears in the interface editor), there’s an intermediate object that looks different, called Table Row Controller. This is the row controller we’ve been talking about, and it’s vital to understanding how tables work in WatchKit.

Row controllers are lightweight objects that sit between tables and row content. Their entire role is to ferry data from your interface controller to the interface objects you’ve set up in the storyboard. Your row controller is going to be incredibly simple, let’s create it now and walk through what it needs to do.

You’ll need a new class for the row controller, and since you’ll be referencing it from the storyboard, it’ll need to inherit from NSObject—storyboards use a lot of internal NSObject magic. Name the class RunLogRowController. Create a new Swift file called RunLogRowController.swift using the WatchKit Class template to create the class.

Next, let’s set up outlets for your UI elements. You’ll make one for each label (there’s no need to reference their containing groups for now), and name them the same as they’re named in the storyboard:

 @IBOutlet​ ​weak​ ​var​ dateLabel: ​WKInterfaceLabel​!
 @IBOutlet​ ​weak​ ​var​ distanceLabel: ​WKInterfaceLabel​!
 @IBOutlet​ ​weak​ ​var​ durationLabel: ​WKInterfaceLabel​!

With that set up, you need to connect these outlets to your UI so that you can reference the interface objects in code. Head back to the storyboard and select the row controller object in the Run Log interface controller’s Document Outline. In Xcode’s Identity Inspector, change its class to RunLogRowController. In the Attributes Inspector, set its Identifier to RunRow. If you fail to do this, the table won’t be able to create the row, because it uses this identifier to, well, identify it. Now you can link it up with its outlets. For each label, Control-drag from the row controller in the Document Outline to the label, selecting the appropriate outlet.

Your UI is all hooked up and you need to put the appropriate data in it. To keep the row controller class separate from your model objects, the row controller will deal only with values: distance, duration, and date. Add a new method, configure(date:distance:duration:), and it will take care of the UI for you:

 var​ dateFormatter: ​NSDateFormatter​?
 var​ distanceFormatter: ​NSLengthFormatter​?
 var​ durationFormatter: ​NSDateComponentsFormatter​?
 
 func​ configure(date date: ​NSDate​, distance: ​Double​, duration: ​NSTimeInterval​) {
  dateLabel.setText(dateFormatter?.stringFromDate(date))
  distanceLabel.setText(distanceFormatter?.stringFromMeters(distance))
  durationLabel.setText(durationFormatter?.stringFromTimeInterval(duration))
 }

When a new RunLogRowController is created, the dateFormatter, distanceFormatter, and durationFormatter properties are all nil. These are all NSFormatter subclasses to help you convert numbers to strings, but instead of creating them in this class, you’ll fill them in later—that way you can reuse your NSDateFormatter.

Joe asks:
Joe asks:
Why Do We Need to Reuse Date Formatters?

Creating a date formatter, according to Apple’s Data Formatting Guide, “is not a cheap operation.”[7] If we were to create a new date formatter for every row in the table, we’d be sitting here for a long time waiting for a table of any reasonable length to display. Speed is the name of the game with tables (see Performance Concerns,, for more), so we want our code to be as efficient as possible.

Perfect. Whenever you call configure(date:distance:duration:), you’ll automatically put the data into your UI. That raises the next question: when does that happen? Let’s look at the other side of this and get some data into your table.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.217.139