Brian Gilham

Engineering leader, husband, and father

medium

The Key

People always ask me about my tattoo — an ornamental key covering the underside of my right forearm. They joke that it’s a key to the city. Or they ask if my wife has a tattoo of a lock. Or the dreaded question, “What does your tattoo mean?” I usually deflect. It doesn’t mean anything. I just liked the way it looked. It’s just a key. But it isn’t.

People always ask me about my tattoo — an ornamental key covering the underside of my right forearm. They joke that it’s a key to the city. Or they ask if my wife has a tattoo of a lock. Or the dreaded question, “What does your tattoo mean?” I usually deflect.

It doesn’t mean anything. I just liked the way it looked. It’s just a key.

But it isn’t. It’s a tribute to my Dad.

The memory is fuzzy. But I remember him having this old, ornamental key. The kind of key you see in movies, with two prongs sticking out the end of it and huge loops at the top. It looked like it belonged in a castle. It didn’t look anything like the one on my arm.

I haven’t seen it in decades. I could ask my parents about it but I’m afraid seeing it would ruin the memory. For all I know it was some trinket he found lying around. A good luck charm made of plastic. Maybe it never existed — a trick of the brain.

Even if that’s true, it doesn’t matter. It’s one of the few objects I associate with my Dad, right up there with the wooden duck on his dresser and the rubber Hamburgalar toy he kept in his briefcase — a gift from my brother and I. My tattoo is a way of putting a small piece of my family on my body forever.

There will be more tattoos. I’ve already begun thinking of a tribute to my Mom. Or one for my brother. Or my wife.

I don’t think I’ll ever sport someone’s name, but I love the idea of decorating my body with my life story — the people, places, and events that have shaped me.

I’ve never told my Dad about the meaning behind my tattoo. He would be uncomfortable, I’m sure. But I’ll always know. And I’ll always have a small part of him with me.


Accessibility in WatchKit

Many developers aren’t aware of the accessibility options on the Apple Watch. In this quick talk, presented at this month’s tacow meetup, I talked about why accessibility is important and give a brief overview of VoiceOver, Dynamic Text, Grayscale, and Reduce Transparency/Motion. A few people asked about my slides, so I thought I’d share.

Many developers aren’t aware of the accessibility options on the Apple Watch. In this quick talk, presented at this month’s tacow meetup, I talked about why accessibility is important and give a brief overview of VoiceOver, Dynamic Text, Grayscale, and Reduce Transparency/Motion.

A few people asked about my slides, so I thought I’d share.


Adventures of a First Time Winter Cyclist

(Originally published on November 17, 2014) I’ve recently begun enjoying cycling as my full-time mode of transportation around the city. As temperatures began to drop, my mind naturally turned to winter riding. Can my bike handle it? Should I get new tires? What if I bail hard? After consulting numerous articles and blog posts, I decided to stick it out and figure it out as I go. This morning, Toronto saw its first “real” snowfall.

(Originally published on November 17, 2014)

I’ve recently begun enjoying cycling as my full-time mode of transportation around the city. As temperatures began to drop, my mind naturally turned to winter riding. Can my bike handle it? Should I get new tires? What if I bail hard? After consulting numerous articles and blog posts, I decided to stick it out and figure it out as I go.

This morning, Toronto saw its first “real” snowfall. It wasn’t much, but it was enough to cause 41 crashes per hour. Looking outside, I honestly wasn’t sure if I would stick to the plan or not. But, after much internal debate, I decided to go for it.

It was great. Wearing my new cold-weather getup I was nice and toasty warm. I had already given it a trial run last last week, but today was the first real test. I kept my riding slow and steady and everything went great. It added about 15 minutes to my usual morning commute time.

I’m going to try and blog about my experiences as a first-time winter cyclist from time to time. It should be a hell of a ride.

Cold-weather setup: warm base layer with hood, water-resistant outer layer, thick construction gloves, ski goggles, boots, and of course my helmet. The gear will change as the temperatures drop and I’m forced to re-evaluate. I’ll try to post reviews of any gear I pick up.


How to Disable App Transport Security

(Originally published at FiveMinuteWatchKit.com) 06/11/15: Steven Peterson has posted an update, showing how to explicitly define per-domain exceptions to ATS. The method described below should only be used as a last resort. If you eagerly fired up iOS 9 and watchOS 2 yesterday you may have noticed something strange, at least if your app relies on NSURLSession. In iOS 9, Apple is introducing App Transport Security. ATS enforces best practices during network calls, including the use of HTTPS.

(Originally published at FiveMinuteWatchKit.com)

06/11/15: Steven Peterson has posted an update, showing how to explicitly define per-domain exceptions to ATS. The method described below should only be used as a last resort.

If you eagerly fired up iOS 9 and watchOS 2 yesterday you may have noticed something strange, at least if your app relies on NSURLSession.

In iOS 9, Apple is introducing App Transport Security. ATS enforces best practices during network calls, including the use of HTTPS.

From the docs:

ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt. You should adopt ATS as soon as possible, regardless of whether you’re creating a new app or updating an existing one. If you’re developing a new app, you should use HTTPS exclusively. If you have an existing app, you should use HTTPS as much as you can right now, and create a plan for migrating the rest of your app as soon as possible.

If, however, your app relies on a non-HTTPS API outside of your control, this is problematic.

While the documentation also mentions:

App Transport Security (ATS) lets an app add a declaration to its Info.plist file that specifies the domains with which it needs secure communication.

It currently fails to describe the Info.plist keys needed to specify exceptions to ATS.

After a lot of searching last night, Steven Peterson found one solution: disabling ATS entirely. Simply include the following in your Info.plist file:

Obviously this is not ideal.

He also turned up two other keys: NSExceptionDomains and NSIncludesSubdomains. However, neither one of us has been able to figure out how to successfully use them.

With any luck the documentation will be updated in short order and we can update our apps to use ATS properly. Until then, Steven’s solution does just the trick.


Improve the Accessibility of Images in Your WatchKit App

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) While browsing through the WatchKit Framework Reference recently, I noticed an interesting class: WKAccessibilityImageRegion. Intrigued — and unable to find anyone else who had tried it out — I put together a quick example. Essentially, WKAccessibilityImageRegion allows you to add accessibility labels to specific parts of an image. Let’s say you have a photo of a group of people. By default, WatchKit allows setting the usual accessibility properties for the image as whole: label, hint, value, and traits.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

While browsing through the WatchKit Framework Reference recently, I noticed an interesting class: WKAccessibilityImageRegion. Intrigued — and unable to find anyone else who had tried it out — I put together a quick example.

Essentially, WKAccessibilityImageRegion allows you to add accessibility labels to specific parts of an image. Let’s say you have a photo of a group of people.

Tim Cook, Jony Ive, Dave Grohl, and Nathan Mendel

By default, WatchKit allows setting the usual accessibility properties for the image as whole: label, hint, value, and traits. By employing WKAccessibilityImageRegion, however, we can call out each person individually.

Let’s define an area around Tim Cook’s face. We simply create a new WKAccessibilityImageRegion object, set the frame and label, and add it to the group using setAccessibilityImageRegions:.

(Note: In this example, I’ve set the above photo as a background image on a group. While the documentation claims otherwise, I’ve been unable to get this working with a standalone WKInterfaceImage)

Voila! With one simple change, Voiceover not only calls out the image as a whole, but identifies Tim Cook within it.

Please excuse my hairy arm.

Whether you are working with static images, or generating images dynamically, WKAccessibilityImageRegion offers a simple way to improve the accessibility of the images in your WatchKit app.


Quick WKInterfaceImage Tips

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) Now that users everywhere are firing up their brand-new Apple Watch, I’ve been extremely busy working on updating a few apps. But I wanted to take a moment and share two quick image-related tips with you. Rounded Corners I see one question being asked on Stack Overflow again and again. How the heck do I round the corners on a WKInterfaceImage?

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

Now that users everywhere are firing up their brand-new Apple Watch, I’ve been extremely busy working on updating a few apps. But I wanted to take a moment and share two quick image-related tips with you.

Rounded Corners

I see one question being asked on Stack Overflow again and again. How the heck do I round the corners on a WKInterfaceImage? It’s easy. Like many UI tricks in WatchKit, the secret is WKInterfaceGroup.

Simply nest your image inside a group sized to fit its content and set the cornerRadius on the group as desired. The group will clip your image, giving you the appearance of rounded corners on the image itself.

Why nest a WKInterfaceImage inside the group, instead of setting the group’s backgroundImage? That leads me to my second tip.

Image Placeholders

In many apps, developers opt to lazy-load their images. From a performance standpoint, this is a wise choice. Many apps, however, simply show a large gap in the content until the image loads. This can be confusing to users. At best, they guess something might load there eventually. At worst, your layout appears broken.

The solution, then, is to display some sort of placeholder for the image. In many of the apps I’ve worked on we accomplish this by nesting a WKInterfaceImage inside a WKInterfaceGroup and using the group’s backgroundImage to display a placeholder graphic or animation. Once the image inside the group is set, it completely covers the background image.

It’s an extremely simple technique, but it’s proven to be a huge help for users.


Submitting Your WatchKit App

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) Now that submissions are open for WatchKit extensions, many developers are running into issues and bugs that didn’t present themselves when working in the simulator. This post is an attempt to aggregate tips and solutions to common problems. Of course, be sure to check out Apple’s official guidelines. Many of these tips are gleaned from posts in the dev forums and my own experience submitting a WatchKit app.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

Now that submissions are open for WatchKit extensions, many developers are running into issues and bugs that didn’t present themselves when working in the simulator. This post is an attempt to aggregate tips and solutions to common problems. Of course, be sure to check out Apple’s official guidelines.

Many of these tips are gleaned from posts in the dev forums and my own experience submitting a WatchKit app. I’ll update the list as time goes on. Have something to add? Give me a shout.

iTunes Connect

  • The section for uploading your Apple Watch screenshots and app icon will only appear once you have uploaded your first WatchKit build.

Screenshots

  • Ensure your screenshots are 312x390px.
  • Screenshots should depict only your app’s interface — and use the entire space to do so.
  • Do not frame your screenshots in an Apple Watch “frame” or image.
  • Do not refer to your Apple Watch app in your iPhone app screenshots.
  • Do not add additional text/promo material to your Watch screenshots.
  • Despite the earlier requirement for screenshots to be taken only on device, you can now submit screenshots from the simulator. To do so, simply hit ⌘ + S or File > Save Screen Shot. The resulting images will be saved to your desktop, by default. Thanks to reader Jeff Rames for prompting this tip.

App Icons

  • Ensure your app icon does not include an alpha channel. This will result in an automatic rejection during validation and produces a cryptic error message for some.
  • If you encounter the error file names must match pattern “*@x.png”, ensure your Watch app icon is contained in an asset catalog included with the Watch app target. You cannot share an asset catalog between your iPhone app and your Watch app.
  • Make sure your icon does not contain a black background. This will cause it to blend into the background on the phone and has been a source of rejections for some.

Deployment Targets

  • While your iPhone app may support versions of iOS lower than 8.2, your WatchKit extension’s deployment target must be 8.2 or higher.
  • If you employ a framework in your WatchKit extension, your iPhone app’s deployment target must be 8.0 or higher. This is due to your WatchKit extension being bundled with your host app.

Build Process

  • If your build process happens outside of Xcode, or you have a custom build script, be sure your final zipped IPA follows the conventions described in this dev forums post.

Version & Build Numbers, Bundle Identifiers

  • Ensure the build and version number for your iPhone app, WatchKit extension, and Watch app are exactly the same.
  • Your WatchKit extension’s bundle identifier should use the bundle identifier for your iPhone app as a prefix. For example: if your iPhone app’s bundle identifier is com.company.AppName, your WatchKit extension’s bundle identifier should be something along the lines of com.company.AppName.watchkitextension.
  • David Olesch, iOS Lead at Jackrabbit Mobile, adds: “also make sure your app target and watch app target have the same display name. I got rejected because I forgot the other.”
  • An Tran adds: Ensure your WatchKit app does not include “WatchKit” or “Apple Watch” in the name.

Provisioning

  • Remember that your WatchKit extension requires its own app ID and provisioning profile.
  • From the ever-awesome Nick Arnott: If your WatchKit app fails to code sign with Xcode 6.3, you now need a profile for the WatchKit app in addition to the WatchKit extension.

App Store Description

  • If you reference the Apple Watch in your App Store description, be sure to follow Apple’s guidelines for capitalization and such. A few developers have faced rejections due to not following the guidelines.
  • As a quick reference, Apple Watch should always be written in English with an uppercase A and an uppercase W. It should not be UPPERCASE, lowercase, or use the Apple logo in place of the word “Apple”.

Performance

  • Ensure, as much as possible, that your app feels responsive in the simulator. If it feels at all sluggish in the simulator, it will be doubly so on device. At least one developer has been rejected for this.
  • If you are making use of openParentApplication:reply: I strongly suggest you follow the advice given in this post. In my testing with an actual Watch, openParentApplication:reply: was extremely unreliable without using the tips in that post. Another Watch labs participant has confirmed that to be the case for them as well. At least one developer has had their app rejected due to openParentApplication:reply: calls being killed on device before completion.

Swift

  • If you use Swift in your iPhone app, be sure to set the “Embedded Content Contains Swift” build setting to NO for your frameworks and extensions and YES for your iPhone app target.

App

  • Duplicating the functionality of a clock face, or displaying the time in a way that could be confused with one, will result in a rejection. Judging by the posts in the developer forums, this rule was supposed to appear in the HIG but was missed. It will be added soon.
  • Looking at this post in the dev forums, it appears your Watch app cannot exceed 50mb in size.

How to use Handoff in your WatchKit app

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) Considered by many to be an optional feature in their iOS/OSX apps, I believe Handoff will play an integral role in our WatchKit apps. Need the user to sign in before they can use your Watch app? Handoff. Want to present content a big too long for the Watch? Handoff. Need specific OS-level permissions for your Watch app? Asking the user to Handoff to this phone and pop open an interface specifically asking for/setting those permissions up.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

Considered by many to be an optional feature in their iOS/OSX apps, I believe Handoff will play an integral role in our WatchKit apps.

Need the user to sign in before they can use your Watch app? Handoff. Want to present content a big too long for the Watch? Handoff. Need specific OS-level permissions for your Watch app? Asking the user to Handoff to this phone and pop open an interface specifically asking for/setting those permissions up. When I see developers complain about WatchKit’s limitations, 99% of the time I think their problems could be easily solved by handing off to the iPhone and presenting custom UI.

Let’s take a look at how to implement it.

Give me your hand

To broadcast your app’s current activity, simply call updateUserActivity:userInfo:webpageURL: any time during the execution of your WKInterfaceController’s code. You should not create an NSUserActivityobject, as you would on iOS or OSX.

The updateUserActivity parameter requires an NSString describing the type of activity you’d like to broadcast in reverse-DNS format, by convention. It cannot be nil or an empty string.

userInfo expects an NSDictionary, as you might expect. This is where you can send along any data or state information the iPhone might need to pick up what the user is doing on the Watch. The contents of userInfo must be one of the following types: NSArray, NSData, NSDate, NSDictionary, NSNull, NSNumber, NSSet, or NSString.

Finally, you can optionally specify webpageURL to let the receiving iPhone continue your activity in Safari. Any URL scheme other than http or https throws an exception.

Invalidation

An activity will be broadcasted until the OS decides to kill it, you call updateUserActivity:userInfo:webpageURL: with a new activity, or call invalidateUserActivity to manually invalidate it.

Glances & Notifications

It isn’t obvious as first, but you can also call updateUserActivity:userInfo:webpageURL: from your Glance and custom notification interfaces. If you specify an activity that is recognized by the phone, it will allow the user to continue it there. But you can also “continue” the activity in your WatchKit app.

When your app is launched from a Glance or custom notification interface, any activity broadcasted from those interfaces will be passed to your root interface controller in the handleUserActivity: method.

If your app uses a page-based interface, handleUserActivity: will be called for each controller that is part of the initial interface. You don’t need to register the activity type in your WatchKit app for this to work. When overriding this method, don’t call super.

Simulator

As usual, the iOS simulator does not support testing Handoff. Unless you have received an invite to one of the developer labs and can test on actual hardware, you’ll have to hope for the best or wait for the Watch to be released.


How to get text input from the user

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) One of the most interesting features of WatchKit — collecting text input through dictation — is also one of the least talked about. Let’s get started. Talk to me Dictation is handled using a standard modal, presented by calling presentTextInputControllerWithSuggestions:allowedInputMode:completion:on your currently-active WKInterfaceController. The controller runs asynchronously, waiting for the user to tap “Done” and confirm their input. Once that happens, the provided completion block is executed on the main thread and you can use the supplied results however you like.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

One of the most interesting features of WatchKit — collecting text input through dictation — is also one of the least talked about. Let’s get started.

Talk to me

Dictation is handled using a standard modal, presented by calling presentTextInputControllerWithSuggestions:allowedInputMode:completion:on your currently-active WKInterfaceController.

The controller runs asynchronously, waiting for the user to tap “Done” and confirm their input. Once that happens, the provided completion block is executed on the main thread and you can use the supplied results however you like.

You should always call presentTextInputControllerWithSuggestions:allowedInputMode:completion: on your WatchKit extension’s main thread.

Suggestions

When presenting the dictation controller, you can optionally provide an array of NSString objects representing suggested input for the user. In a messaging app, for example, you might want to suggest generic responses a user could send to their friend.

Input Modes

You have to choose which of the three WKTextInputMode options you would like to present to the user.

  • WKTextInputModePlain: Dictation/suggested text only. No emoji. The emoji button will be hidden.
  • WKTextInputModeAllowEmoji: Dictation, suggested text, and non-animated emoji.
  • WKTextInputModeAllowAnimatedEmoji: Dictation, suggested text, and both animated and non-animated emoji.

If you skip providing suggestions and set the input mode to WKTextInputModePlain, the user will be sent directly to the dictation interface.

Completion

The completion block is passed an NSArray containing the input from the user. If the modal is dismissed before any input is given, this array will be nil. You can usually expect the array to contain a single NSString object representing the text input.

However, it can also contain an NSData object representing an emoji image if you’ve allowed the user to provide one. You can use that NSData object to create a UIImage, or use it directly in a WKInterfaceImage.

Since the text input interface is presented modally, the presenting WKInterfaceController will be re-activated before the completion block is called.

Simulator

It’s worth mentioning a few things when it comes to testing dictation in the simulator:

  • While you can specify any input mode you like, the simulator only supports providing text input using a suggested string. You can’t speak into your computer’s mic and have it converted to text. Similarly, the simulator does not support selecting either type of emoji.
  • The dictation screen will appear blank. It’s important to know that dictation will begin immediately when used on an actual Watch. The user will have to tap a “Done” button to confirm the dictated text before it is passed back to your app.

How to debug an iOS app while the associated WatchKit app is running

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) Since the introduction of openParentApplication:reply: I’ve seen developers struggle to debug their iOS app while running a WatchKit app in the simulator. If you haven’t worked with extensions before, the solution may not be obvious. Here’s how to pull it off: Build & run your iOS app in the simulator. Wait for it to finish launching, then hit the stop button in Xcode.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

Since the introduction of openParentApplication:reply: I’ve seen developers struggle to debug their iOS app while running a WatchKit app in the simulator. If you haven’t worked with extensions before, the solution may not be obvious. Here’s how to pull it off:

  1. Build & run your iOS app in the simulator.
  2. Wait for it to finish launching, then hit the stop button in Xcode.
  3. Switch your active target to your WatchKit app, build, and run it.
  4. When the Watch app has finished launching, tap your iOS app’s icon in the main simulator window.
  5. In Xcode’s menu bar select Debug > Attach to Process.
  6. Select your iOS app from the list. Chances are you’ll find it under Likely Targets.

If you take a look in the Debug Navigator (⌘ + 6), you’ll notice the debugger is now attached to both your iOS app and the WatchKit extension. You can click on each target in the navigator window to select which console output you’d like to view. If Xcode encounters a breakpoint it will automatically switch to the correct target.

Keep in mind that you’ll have to repeat this process each time you re-run your WatchKit app.


One weird trick to “fix” openParentApplication:reply:

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) A quick perusal of the Apple Developer Forums shows more than a few developers have experienced strange bugs when calling openParentApplication:reply: in a WKInterfaceController. Most often, it seems, when making multiple requests in quick succession. In an app I worked on recently we were hitting all sorts of strange behaviour. Sometimes openParentApplication:reply: would mysteriously be called twice. Every once in a while the reply block would fail to ever be called — despite being certain the delegate was functioning correctly and completing work in a background task.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

A quick perusal of the Apple Developer Forums shows more than a few developers have experienced strange bugs when calling openParentApplication:reply: in a WKInterfaceController. Most often, it seems, when making multiple requests in quick succession.

In an app I worked on recently we were hitting all sorts of strange behaviour. Sometimes openParentApplication:reply: would mysteriously be called twice. Every once in a while the reply block would fail to ever be called — despite being certain the delegate was functioning correctly and completing work in a background task.

Frustrating, to say the least.

However, I’ve discovered a solution that has made communication with the iPhone rock-solid. Essentially you have to begin — and end, after two seconds — an empty background task right at the beginning of the delegate method. It should be the absolute first thing you do. Afterward, kick off a background task for the real work.

Here’s an example:

The theory is the bogus background task prevents the OS from killing your app immediately. I honestly couldn’t tell you for sure.

All I know is it’s made openParentApplication:reply: far more reliable.


How to round the corners of a WKInterfaceImage

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) The Human Interface Guidelines recommend using black as the background colour across your entire app. Why? It allows the background to blend in with the bezel surrounding the display, giving the illusion there isn’t a bezel at all. In my experience, rounding the corners of your full-width images can help this illusion. A quick look at the WKInterfaceImage class reference, however, might make you think this isn’t possible.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

The Human Interface Guidelines recommend using black as the background colour across your entire app. Why? It allows the background to blend in with the bezel surrounding the display, giving the illusion there isn’t a bezel at all.

In my experience, rounding the corners of your full-width images can help this illusion. A quick look at the WKInterfaceImage class reference, however, might make you think this isn’t possible. Where’s the setCornerRadius: property?

It isn’t possible. Not directly, anyway.

Poking around, you’ll notice that WKInterfaceGroup does have a setCornerRadius: method. Place your WKInterfaceImage inside a group, set the corner radius, and you’ll notice it clips the corners of your image beautifully.


How to Display an Image Using WKInterfaceImage

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2) If you take a look at the class documentation for WKInterfaceImage, you’ll notice there are three different methods for displaying an image. For many developers new to WatchKit this has proven to be a bit confusing. When should you use one over the other? Where are the images coming from? Here’s a quick guide. setImage: This method sends a UIImage — or multiple, if you’re creating an animation — from your WatchKit extension to your WatchKit app.

(Originally published at FiveMinuteWatchKit.com, before the release of watchOS 2)

If you take a look at the class documentation for WKInterfaceImage, you’ll notice there are three different methods for displaying an image. For many developers new to WatchKit this has proven to be a bit confusing. When should you use one over the other? Where are the images coming from? Here’s a quick guide.

setImage:

This method sends a UIImage — or multiple, if you’re creating an animation — from your WatchKit extension to your WatchKit app.

setImageData:

This method sends an NSData object containing one or more images from your WatchKit extension to your WatchKit app. This saves the overhead of creating a UIImage if you are trying to set an image with data loaded directly from a file or downloaded from the Internet.

If you have to send an image from the phone to the Watch, this is the most efficient way to do so.

setImageNamed:

This method displays an image that has already been stored in the WatchKit app’s bundle, or cached on the device. If you are trying to displaying an image from the bundle, be sure to specify the full name and the file extension.

Caching

If you are displaying an image using setImage: or setImageData: that you’ll show more than once, cache it using the addCachedImage:name: method on WKInterfaceDevice. Afterward, you can use the specified cache name when calling setImageNamed:.

Make sure to clear images out of the cache as needed — you get 20mb of storage and it isn’t pruned automatically. To remove an image from the cache, you can use the WKInterfaceDevice method removeCachedImageWithName:. To clear all cached images use removeAllCachedImages.

Storyboards

One thing to keep in mind: while Interface Builder will allow you to specify an image from anywhere in your project, it will only be displayed if it is included in your Watch app bundle.


No USB-C to USB-A Cable? No Problem!

I knew ahead of time that the 2nd-round Dev Kits wouldn’t include a USB-C to USB-A cable, as the first batch had. I ordered one but have yet to receive it. Frustrated with not being able to deploy to my Apple TV — or even find the UDID so I could produce a TestFlight build — I decided to take matters into my own hands. One USB-C to Female USB-A adapter, some soldering, and a bunch of duct tape later, I had my solution.

I knew ahead of time that the 2nd-round Dev Kits wouldn’t include a USB-C to USB-A cable, as the first batch had. I ordered one but have yet to receive it. Frustrated with not being able to deploy to my Apple TV — or even find the UDID so I could produce a TestFlight build — I decided to take matters into my own hands.

One USB-C to Female USB-A adapter, some soldering, and a bunch of duct tape later, I had my solution.


Building DubDub: Part 1

tvOS offers two options for building Apple TV apps: UIKit and TVML. Both offer interesting opportunities. If your app requires custom UI or makes use of system frameworks like Metal, Core Data, or GameKit, a UIKit-based app is the obvious solution. If your app simply displays a collection of content from an API you control — video, news updates, music, etc. — TVML seems like a great choice. It’s faster and you get a lot of great UI for free.

tvOS offers two options for building Apple TV apps: UIKit and TVML.

Both offer interesting opportunities. If your app requires custom UI or makes use of system frameworks like Metal, Core Data, or GameKit, a UIKit-based app is the obvious solution. If your app simply displays a collection of content from an API you control — video, news updates, music, etc. — TVML seems like a great choice. It’s faster and you get a lot of great UI for free.

I’ll be playing around with both, in time. Being more comfortable with UIKit, I decided to tackle that first.

When tackling a new platform or technology, I like to like to build a “real” app. When I was learning WatchKit, I was lucky to have the opportunity to build a Watch app for the Globe and Mail. This time around, I’ll be building a project of my creation: DubDub. In a sentence, my goal is to put much of the functionality of the WWDC app on the Apple TV. It’s not an app I plan on selling–or even releasing–but I think it will provide an opportunity to touch a lot of the SDK.


My first “real” tvOS app

I’ll be sharing more thoughts later, but I quickly put together my first functional — though far from pretty or HIG-compliant — tvOS app last night and wanted to share. You can browse every WWDC session video and easily watch it from your couch. Your simulated couch, anyway. In case it wasn’t obvious, full-screen table views are ugly and a bad idea. As expected.

I’ll be sharing more thoughts later, but I quickly put together my first functional — though far from pretty or HIG-compliant — tvOS app last night and wanted to share. You can browse every WWDC session video and easily watch it from your couch. Your simulated couch, anyway.

In case it wasn’t obvious, full-screen table views are ugly and a bad idea. As expected.


tvOS: First Impressions

Finally. I’ve been excited by the prospect of creating apps for the Apple TV since 2012. After three years of rumours and hints from Apple execs, it’s finally here. After downloading all the things, I fired up Xcode 7.1 and started poking around tvOS. Hey, everyone has to start somewhere right? Some quick first impressions: There’s two ways to build a tvOS app. A full UIKit-backed app or an app built using JavaScript and TVML.

Finally. I’ve been excited by the prospect of creating apps for the Apple TV since 2012. After three years of rumours and hints from Apple execs, it’s finally here. After downloading all the things, I fired up Xcode 7.1 and started poking around tvOS.

Hey, everyone has to start somewhere right?

Some quick first impressions:

  • There’s two ways to build a tvOS app. A full UIKit-backed app or an app built using JavaScript and TVML. TVML sounds pretty similar to how current Apple TV apps work — XML templates provided by a server. Interesting that they’ve left that as an option.
  • The simulator is huge. It simulates a 1080p display and, near as I can see, there’s no way to test it at a smaller resolution. I can see the entire window on my Thunderbolt Display, but my 13-inch Retina Macbook Pro requires bumping it down to 50% scale to be useable.
  • You interact with the simulator using a simulated remote. You can’t just click around like you would in the iPhone simulator. After some reflection, I’m glad developers are forced to interact with tvOS apps the same way their users will.
  • Local storage is not an option. I tweeted about this pretty quick yesterday. Apps are limited to 200mb — anything beyond that will have to be fetched dynamically. Apple’s On-Demand Resources, introduced at WWDC, were created for this very reason, I suspect.
  • Lots of iOS frameworks didn’t make the cut. I was most surprised by the exclusion of HomeKit. You can see the full list here.

All told, I’m extremely excited. There’s lots to learn and lots to share. More to come as I dig in.


Things to think about when planning an Apple Watch app

The first question to ask yourself is, “Just what the heck is this thing going to do?” For the average user, the Apple Watch will be joining an entire constellation of devices they already use in the course of a day. If they use their laptop for general computing, perhaps they use their iPad for reading books or blog posts on the couch. Or watching Netflix. They pull out their phone on the go to play games or catch up on Twitter.

The first question to ask yourself is, “Just what the heck is this thing going to do?”

For the average user, the Apple Watch will be joining an entire constellation of devices they already use in the course of a day. If they use their laptop for general computing, perhaps they use their iPad for reading books or blog posts on the couch. Or watching Netflix. They pull out their phone on the go to play games or catch up on Twitter. We’ve all seen someone browsing Instagram on the bus.

Despite how connected to our smartphones we’ve all become, the Watch will be even more intimate. It’s literally strapped to your body. You need to respect that.

Should your app exist?

Assuming you have some say in the matter, take a moment to ask yourself if creating a WatchKit app for your product is really beneficial for your users. I love Dropbox, but struggle to think of any reason I’d want it on my wrist. Perhaps they’ll surprise me.

What would your app bring to the table? In my mind, useful Watch apps do one of three things:

1. Make it easier to do my job or live my life.
2. Improve the connections I have with people I care about.
3. Bring a small moment of joy into my life.

If the app concept in your mind doesn’t fit into one of those three categories — or more than one — I would think long and hard about whether it should exist at all.

When in doubt, why not ask your users? By speaking to my app’s potential users, I’ve avoided making false assumptions about how they’ll use it.

If I try your Watch app and you piss me off, I won’t be back.

Precious Seconds

If we measure iPhone app usage in minutes, Watch apps will be measured in seconds. In my testing, users want their smartwatch to integrate into their life/workflow, not become the focus of it.

Watch apps should get the user in and out as fast as possible. Convenience is your guiding principle.

I had the opportunity to test a Pebble smartwatch for two months and I loved how little I had to pull out my phone to deal with my digital life. New message from a contact? I glanced at my wrist, decided whether or not it needed to be dealt with in the moment, and got on with my day.

That’s powerful.

When you’re planning your app’s functionality, design, and UI don’t disrespect my time by asking me to do any more than that.

Duplication of effort

A Watch app complements your existing iOS app, it doesn’t replace it. Don’t try to re-create all of the existing functionality. What are the top three features your app needs and your users would appreciate? Better yet, what’s the one killer feature?

  • I want to start/stop recording my bike ride in Strava, I don’t want to read through a long list of every ride I’ve ever taken.
  • I want to see the latest deals at the store and find the closest location. I don’t want to browse every product you carry.
  • I want to see the top 5 reviews of the restaurant I’m standing in front of, not read every damn review ever written.
  • I want to read the top news stories of the day that are most relevant to me, not flip through every story in the paper.

Your Watch app is bundled with a fully-featured iOS app. Don’t duplicate your effort. If you simply “minify” your existing app, you blew it.

Working on an awesome app for the Apple Watch? I’ve released a set of 113 HIG-compliant icons called Chronicons. Designed specifically for the Apple Watch, they’re $5 off until Wednesday.


How to Design an Icon Set for the Apple Watch

As I prepare to wrap up work on the first edition of Chronicons, my menu icon set designed for the Apple Watch, I wanted to share a few of the steps I took to (hopefully) ensure its success. Designing for a brand-new device — particularly one that hasn’t been released — can be tricky. It’s important to find ways to anticipate design considerations ahead of time, rather than just waiting for launch.

As I prepare to wrap up work on the first edition of Chronicons, my menu icon set designed for the Apple Watch, I wanted to share a few of the steps I took to (hopefully) ensure its success.

Designing for a brand-new device — particularly one that hasn’t been released — can be tricky. It’s important to find ways to anticipate design considerations ahead of time, rather than just waiting for launch. Here’s the approach I took:

1. Read the documentation

Often the docs are all you’ll have to go on at first. For Apple products, the Human Interface Guidelines are your bible. Following the guidelines in the HIG won’t stop you from designing garbage, but it’s better than going in blind.

I went one step further and used iOS Artwork Extractor to grab the menu assets included in the beta OS. By studying how Apple’s designers had created their icons, I was better able to understand the guidelines set out in the HIG.

2. Follow what other people are doing

Every morning I sit down with a coffee — or a Red Bull — and open a new tab to the Apple Developer Forums. Ditto for Stack Overflow questions tagged “WatchKit”. Oh, and a Twitter search for the same.

Part of the reason I do this is to find great links for WatchKit Resources. But it also allows me to stay abreast of the problems other designers are facing — and the solutions to those problems. When it’s the Developer Forums, those solutions often come Apple devs, designers, and evangelists. Invaluable. Where I can, I try to offer solutions of my own — either by responding directly, or writing blog posts.

3. Fake it

Designing for a device that hasn’t been released yet is really hard. Sure, you can read the HIG and look at pretty mockups on Dribbble. But it doesn’t help you understand the context your work will be used in. It didn’t for me, at least.

The size of the Apple Watch simulator window can be deceiving. If you want to get a better sense of just how damn small the Apple Watch is, I suggest using Bezel to bring it back down to size.

But that wasn’t enough for me. Forget launch dates, I wanted to hold an Apple Watch now. Enter 3D printing. I created a model of the 42mm Watch and, at one point, strapped it to my wrist with duct tape. If you have access to a 3D printer, I highly recommend it.

Oh, and I wore a bunch of competing smartwatches. Every single one I could find. Pebble, Moto, you name it. Fitness devices like the FitBit and the FuelBand, too. I wanted to understand their individual strengths and weaknesses, along with the benefits of wearables in general.

4. Talk to your future customers

Coming up with icon concepts was easy, at first. I knew the kind of apps I wanted to build for the Watch, so I created icons to fit those ideas. After a few weeks, however, I realized I needed to ask other developers what they were working on.

I chatted with my fellow Apple Watch devs every chance I got. Heck, I still do. I asked them what they were working on, where they saw the Watch going in the future, and what sort of design assets they needed for their projects. Basically, I listened to their needs and then said, THAT’S AWESOME PERHAPS I CAN HELP.

There are plenty of icons that wouldn’t have made it into Chronicons Edition #1 if it weren’t for those conversations. And I already have a great list for Edition #2.

5. Assume you’ll be wrong

This is all well and good, but we still don’t have the damn Watch in our hands. And, despite all the efforts to lessen the risk, that’s still a risk. Particularly when you are asking customers to give you cold, hard cash for your design work. I know there’s a good chance some of these icons will need tweaking once the Apple Watch has been released to the public. If something ends up looking like crap, I don’t want people to feel ripped off. But I also want them to be able to make use of Chronicons now.

To that end, I am committing to free updates for all customers. Dead stop. It just seems like the right thing to do. If you are getting ready to launch your own pre-launch products for the Apple Watch, I would suggest thinking about doing the same.

Working on an awesome app for the Apple Watch? Chronicons Edition #1 will be available March 4th, 2015. Want to hear more from me? Sign up for the mailing list to be first to know about new icons sets and deals.


The Kevlar Tube

Your fiancé’s chest hurts. The doctors find clots. Big ones. You’re thankful they found them. She’s in the hospital for a week. Constant pain. Blood-thinning medication until who-knows-when. Trips cancelled. Time off work. The day she came home from the hospital, someone stole your bike. Asshole. The dog gets hurt. A stick went into his chest. Impaled, really. He needs surgery. Expensive surgery. What else is there to do? Stitches, a tube coming out of his chest.

Your fiancé’s chest hurts. The doctors find clots. Big ones. You’re thankful they found them. She’s in the hospital for a week. Constant pain. Blood-thinning medication until who-knows-when. Trips cancelled. Time off work.

The day she came home from the hospital, someone stole your bike. Asshole.

The dog gets hurt. A stick went into his chest. Impaled, really. He needs surgery. Expensive surgery. What else is there to do? Stitches, a tube coming out of his chest. He’ll be fine.

Hours spent in hospitals of every stripe. Keep moving.

Then your chest hurts. You’re at work. Sharp, at first, then dull. Then heavy. Then your left arm feels numb. Is this a heart attack? You look up “symptoms of a heart attack.” That was a bad idea.

Don’t take chances.

You vaguely explain why you aren’t at work. It’s too embarassing.

The doctors are great. Lots of machines. Two rounds of blood tests. A needle in your hand. Waiting. Oh, the waiting. And questions.

When’s the last time you ate? It’s hard to remember.

Then, nothing. You’re fine. No heart attack. Stress, most likely. You haven’t been sleeping much. You’re young.

You don’t feel young.

An ER doc comes by to take the needle out of your hand, five hours later.

“Getting that needle out will be the highlight of my month.”

He smiles. “Actually, it’s not a needle anymore. Now it’s a thin kevlar tube.”

And you laugh. A crazy laugh.

Who cares?