WatchKit and Threading

While working on some of the chapters for the upcomming WatchKit by Tutorials book, I assumed since WatchKit extensions bascially run as a Remote Procedure Call (RPC), writing asynchronous code wouldn't work. This was a bummer because running dynamic applications on Apple Watch would be very slow.

But I hadn't actually tried it.

At Facebook we have a saying that "Code Wins Arguments", so I decided to prove that something horribly, horribly wrong would happen when you wrote async code in WatchKit.

I wrote a really simple app to test a couple of things:

Experiment Storyboard Setup

Inside initWithContext: I download an image and set the contents of the WKInterfaceImage. I also set the contents of the label above the image with text that will wrap, just to push the watch layout system.

[self.label setText:@"Loaded at initWithContext:"];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  NSURL *url = [NSURL URLWithString:@"http://placehold.it/120x100"];
  NSData *data = [NSData dataWithContentsOfURL:url];
  UIImage *placeholder = [UIImage imageWithData:data];

  dispatch_async(dispatch_get_main_queue(), ^{
    [self.image setImage:placeholder];
  });
});

To my surprise, the image downloaded, set the WKInterfaceImage contents, resized based on the image width and height, and pushed the label below the image down!

This worked?

Granted, this is on a simulator so we will have to see what happens when running on a real device and how the Bluetooth connection handles these async callbacks, but this is a great sign!

If you want to play with this project you can check it out on Github.

Sidenote: Yes I'm using Objective-C. Swift introspection sucks and doesn't work at all with Facebook's Chisel LLDB extensions.