by Matthew Thompson, Senior iOS Engineer at Enola Labs
Recently, our team decided to take on WatchKit to create an Apple Watch extension for one of our apps, Texas Landmarks. The Texas Landmarks app contains Texas’ 14,000+ historical markers and makes it incredibly easy for users to discover nearby landmarks and learn more about their related history.
The “Near Me” feature was one that we found users really enjoyed, so we decided to make it the focal point for our Watch app. The final version of the Watch app that we came up with takes the user’s latest location and puts the 5 nearest historical landmarks right at their wrist. From there, they can read more and even get directions straight to a landmark.
Along the way we learned a lot about the features and conversely, the limitations of both the Apple Watch and WatchKit.
The first problem we ran into with development was data accessibility. Before WatchKit and Extensions, an application had its own documents directory that contained any and all resources that were necessary for it to work. Images and any other resources could be stored in this directory, along with any CoreData stores that you created in your application. Since Texas Landmarks uses a SQLite persistent store for CoreData, it makes use of this feature for storing all of our data. Watch Apps and Extensions however, are separate from your application bundle. This meant that our Watch App had no way to access the massive amount of data that we had used to populate our CoreData database.
Fortunately, Apple has built in a methodology for sharing information between applications and extensions - App Groups. App Groups are an entitlement added to an application target that allows them to access a shared container for any information that needs to be accessible across apps. By creating a group with a given ID and adding it to both the Landmarks app and Watch extension we were able to make our info available to both. From here, we could simply move all of our CoreData resources from the current application bundle to the shared container and boom - Watch app.
This is where the limitations of the Watch app come into play; memory restrictions on extensions are significantly lower than those for an iOS application. Previously on the iOS app, we were able to load large numbers of landmarks into memory for filtering and display. With the watch app though, we found very quickly that the system was terminating our application much faster than we expected. This required us to rethink how we managed shared information between app and extension.
Since our Watch app was designed to show only the 5 nearest landmarks in relation to the user, we were able to come up with a different solution that solved both our performance and memory problems. We used Texas Landmark’s existing location manager to cache the nearest landmarks in the shared container on a location update event (either while running the app or in the background); ensuring that our Watch app queries were always concise and manageable.
This was easily done using the NSUserDefaults initWithSuiteName method introduced in iOS 7. Not only is NSUserDefaults an extremely simple way to share data between applications, it is also an API that iOS developers should be incredibly familiar with. By using our shared App Group as the suite name, we enabled access to our shared cache for Landmarks and the Watch app. From there, the watch app could simply grab the cached landmarks and display them on screen to the user.
As iOS devices have become significantly more powerful, user interfaces have become significantly more sophisticated. Custom animations, layouts and transitions are the norm for any modern application and can make or break a user experience. However, any good app should be responsive and fast regardless of how it looks.
The Apple Watch has a drastically simplified API for UI which at first glance seems almost too restrictive to be useful. The level of customization available for view components is minimal, at best. Animations on the watch are nothing more than a sequence of images, either generated on the phone app or stored in the WatchKit app bundle. Gone are the AutoLayout constraint methods that iOS developers have become so familiar with, replaced by a simple hierarchical vertical/horizontal layout system. Items can be grouped to provide some additional flexibility but by and large the watch manages all layouts itself, placing items on screen from left-to-right or top-to-bottom as defined by the interface controller.
Once the initial shock wears off, UI development for the Watch becomes a very freeing experience. The interface is intended to be simple and clean, with the data right at the user’s fingertips without all the frills and fuss. The Interface classes give you enough flexibility to let you configure your app to reflect your branding and then they handle the rest. Images and animated image sequences can be cached (up to 5 MB) on the device for faster load times.
Our watch app’s main interface makes use of a table containing the cached landmarks with the estimated distance to each. Tapping on a landmark presents an interface with a map and a description of the landmark. One side note - Maps on the watch are incredibly slow to load and not interactive (tapping an enabled Map View leaves your app and opens the Maps application), so consider their benefit before deciding to throw them into your app.
Anyone who has dealt with Apple’s provisioning system before is well aware of the headaches it’s capable of inducing. Setting up a Watch app is no exception, as we found when preparing to submit our new version to the App Store. With XCode 6.3 and newer it seems that in order to submit an app with a Watch app extension to the store, you must have a provisioning profile set up for each component: Application, WatchKit extension and the Watch app. This means that in the provisioning portal you need to create App IDs for each component with a matching distribution provisioning profile. Our application ran fine in Debug and testing without them, but when the time came to submit to the App Store our app failed to validate until all of the profiles were set up and configured.
Development for the Apple Watch requires a slight paradigm shift in both design and implementation, but in many ways those changes are beneficial for the end user and for the developer. It isn’t without its shortcomings - the Watch’s Bluetooth connection is unreliable and painfully slow at times, so smaller requests and limited communication between the Watch and Phone are essential to a responsive app. None of these obstacles are impossible to work through - it just requires the developer to streamline an application’s feature set and how information is presented to the user. Take the time to plan out what features your user’s will love to see in a Watch app and leave the rest to your phone application. Apple has compiled several great references for WatchKit development on their developer site.
Feel free to contact us at Enola Labs if you are looking to learn more from our web development company experts.