Getting background location on WatchOS with no phone present

WatchOS 3.2 and Apple Watch Series 2

I wanted to see if it was possible to get a constant location from the Apple Watch Series 2, from the GPS, without having the phone present.

Background Task

The first thing to check is if it was possible to run a background task to get the location every so often. The WKApplicationRefreshBackgroundTask allows you to do this, but it is budgeted by WatchOS to one task per hour so was not any use for our purpose. It is obvious why this is the case, to save battery on the watch.

Background Modes

Getting location updates from enabling CLLocationManager in the watch is not a supported background mode, so CLLocationManager is not fully featured on the watch. On an iPhone, you can run this in the background and it will provide location changes to your app in the background. The only supported mode on WatchOS 3 is Workout Processing, with the added option of sound and picture in picture related to workouts.

How does Strava get location?

Strava is a workout app, and I have checked that the watch can be used for a run and track location without the phone present. I assume that it calls a location update when it gets the callback to process workout data from HKWorkoutSession. It may call data from Health Kit and that contains location information from that workout session. I could not confirm in the Health Kit documentation that workout data contains location information.

Conclusion

It’s not possible to create an app (extension) on the watch that gets location tracking without running a workout session.

Default values for optionals in Swift using the ?? operator

Swift 3

We know we need to test optionals to see if they have a value before we use them. If you use a nil value in your app, you could cause a crash. Let’s look at that.

Potential crash

We want to get a String value from UserDefaults. At this point, we have no idea what the value is, or indeed if it was ever set. On first run of an app, for example, it would never have been set and have a value of nil. Usually, the best way of dealing with this is to unwrap the optional and test the value with an if statement.

This is safe. It will only print the setting1 value if it existed. But what if we wanted to do something with setting1 even if the value didn’t exist? We could use an else statement to provide a default value.

Providing a default value for an optional

That’s a lot of code for providing a default. This is where a Nil-Coalesing Operator can help us. The Nil-Coalesing operator, ie: ??, will unwrap an optional, use it if it has a value, or use the right hand value if it finds nil.

Using ??

Great. If there is a value, it will use it, and we can provide a default value if setting1 equates to nil.

A few rules to using ??. The left hand value, ie: settings1, has to be an optional. The right hand value, must be of the same Type, in our case a String. It’s not costly to use this, because if the left hand value is found, it will not evaluate the right hand value at all.

Conclusion

The Nil-Coalesing Operator allows us to provide a default value for an optional at the time of use, and it is easy to read this short-hand method of doing so.

Xcode comments that show up in the source navigator

Xcode 8.2

Xcode’s source editor is a quick way to navigate the properties and methods of a source file. At the top of each source file, is a dropdown that allows you to jump quickly to where you want to go in any source file. Selecting collectionView in this example will show a menu of items you can jump to.

This is the basic menu.

Using MARK to group the menu

With MARK as a comment, you can add comments to the dropdown.

The result is a menu item in the place that you wrote the MARK comment. You can jump to these like any other method or property.

You can go one better and break sections up into groups just be adding a dash like so.

The result is a divider separating the MARK sections in the menu. It’s a great way to group code together.

TODO and FIXME

Other comments that show up in this menu are FIXME and TODO. You can leave yourself reminders for bugs you find and tasks that you need to do later. A number of languages recognise these comments.

Let’s see them in action in the source menu.

Conclusion

Organising your source menu can logically group together your code, help you to quickly find tasks, and bug comments, and give you quick access to where in the file you need to go. It is especially handy when the source file gets too large.

Better function parameter labels in Swift

Swift 3

Deciding on a good function name will help you later to remember what the function does and what it is expecting from you for the parameters you pass. I’m a big fan of long function names. If it takes the guessing out of what the function does, then I’m all for it. I can’t see any real advantage to having it short.

What is not used often enough is more explicit parameter names to go along with the great function name we created.

Consider you have a function that returns the day of the week by passing it an index which is an Int.

Well, it is obvious enough from the function name what this does, but index is used three times.

Using _ to avoid using a parameter label

What we could do is lose the parameter label by using _ before the index parameter which will be used by the function itself.

When calling the function, we do not need to use a label at all.

This is better, but we can shorten the function name by allowing the parameter label to explain what we need for this function, and the variable index was named in a way that does the rest.

Allowing the function parameter to act as a label only

The for label allows us to have a placeholder that isn’t used in the function itself. We can take advantage of this to achieve a shorter function name. Xcode will display that it requires an Int on auto completion of the function, so there is never a need to put types in the label. You wouldn’t use forInt for example. This is how Xcode displays it.

Conclusion

The parameter label can help us shorten the function name, and provide a clearer idea what the parameter should be, and all this can be done without changing code in the function itself.

Using Guard to early exit in Swift

Swift 3

You can use Guard to early exit a loop or function to prevent the rest of the code executing when it doesn’t have what it needs to run. This kind of safety is what makes apps stable when things go unexpectedly wrong.

Consider you have a function that builds a filename from data in your app.

We can not afford empty strings, which may cause crashes elsewhere in the app. For the sake of safety, it would be a good idea to make the function return an optional, and check for empty strings.

This works, but if the function was complex, and lots of code generated the filename, then we need it to exit early if the function did not have what we needed to generate a safe filename.

Using guard in a function

Let’s use guard to exit early.

The guard statement will return nil if the test given to it returns false. Below this, we know that name and suffix are not empty, so we can use them with confidence and return the result. This allows the code to be shorter, and more readable after the guard statement.

You can do the same thing with a loop. Lets look at an example of a guard statement speeding up a loop by exiting early using continue.

Using guard in a loop

In this example, we have an array of optional Strings, but one of them is nil.

With Guard, you can use return, break or continue to exit out of code early.

Conclusion

Guard can save CPU cycles in a loop or lots of testing during a function, and has the added benefit of making the code more readable, and much safer.