On May 26 we conducted our 6th MadCode Meetup. It’s free monthly webinar where members of our team share their knowledges in some specific area of mobile development. This time Paul Taykalo, iOS Tech Lead at Stanfy talked about first steps in Apple Watch development, particularly about:
- restrictions that developers and designers are forgetting about;
- communication between Apple Watch and your application.
In this article he also shares best practices when programming for Apple Watch. So make yourself comfortable and we begin!
I think there is no need to explain why we should develop for Apple Watch (it’s obvious) the more important thing is to know how.Let’s start with some not so obvious (for some people) pitfalls.
The first one you encounter is that you need an iOS app to create a Watch app, because it serves only as an addition to the first one. So now, when a client asks you to make just a Watch application— you know what to answer.
The second one, and I think it’s a major one, is to have a good idea. Yeah, this sounds banal but there are a lot of cool iOS apps and obviously their devs will create super cool Apple Watch apps and there is also a lot of trash which I bet you don’t want to add to.
Three main parts of Apple Watch applications
Now we’ll talk about what users can see on the screens of their watches. There are three main things with which users interact:
- App itself.
Notifications contain short bits of info about changes or updates in the app. In full form (which appears after users have looked at it for some period of time) it becomes more detailed. If it’s an actionable notification, users can respond by, for example, accepting or declining offered actions associated with this notification.
Glance is a non-active static type of a screen without interactive elements (no buttons, no sliders). It should show the most valuable info (user’s score, weather, maps, etc.). There’s only one glance per application, so you need to choose wisely when deciding what to put there. Glances are read-only. The only way a user can interact with them is by tapping on it. By doing this, the user will be taken to the main application.
The App itself. Here you have more freedom and can make interactive controls, pictures, tablets, etc. Despite the fact that the app is the biggest part of your work, users spend most of their time on the notifications. In the article Smartwatch User Interaction Pavlo Bashmakov explains this case. So you need to understand that only the uniqueness of your app content can attract users’ attention. Now let’s talk about the app’s structure and look how it works inside. It’ll help you to understand the constraints of the platform.
Here you can see that, the iOS app and Watchkit Extension are stored on your iPhone and the Watchkit app is stored on Apple Watch. Moreover all code will be kept in Extension and all the actions you perform using your Watch application will be sent to the phone by BlueTooth where commands will be carried out and the result will be sent back to your Watch app. So there is no third party code in the Apple Watch, there are only your storyboards, assets, pics and resources.
The first one is that you have to work with Storyboards (all your screens will be displayed in them). For now there are no instruments to create apps without Storyboards.
This is an example of an average app on Apple Watch. It has four screens, three of which create app content and one of which is Glance. There are no custom notifications screens here, so notifications in this app will be shown in the standard way.
Two sizes. You should never forget that there are two devices and they are different sizes. So if you created a design that has only one size and start to scale it, some elements can become pretty small, and you’ll need to redesign it to make it work for devices with smaller or bigger screen sizes.
Static Layout. That means you can show users only the info you have in the storyboards.You can not create an element in dynamic. What you can do is make many, many, many elements in storyboards and — depending on the app state — show or hide them. Also, in WatchKit we have a write-only interface. It’s good in that all the code is logic-oriented and doesn’t depend on UI.
The way we do it on the phone:
The way we do it on the watch:
Remember: we can’t create dynamic elements or change properties so animation can be done only with a number of pics and the command to WatchKit to change pics in time with x speed in one or the other direction.
The other important restriction is that there are no such things as UITouch, Custom Gestures, Swipes or Recognizers.
The only event you receive from WatchKit is a tap on interactive elements.Your methods will be called when users tap on something. Nothing more.You have only to touch or force touch when the user calls the context menu. Deal with it.
No sensors API. There are a heart rate sensor, an accelerometer and a couple of others BUT you don’t have access to them.
Limited text input. If a user needs to type a text we can provide him with some variants or suggest to dictatate it.
So with all these restrictions you feel like this:
Despite all these restrictions we need to struggle and create cool products for our users. So below I’ll share some of our best practices.
Images. Apple Watch is too slow. In order to avoid making it even slower, be careful working with images.
When you call setImage: you must remember that code is processed in Extension and the image itself stored on the phone. So while a picture goes from the iPhone to Apple Watch via Bluetooth, the user sees a spinning wheel. So for static images you’d better use setImageNamed:. Working with dynamic pictures from the Internet, try to resize them to the desired size before sending them to the device.
Be careful with Life Cycle. Working with Interface Controllers you will need to remember these main methods:
The awakeWithContext method is called once per Interface Controller lifecycle, and here you need to prepare base information for the screen.
WillActivite/willDeactivite methods will be called each time a user goes in or out of screen and should be used to show most actual information, subscribe/unsubscribe to notifications.
Network. How do you download network data? There are two variants. You can create a download code in WatchKit Extension and take data from the internet or you can ask the main application (through WatchKit Extension) to get needed data. The first variant is good when you need a little info, because Extension terminates faster than the app itself.
App and Extension communication. Who is in charge?
You’ll need to decide where is the main application logic lives. I cannot force you, but it should live in the main (iOS) application. So your watch application can ask for some valuable data by calling`WKIterfaceController: openParentApplication` method. This method will run your application if it wasn’t running before, call the method to handle requests from Watchkit, and return a response. It’s good to know that you cannot force your iOS app to be opened in the foreground.
Use shared groups for communication. Shared groups are a separate directory which is available both for WatchKit Extension and for applications. If you develop a few apps you can make shared group info available to them. It’s useful when you have one database. There’s a good library that is working based on this approach. It’s called MMWormhole.
MMWormhole pros and cons:
- Fast, reusable, any data
- Notification based
- App should notify users about each change
- WatchKit App should be running
Handoff mechanism helps in communication between apps:
- when we need something to be done in the app
- when permissions is about to be activated
- designer task
- custom navigation (all in one controller)
- 2 devices, pixel perfect
- hard to debug
- static – static transitions
But this tool can help to generate a number of needed wireframes as you did it on the phone.
Code reusage. Your code is doing almost the same things on your phone as it is on your watch, so try not to duplicate the business-logic code— it will be hard for you to track changes.
For doing this we’re using the so-called from MVVM(Model-View-ViewModel) architectural pattern. The main idea is to create a passive View, and all logic about what to show is decided on the ViewModel layer so you’ll be able to reuse ViewModel classes, and you’ll need to implement View for each type of device, and there’ll be no need for logic duplication.
How to speed up your app?
- Knowing all this info, rethink your WatchApp.
Always remember about dynamic and static content. If you can show part of the info in static, do it.
- Show content as fast as you can (use cache).
- Show partial information if available (Static+Dynamic).
That’s it. I will give you some more tips.Think hard about the best usage (twice). Think harder about the best usage of your application on Apple Watch. Don’t copy functionality just because it was in your iPhone app. Please don’t! Always track what users are doing in your application. Track their actions. It’s a new device, so you cannot be sure how a user will use it. Track, measure, and make your decisions based on that information. And don’t forget to use the best practices, of course.