Apple Watch Series 3 makes it easier to stay connected, even when away from your phone. Learn how to keep your app responsive over cellular connections using URLSession. Find out how to optimize your Watch app networking code to ensure that your app is always up to date and ready for use. Discover how to leverage Core Motion data from the new barometric altimeter for displaying relative altitude changes.
Updating your watchOS 4 app for Apple Watch Series 3
makes it easier than ever to stay connected,
and allows you to leverage the new barometric altimeter.
Apple Watch began with a dependence upon
its connection to iPhone for all networking.
However, since watchOS 2,
Apple Watch has had the ability to communicate over Wi-Fi
if your iPhone is off or out of range,
and you are in range of a Wi-Fi hotspot
your iPhone has previously connected to.
Apple Watch Series 3 with cellular
now allows your app to communicate directly
over a cellular connection if your iPhone is out of range
and Wi-Fi is not available where you are.
Not only can your app update its data from anywhere,
but push notifications received by your iPhone
will be automatically forwarded to your Apple Watch
when it is on a cellular connection.
To make sure that your app works
over any and all connection possibilities,
itâ€™s now even more important to use URLSession
for networking requests in your watch app.
URLSession is the class used for creating and managing
networking connections in watchOS.
Using URLSession from your watch app code,
allows you to initiate network requests
directly from Apple Watch.
When your iPhone is in range of Apple Watch,
these requests will be proxied behind the scenes through iPhone
to leverage its connection.
Otherwise, requests will occur directly through Wi-Fi hotspots
or cell connection.
When using URLSession while Apple Watch is only
on a cellular connection, be aware that sessions
may be handled slightly differently by the system.
Letâ€™s look at the different types of sessions
and what you can expect.
For default and ephemeral sessions,
these type of sessions will work as they normally do
when the application state is active.
You can check the current application state using
the applicationState property on the shared WKExtension object.
However, these type of sessions are not allowed
if the application state is inactive or background.
There is one caveat to this, as they are allowed if your app
is currently using the background navigation mode.
Next, letâ€™s look at background sessions.
With background sessions, smaller transfers are preferred,
and any transfer could be deferred until a point
where the system has a better opportunity
to make network requests.
This is determined at a system level
and takes into account many facets such as power level,
and tasks other apps are needing to accomplish.
With background sessions, once the request has been made
and a response has returned,
if your app is in the frontmostapp state,
your app will be woken immediately
and handed the response.
Outside of the frontmost app state,
the system will wake your app with the response
when it determines it is a good time to do so,
or when the application state becomes active again.
Now letâ€™s go over a few best practices to make sure
you get the most out of your networking code on watchOS.
The first is to use the new waitsForConnectivity property
on your URLSessionConfiguration object.
Setting this to true on a non-background session
will allow the system to wait until connectivity
is sufficient to make the request,
instead of immediately failing.
There is a delegate method
to know when the connection is waiting,
so you can handle the situation.
We encourage using this property for all requests that are not
dependent on being immediate, since they will fire immediately
as long as connectivity is available.
If not, the system will wait on making the request
until connectivity resumes.
This allows you to focus on what makes your app great
instead of focusing on reachability code.
Using the applicationWillResignActive
method on the WKExtensionDelegate object
allows you to optimize what happens
when the application state changes from active to inactive
or background when you have a networking request in process.
In other words, when someone puts their wrist down
while using your app.
By using this method,
you can decide to cancel your existing request,
or create it again as a background session.
Finally, itâ€™s always best to use
the shared singleton URLSession object for multiple tasks,
instead of creating a session for each task.
Creating and invalidating many sessions
creates unnecessary overhead for the system,
and itâ€™s best to use the shared session,
or as few as needed.
Letâ€™s move on to the Watch Connectivity framework.
As Apple Watch becomes more independent
with its connectivity,
itâ€™s important to identify where using Watch Connectivity
can help make a great watch app experience.
The initial launch of an app on Apple Watch
may require a token for authentication with a service.
Using Watch Connectivity is a great way
to pass this information that may already be established
in the iPhone app.
If your app is a coaching app for workouts,
or something similar,
you may want to initially transfer some larger audio files
to Apple Watch once someone begins using your app.
Watch Connectivity can handle these type of transfers,
and can help your app installation remain small
and supplement the app with resources later.
The updateApplicationContext method on WCSession
allows you to have the iPhone send over a dictionary of data
that the watch app has access to the next time it activates.
This is a good way to keep fresh data flowing to the watch app
in case of situations where the iPhone app gets newer data
and the watch app hasnâ€™t had an opportunity to update yet.
When the watch app launches, you can display this newer data
while you initiate a network request
for more up-to-date data.
Itâ€™s very important that you build in the ability
to fallback to a network request.
With Apple Watch being more independent,
there is less guarantee that your watch app
will have up-to-date data from the iPhone.
Now letâ€™s turn our attention to the new barometric altimeter
in Apple Watch Series 3,
which enables you to now add elevation gain or descent
to workout summaries when someone is away
from their iPhone.
This also helps provide more accurate
active energy burned calculations to HealthKit,
and in turn, your app.
Using Core Motion, your app can now
be informed about relative altitude changes
from where your app begins receiving updates.
Relative altitude changes means that if you begin updates
while standing at an elevation of 800 meters,
and move 50 meters higher in elevation,
the relative altitude value will be 50 meters.
If you move 80 meters lower than where you began,
the relative altitude value will then be negative 80 meters.
Core Motion includes the CMAltimeter class,
which you will use to receive updates.
CMAltimeter can determine and tell you if the device
has the capabilities to give relative altitude updates.
You should always check this first
before asking Core Motion more about relative altitude.
In watchOS 4, CMAltimeter can now provide you with
the authorization status for Motion and Fitness activity.
Depending on what your app is allowed to access,
you may need to handle cases where authorization
is denied or restricted.
Finally, CMAltimeter provides the ability to start and stop
relative altitude updates.
These updates are delivered on a two-and-a-half second cadence
on watchOS 4, due to signal filtering
that we apply to the raw sensor data.
When you receive an update, you will have a handler
that passes you a CMAltitudeData object.
The CMAltitudeData object gives you
the relative altitude change data for that update.
This includes the following pieces of data:
first is the timestamp.
This object is a time interval and is given as
the number of seconds since the reference date.
To convert this value to a Date object,
you can easily use the timeIntervalSinceReferenceDate
initializer method on the Date class.
The next property is relative altitude.
This represents the change in altitude
since the last reported event.
Remember that this will be a relative value,
so if the device moves lower or higher in elevation,
this value will represent the change in elevation
and not the specific altitude.
This value is given in meters.
The last property is pressure.
Since the altimeter onboard is a barometric altimeter,
Core Motion can provide you with the recorded pressure
alongside the relative altitude change.
This value is given in kilopascals.
Letâ€™s walk through an example of how to start
relative altitude updates using CMAltimeter,
as well as how to properly check for device capabilities
and authorization status.
Previous to this beginAltitudeUpdates method,
Iâ€™ve imported the Core Motion framework into my class
and created an instance variable called altimeter,
of type CMAltimeter.
Thatâ€™s the object we will use to start and stop
relative altitude updates later on.
In our function, the first thing we should do is check
to see if relative altitude is available on the device.
If itâ€™s not, we may want to alter the UI
to let the person know that this data will not be available
as they use the app.
Next, we need to check if authorization status
is denied or restricted.
Here, weâ€™re making sure authorization status
isnâ€™t denied, nor restricted.
If the authorization status is authorized we can continue,
and if the authorization status is not determined,
the system will prompt for access,
if the person has not been previously prompted.
Once the app is authorized to use Motion and Fitness activity,
we may ask Core Motion to start relative altitude updates.
This call on a previously created CMAltimeter object
has us pass in which operation queue
weâ€™d like to receive updates on,
as well as provides a handler to run each time new data
is handed to us by Core Motion.
In this case, weâ€™ve set the operation queue
to the main queue since we will be updating UI in the handler.
Moving to the handler, it passes us a CMAltitudeData object,
containing the values we are interested in,
or possibly an error if something went wrong
in the update.
After ensuring we have no error to handle,
we simply grab the relativeAltitude value
from the CMAltitudeData object,
store its float value, and use that to update the UI.
We could just as easily use the timestamp
or pressure properties, as mentioned earlier.
Once we no longer need to receive updates,
we tell Core Motion to stop relative altitude updates,
using our previously used CMAltimeter object.
And thatâ€™s it!
For more information about developing for Apple Watch
and using URLSession and Core Motion,
please view the resources links at the following page.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.