{"id":1072,"date":"2014-12-07T13:39:07","date_gmt":"2014-12-07T19:39:07","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=1072"},"modified":"2014-12-07T13:39:07","modified_gmt":"2014-12-07T19:39:07","slug":"a-look-at-apple-watchkit-tables","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/a-look-at-apple-watchkit-tables\/","title":{"rendered":"A Look at Apple WatchKit Tables"},"content":{"rendered":"<p>Today we&#8217;re going to show you how to use a <code>WKInterfaceTable<\/code> in your Apple Watch applications.  If you&#8217;ve been following or reading this blog for any period of time you will know that we&#8217;re passionate about home automation controls, and look forward to HomeKit in the market.  The Apple Watch interface will lend itself well to controlling home automation devices as it will eliminate things like digging your phone out of your pocket to unlock the door.  Bring up your Apple Watch, open your home automation app, and press Unlock.<\/p>\n<p>Let&#8217;s get started!  Head on over to Bitbucket and download the <a href=\"https:\/\/bitbucket.org\/joeiachievedit\/watchkittables\/get\/starter.zip\">starter app<\/a>.<br \/>\nOur starter app already has an Apple Watch target provided and supplementary images.  Open the <code>watchkittables.xcodeproj<\/code> project in Xcode 6.2 or higher (this is the first version with iOS 8.2 and WatchKit).<\/p>\n<p>Home automation control is all about controlling accessories, and what better way to quickly view all of your accessories than with a table?  WatchKit provides a table UI element with <code>WKInterfaceTable<\/code>.  We&#8217;re going to create a table with two <i>types<\/i> of rows. One row type will contain a lightbulb image and a button to toggle it on and off.  The other row type will contain a label and two buttons to increase and decrease the setpoint temperature on a thermostat.<\/p>\n<p>Bring up your Watch App <b>Interface.storyboard<\/b> and drag and drop a Table onto the watch canvas.  Note that the description for a <code>WKInterfaceTable<\/code> says &#8220;Displays one or more rows of data&#8221;.  After this step your watch interface should look like this:<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_basictablerow.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_basictablerow.png\" alt=\"table_tut_basictablerow\" width=\"559\" height=\"256\" class=\"alignnone size-full wp-image-1099\" \/><\/a><\/p>\n<p>We&#8217;re going to stop and make the distinction now between a table and a row in WatchKit.  In the screenshot above note that the <b>Interface Controller<\/b> contains a <b>Table<\/b>, and that <b>Table<\/b> contains a <b>Table Row Controller<\/b>.  The <b>Table<\/b> in WatchKit is the UI component which will manage the rows, and the <b>row controller<\/b> will manage the display of a type of row.  If you have one more than one type of row you will have more than one row controller.<\/p>\n<p>The table row controller implementation is in the <i>extension<\/i> (in this first iteration of WatchKit it should pointed out that implementation is always in the extension) and is a separate Swift class.  <\/p>\n<p>Now, we&#8217;ve established that we want two types of rows and we currently only have one, so click on the Attributes inspector for the <i>table<\/i> (not the row controller) and set the <b>Rows<\/b> value to 2:<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_initial.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_initial.png\" alt=\"table_tut_initial\" width=\"893\" height=\"311\" class=\"alignnone size-full wp-image-1082\" \/><\/a><\/p>\n<p>Notice that there are now two Table Row Controllers. Each table row controller is responsible for managing their type of row.<\/p>\n<p>We will have two row types:<\/p>\n<ul>\n<li>LightbulbAccessoryRow\n<li>ThermostatAccessoryRow\n<\/ul>\n<p>Click on the first Table Row Controller and in the Attributes inspector for Identifier type LightbulbAccessoryRow. Select the second Table Row Controller and for Identifier type ThermostatAccessoryRow.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_named_rows.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_named_rows.png\" alt=\"table_tut_named_rows\" width=\"363\" height=\"150\" class=\"alignnone size-full wp-image-1083\" \/><\/a><\/p>\n<p>Now let&#8217;s define the content of the LightbulbAccessoryRow.<\/p>\n<p>In <b>Interface.storyboard<\/b> click on the group inside the LightbulbAccessoryRow and drag-and-drop an image and button inside the group.<\/p>\n<p>Set the image size to 32&#215;32 and for the button set the size attributes to <b>Size to Fit Content<\/b>.<\/p>\n<p>Set the horizontal position of the button to Center.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_lightbulbaccessoryrow.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_lightbulbaccessoryrow.png\" alt=\"table_tut_lightbulbaccessoryrow\" width=\"592\" height=\"221\" class=\"alignnone size-full wp-image-1085\" \/><\/a><\/p>\n<p>We now need to create a Swift class for our table row. In the project navigator click on <b>watchkittables WatchKit Extension<\/b> and then go to <b>File &#8211; New &#8211; File<\/b> and choose an iOS Swift file. Name the file <b>LightbulbAccessoryRow<\/b> and ensure it is in the <b>watchkittables WatchKit Extensions<\/b> folder, group, and target.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_addlightbulbswift.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_addlightbulbswift.png\" alt=\"table_tut_addlightbulbswift\" width=\"461\" height=\"635\" class=\"alignnone size-full wp-image-1084\" \/><\/a><\/p>\n<p>The table row class must inherit from <code>NSObject<\/code> and you will want to add <code>import WatchKit<\/code> since this class will contain WatchKit objects:<\/p>\n<pre class=\"lang:swift decode:true\">\r\nimport Foundation\r\nimport WatchKit\r\n\r\nclass LightbulbAccessoryRow : NSObject {\r\n  \r\n  \r\n}\r\n<\/pre>\n<p>Now let&#8217;s wire our WatchKit UI elements to the row class. Click on <b>Interface.storyboard<\/b> in the Watch app and select the LightbulbAccessoryRow and then reveal the <b>Identity Inspector<\/b> and change the row class to <b>LightbulbAccessoryRow<\/b>.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_changeclass.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_changeclass.png\" alt=\"table_tut_changeclass\" width=\"1021\" height=\"309\" class=\"alignnone size-full wp-image-1087\" \/><\/a><\/p>\n<p>Now, select the image in our LightbulbAccessoryRow. Click on the Assistant editor button (the joined rings). If <code>InterfaceController.swift<\/code> appears, change it to <code>LightbulbAccessoryRow.swift<\/code>.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_linkimage.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_linkimage.png\" alt=\"table_tut_linkimage\" width=\"866\" height=\"260\" class=\"alignnone size-full wp-image-1088\" \/><\/a><\/p>\n<p>CTRL-click the image and drag and drop an <b>Outlet<\/b> into the <code>LightbulbAccessoryRow<\/code> class, naming the attribute <code>lightbulbImage<\/code>.<\/p>\n<p>Now add an outlet for the button (<code>lightbulbButton<\/code>) <i>and<\/i> an <b>Action<\/b> named <code>buttonTapped<\/code>).<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_lightbulbrowwired.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_lightbulbrowwired.png\" alt=\"table_tut_lightbulbrowwired\" width=\"789\" height=\"283\" class=\"alignnone size-full wp-image-1089\" \/><\/a><\/p>\n<p>Recall that when your Watch app is instituted the <code>init<\/code> method of your <code>InterfaceController<\/code> will be called. Here is where we will initialize our table, so create an outlet for your table in <code>InterfaceController<\/code>.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_addtableoutlet.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_addtableoutlet.png\" alt=\"table_tut_addtableoutlet\" width=\"1030\" height=\"273\" class=\"alignnone size-full wp-image-1090\" \/><\/a><\/p>\n<p>We&#8217;ve named our table <code>accessoryTable<\/code>.<\/p>\n<p>In the <code>init<\/code> method of <code>InterfaceController<\/code> add the following (after the call to the super initializer of course):<\/p>\n<pre class=\"lang:swift decode:true\">\r\n      let accessories = [\r\n        [\"type\":\"lightbulb\",\r\n          \"name\":\"Living Room\",\r\n         \"state\":\"off\"],\r\n        [\"type\":\"lightbulb\",\r\n         \"name\":\"Dining Room\",\r\n         \"state\":\"on\"],\r\n        [\"type\":\"thermostat\",\r\n         \"name\":\"Upstairs\",\r\n         \"mode\":\"cool\",\r\n         \"setpoint\":\"72\"],\r\n        [\"type\":\"thermostat\",\r\n         \"name\":\"Downstairs\",\r\n         \"mode\":\"cool\",\r\n         \"setpoint\":\"68\"]\r\n        ]\r\n<\/pre>\n<p>To simplify the tutorial we&#8217;ll use this predefined data to drive our table. In the real world this data will come from your iOS application. In our case, we would query the state of the HomeKit environment.<\/p>\n<p>To add rows for our lightbulbs we will use:<\/p>\n<pre class=\"lang:swift decode:true\">\r\n      let lightbulbs = accessories.filter{$0[\"type\"] == \"lightbulb\"}\r\n      self.accessoryTable.setNumberOfRows(lightbulbs.count, withRowType: \"LightbulbAccessoryRow\")\r\n<\/pre>\n<p>Let&#8217;s stop and explain these two lines. The first is straightforward (if you are familiar with the Array <code>filter<\/code> function that is); we are filtering our accessory <code>Array<\/code> for those accessories whose <code>type<\/code> key is set to <code>lightbulb<\/code>. The second line is where we tell our table to provide us with a set of number of <code>LightbulbAccessoryRow<\/code> rows. Note that the <code>rowType<\/code> is given as a <code>String<\/code>. This  is the identifier string you provided in the Attributes inspector for the row. The string given in the code and that given in the interface builder <i>must match<\/i>.<\/p>\n<p>Now that we&#8217;ve set the number of rows, let&#8217;s add them. This can be accomplished with:<\/p>\n<pre class=\"lang:swift decode:true\">\r\n      for var i = 0; i < lightbulbs.count; i++ {\r\n        \r\n        let row = self.accessoryTable.rowControllerAtIndex(i) as LightbulbAccessoryRow\r\n        \r\n        row.lightbulbImage.setImageNamed(lightbulbs[i][\"state\"])\r\n        if lightbulbs[i][\"state\"] == \"off\" {\r\n          row.lightbulbButton.setTitle(\"On\")\r\n        } else {\r\n          row.lightbulbButton.setTitle(\"Off\")\r\n        }\r\n        \r\n      }\r\n<\/pre>\n<p>You can run the application at this point and get a watch app that looks like this:<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_firstwatch.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_firstwatch.png\" alt=\"table_tut_firstwatch\" width=\"273\" height=\"365\" class=\"alignnone size-full wp-image-1117\" \/><\/a><\/p>\n<p>Now, we want to add an implementation for <code>buttonTapped<\/code>.  Unfortunately WatchKit does not provide for querying the attributes of elements on the watch display in your extension app. For example, we cannot say:<\/p>\n<pre class=\"lang:swift decode:true\">\r\nif lightbulbButton.title == \"Off\" {\r\n  lightbulbButton.setTitle(\"On\")\r\n}\r\n<\/pre>\n<p>One can assume Apple did this for a reason, and thats to minimize the amount of communication traffic between the Watch and iPhone.<\/p>\n<p>We'll have to add our own state variable. In the <code>LightbulbAccessoryRow<\/code> class add a boolean flag:<\/p>\n<pre class=\"lang:swift decode:true\">\r\nvar on:Bool = false\r\n<\/pre>\n<p>Then in the <code>buttonTapped<\/code> method of <code>LightbulbAccessoryRow<\/code> use the boolean flag to change the image and title depending on the value.  Make sure and toggle the bool value as well.<\/p>\n<pre class=\"lang:swift decode:true\">\r\n  @IBAction func buttonTapped() {\r\n    if self.on {\r\n      \/\/ Turn bulb off\r\n      self.lightbulbImage.setImageNamed(\"off\")\r\n      self.lightbulbButton.setTitle(\"Turn On\")\r\n      self.on = false\r\n    } else {\r\n      \/\/ Turn bulb on\r\n      self.lightbulbImage.setImageNamed(\"on\")\r\n      self.lightbulbButton.setTitle(\"Turn Off\")\r\n      self.on = true\r\n    }\r\n  }\r\n<\/pre>\n<p>Update the row initialization loop code in <code>InterfaceController<\/code> to make use of the property:<\/p>\n<pre class=\"lang:swift decode:true\">\r\n      for var i = 0; i < lightbulbs.count; i++ {\r\n        \r\n        let row = self.accessoryTable.rowControllerAtIndex(i) as LightbulbAccessoryRow\r\n        \r\n        row.lightbulbImage.setImageNamed(lightbulbs[i][\"state\"])\r\n        if lightbulbs[i][\"state\"] == \"off\" {\r\n          row.on = false\r\n          row.lightbulbButton.setTitle(\"Turn On\")\r\n        } else {\r\n          row.on = true\r\n          row.lightbulbButton.setTitle(\"Turn Off\")\r\n        }\r\n        \r\n      }\r\n<\/pre>\n<p>Run the Watch app in the Xcode simulator, and your app should run similar to that in this video:<br \/>\n[youtube]http:\/\/youtu.be\/3h3V2D4Q29g[\/youtube]<\/p>\n<p>I can hear the howls of protest regarding how we've implemented the state nature of our lightbulb!  For extra credit, <i>yes<\/i>, you can implement functions in the <code>LightbulbAccessoryRow<\/code> class for <code>setOn<\/code> and <code>setOff<\/code> which encapsulate all of the logic of setting images, strings, and flags.<\/p>\n<p>Now let's add our support for our <code>ThermostatAccessoryRow<\/code>.  Create a new Swift file <code>ThermostatAccessoryRow<\/code> and ensure that it is in the extension folder, group, and target.  We'll make the point once more:  your Swift file should include <code>import WatchKit<\/code> and your row class needs to inherit from <code>NSObject<\/code>:<\/p>\n<pre class=\"lang:swift decode:true\">\r\nimport Foundation\r\nimport WatchKit\r\n\r\nclass ThermostatAccessoryRow : NSObject {\r\n    \r\n}\r\n<\/pre>\n<p>Now go to the <b>Interface.storyboard<\/b> and click on the <b>ThermostatAccessoryRow<\/b> and in the <b>Identity Inspector<\/b> set the class to <code>ThermostatAccessoryRow<\/code>.  This should be old hat by now.<\/p>\n<p>To give our UI a little flair we'll add two groups to our existing default ThermostatAccessoryRow group.  The first group will contain our thermostat cooling setpoint temperature label, and the second will contain the up and down buttons for the setpoint.  While writing this tutorial I decided that verbally describing every setting in Interface Builder would be cumbersome, so you can see from this video how the layout for the ThermostatAccessoryRow is accomplished.<\/p>\n<p>[youtube]https:\/\/www.youtube.com\/watch?v=rX90egdWd_8[\/youtube]<\/p>\n<p>Briefly, the thermostat row has two groups:  the first group contains our labels and is layed out vertically.  Our second group contains the up and down buttons.  The buttons don't have any titles, but instead we've used the <code>cool_down<\/code> and <code>cool_up<\/code> images that were included in the <b>Images.xcassets<\/b> folder.  You can if you like, name the groups in Xcode for ease-of-use.  We've named ours <b>Setpoint Temperature<\/b> and <b>Setpoint Controls<\/b>, respectively.<\/p>\n<p>For the purposes of this tutorial if you don't get the exact table row layout right, it's okay.  You can even skip adding the \u00b0F label, it's only for effect.<\/p>\n<p>In case you missed it, we wired up an outlet (<code>setpointTemperatureLabel<\/code>) and two actions:  one for the down button (<code>setpointDown()<\/code>) and one for the up button (<code>setpointUp()<\/code>).  <\/p>\n<p><b>An aside:<\/b>  If you ever see the error <code>Could not insert new outlet connection:  Could not find any information for the class named <i>Classname<\/i><\/code>, this is Interface Builder's way of saying it hasn't processed (indexed, scanned, take your pick) the class file in question.  Why it hasn't done so could be any number of reasons, but I've found its often the case when I have something running in the simulator.  Stop any running simulations with the Xcode stop button and try again.  If all else fails quitting Xcode and reopening the project usually works.<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_cannotinsert.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_cannotinsert.png\" alt=\"table_tut_cannotinsert\" width=\"565\" height=\"212\" class=\"alignnone size-full wp-image-1106\" \/><\/a><\/p>\n<p>Our final <code>ThermostatRowController<\/code> UI should look something like:<\/p>\n<p><a href=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_thermostatrow.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/dev.iachieved.it\/iachievedit\/wp-content\/uploads\/2014\/12\/table_tut_thermostatrow.png\" alt=\"table_tut_thermostatrow\" width=\"1131\" height=\"320\" class=\"alignnone size-full wp-image-1108\" \/><\/a><\/p>\n<p>And, now our <code>ThermostatRowController<\/code> class will look like this<\/p>\n<pre class=\"lang:swift decode:true\">\r\nclass ThermostatAccessoryRow : NSObject {\r\n  \r\n  @IBOutlet weak var setpointTemperatureLabel: WKInterfaceLabel!\r\n\r\n  var setpoint = 72\r\n  \r\n  @IBAction func setpointDown() {\r\n    self.setpoint = self.setpoint - 1\r\n    self.setpointTemperatureLabel.setText(\"\\(self.setpoint)\")\r\n  }\r\n  \r\n  @IBAction func setpointUp() {\r\n    self.setpoint = self.setpoint + 1\r\n    self.setpointTemperatureLabel.setText(\"\\(self.setpoint)\")\r\n  }\r\n  \r\n}\r\n<\/pre>\n<p>The logic of the row controller is straightforward.  As with our lightbulb, we cannot query the label text dynamically so we add a <code>setpoint<\/code> property to our class.  When the user presses our <code>setpointDown<\/code> button we decrement the setpoint and then set the label accordingly.  Likewise, when our <code>setpointUp<\/code> button is tapped, we increment and set accordingly.<\/p>\n<h2>Multiple Row Types<\/h2>\n<p>Adding the second type of row controller introduces us to the <code>setRowTypes<\/code> function of <code>WKInterfaceTable<\/code>.  Whereas previously we used <code>setNumberOfRows<\/code> for a table containing one type of row, a table containing more than one row type requires us to use <code>setRowTypes<\/code>.<\/p>\n<p><code>setRowTypes<\/code> takes an array of <code>String<\/code>s, with each entry declaring what type of row controller should govern the row at the given array index.  Let that soak in.  If you want 5 rows, 3 of which are lightbulbs and 2 of which are thermostats you're going to create an array of 5 strings:<\/p>\n<pre class=\"lang:swift decode:true\">\r\nlet rowTypes = [\"LightbulbAccessoryRow\",\r\n \"LightbulbAccessoryRow\",\r\n \"LightbulbAccessoryRow\",\r\n \"ThermostatAccessoryRow\",\r\n \"ThermostatAccessoryRow\"]\r\n\r\nself.accessoryTable.setRowTypes(rowTypes)\r\n<\/pre>\n<p><b>Make sure<\/b> and spell your row type correctly!  Otherwise, you'll be treated with the incredibly irritating <code>Error - unable to instantiate row controller class (null) for row 0<\/code> error!<\/p>\n<p>We'll build our <code>rowType<\/code> array dynamically with the following:<\/p>\n<pre class=\"lang:swift decode:true\">\r\n      var rowTypes = [String]()\r\n      \r\n      for accessory in accessories {\r\n        var type = accessory[\"type\"]!\r\n        type = type.capitalizedString\r\n        rowTypes.append(\"\\(type)AccessoryRow\")\r\n      }\r\n<\/pre>\n<p>First, declare a new array of type <code>[String]<\/code> (that is, an array of <code>String<\/code>s).  Then, for each accessory, obtain the type and use it for building our row controller class name.  Append the name to our <code>rowTypes<\/code> array.<\/p>\n<p>Stop now and in the <code>InterfaceController<\/code> <code>init<\/code> function delete all of the previous table initialization code for the lightbulb and replace with the above.  Your function should look like this:<\/p>\n<pre class=\"lang:swift decode:true\">\r\n    override init(context: AnyObject?) {\r\n      super.init(context: context)\r\n      \r\n      let accessories = [\r\n        [\"type\":\"lightbulb\",\r\n          \"name\":\"Living Room\",\r\n          \"state\":\"off\"],\r\n        [\"type\":\"lightbulb\",\r\n          \"name\":\"Dining Room\",\r\n          \"state\":\"on\"],\r\n        [\"type\":\"thermostat\",\r\n          \"name\":\"Upstairs\",\r\n          \"mode\":\"cool\",\r\n          \"setpoint\":\"72\"],\r\n        [\"type\":\"thermostat\",\r\n          \"name\":\"Downstairs\",\r\n          \"mode\":\"cool\",\r\n          \"setpoint\":\"68\"]\r\n      ]\r\n      \r\n      var rowTypes = [String]()\r\n      \r\n      for accessory in accessories {\r\n        var type = accessory[\"type\"]!\r\n        type = type.capitalizedString\r\n        rowTypes.append(\"\\(type)AccessoryRow\")\r\n      } \r\n\r\n    }\r\n<\/pre>\n<p>Our logic for populating each row in the table is as follows:<\/p>\n<pre class=\"lang:swift decode:true\">\r\n      self.accessoryTable.setRowTypes(rowTypes)\r\n      \r\n      for var i = 0; i < accessories.count; i++ {\r\n        if accessories[i][\"type\"] == \"lightbulb\" {\r\n          let row = self.accessoryTable.rowControllerAtIndex(i) as LightbulbAccessoryRow\r\n          \r\n          row.lightbulbImage.setImageNamed(accessories[i][\"state\"])\r\n          if accessories[i][\"state\"] == \"off\" {\r\n            row.on = false\r\n            row.lightbulbButton.setTitle(\"Turn On\")\r\n          } else {\r\n            row.on = true\r\n            row.lightbulbButton.setTitle(\"Turn Off\")\r\n          }\r\n          \r\n        } else if accessories[i][\"type\"] == \"thermostat\" {\r\n          let row = self.accessoryTable.rowControllerAtIndex(i) as ThermostatAccessoryRow\r\n          let t = accessories[i][\"setpoint\"]\r\n          \r\n          row.setpointTemperatureLabel.setText(t)\r\n          row.setpoint = t!.toInt()!\r\n        }\r\n      }\r\n\r\n<\/pre>\n<p>There are many ways to improve upon this code, and it's not meant to necessarily be an example of elegant and DRY techniques.  For our training purposes it will suffice.<\/p>\n<p>Run the example again and you should have something very similar to that in our video:<\/p>\n<p>[youtube]https:\/\/www.youtube.com\/watch?v=HxJjhs3dSiQ[\/youtube]<\/p>\n<h2>Getting the Code<\/h2>\n<p>To get the starter application download it directly from <a href=\"https:\/\/bitbucket.org\/joeiachievedit\/watchkittables\/get\/starter.zip\">Bitbucket<\/a>.  Or, check out the <a href=\"https:\/\/bitbucket.org\/joeiachievedit\/watchkittables\/src?at=master\">master branch<\/a> at Bitbucket for the completed application.<\/p>\n<h2>Final Thoughts<\/h2>\n<p>If you're a long time Cocoa and UIKit developer you'll notice that the table programming paradigm is quite different.  With OS X and iOS tables you create table controllers, table data sources, and stick with a \"the table will ask you for data\" MVC model.  Apple Watch table control is (depending upon your point of view) much simpler with a direct \"set this row to this data\" approach.  When you take a look at the WatchKit environment this again makes more sense if it is put in the light of how much communication needs to occur between the watch and phone.  With the current <code>WKInterfaceTable<\/code> method the watch does not need to constantly ask the phone for row data.  It remains to be seen if this will change as application logic moves to the watch in future iterations.<\/p>\n<h2>Follow us!<\/h2>\n<p>If you've liked our tutorial and are interested in keeping up with our posts, follow us on Twitter at @iachievedit!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re going to show you how to use a WKInterfaceTable in your Apple Watch applications. If you&#8217;ve been following or reading this blog for any period of time you will know that we&#8217;re passionate about home automation controls, and look forward to HomeKit in the market. The Apple Watch interface will lend itself well [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16],"tags":[],"class_list":["post-1072","post","type-post","status-publish","format-standard","hentry","category-apple-watch"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1072"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=1072"}],"version-history":[{"count":33,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1072\/revisions"}],"predecessor-version":[{"id":1121,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/1072\/revisions\/1121"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=1072"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=1072"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=1072"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}