---
title: "A Core Location Abstraction Layer with Combine and SwiftUI"
source: "/writing/a-core-location-abstraction-layer-with-combine-and-swiftui/"
---

Article

# A Core Location Abstraction Layer with Combine and SwiftUI

Matt Czech

June 7, 2021

Photo by [Artem Beliaikin](https://unsplash.com/@belart84?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com/?utm_source=medium&utm_medium=referral)

One of the benefits of modern mobile devices is that they can determine your device's precise location. This enables you to get directions to where you're going, see nearby restaurants, or view a hyperlocal weather forecast.

On iOS, the [Core Location](https://developer.apple.com/documentation/corelocation) framework gives a developer access to the device's geographic location and orientation. At an initial glance, this makes it easy to determine the device's location, with great accuracy.

But as you start to dig into the Core Location documentation, you'll find that there are a few steps to the process. You have to first request the user's permission to access the device's location. Then, if granted, you can request the location. Since determining the device's location isn't always instantaneous, you'll get a callback once a location has been determined.

The Core Location framework uses delegation to asynchronously respond to requests for asking for permission and determining location. Let's see how this works by implementing a simple SwiftUI view which contains a button for requesting the device's location.

Since fetching a location is asynchronous, we will show a `ProgressView` while the location is being determined. Once a location is available, we either display a description of the location or an error message if a location wasn't able to be determined.

Now we can create the view model which handles interacting with a `CLLocationManager` to get the device's location.

There's a lot to this! The view model exposes properties for a loading indicator and the location or an error if the location is unable to be determined. Additionally, there's a function for fetching the device's location which requests permissions if necessary and then finally requests the device's location.

While this solves the need of getting the device's location, the logic is spread throughout the class. This isn't terrible to follow for now, but this is a simple example and the view model is only doing one thing. As the requirements for this view grow (and the code that follows), it's likely that the view model will become more complex, making it harder to understand and troubleshoot if there's a bug.

We can abstract some of this location logic so that it's encapsulated and reusable outside of this view.

We've moved all of the logic for requesting permissions and location into this `LocationService` class. Instead of using a delegate to communicate with `LocationService`, we've implemented Combine's [Futures](https://developer.apple.com/documentation/combine/future) .

A Future is a publisher that will eventually either produce a single value or an error. It is initialized with a completion closure that is called at some point in the future when the operation completes and either a value or an error is available. We can create a Future that is generic over `CLLocation` and `LocationError` which will either publish a `CLLocation` if a location is determined or a `LocationError` if there was an error fetching the location. Here's the full Future declaration with the completion.

If we happen to already have or know the value without needing to perform an async operation, we can call the closure immediately. This is used in the `LocationService` if we know the user has previously denied authorization to get the devices location, but we still want to return a Future.

Using a Future here is great for handling these asynchronous operations because it keeps the logic at the call site compact by allowing us to chain multiple operations together. Here's an updated view model that implements our new `LocationService`.

The API for our view model hasn't changed, so we can integrate this with our original `MyLocationView` without any changes. Now we have all of the location logic in one compact method. We start by requesting permission to get the device's location while our app is in use, and once that succeeds, we request the device's location. Any failures that occur in the chain will be handled in the `receiveCompletion` closure of the `sink` method.

This gives us a lot of flexibility. If we wanted to get the device's location on another view in the app, we no longer need to duplicate the delegate code within each view model. Additionally, `LocationService` isn't specific to this application, so we could reuse it in other apps that we are building and extend it to handle other location requirements. And switching from using a delegate-based API to one that uses Futures and Promises improves on the readability of the code within the view model.

While Core Location gives us a good testbed for demonstrating this technique, this approach can be used with other frameworks and even custom code that you write in your application. Hopefully this article has given you an idea of how you can abstract common logic into a helper or utility class to improve on readability and conciseness within your app.

_Matt works at_ [_Livefront_](https://livefront.com) _where he builds iOS applications with abstraction layers to make his life easier._

-   Matt Czech

    Software Engineer

    [More from Matt](/team/matt-czech/)

    Matt Czech

### Tags

[Digital Engineering](/insights/all/?topic=digital-engineering) [Mobile Apps](/insights/all/?topic=mobile-apps)

### Share

-   Copied

## View these next.

[See all](/insights/all/?type=writing)

-   [

    Article

    How To Sabotage Your Project Using Inconsistency

    Collin Flynn

    ](/writing/how-to-sabotage-your-project-using-inconsistency/)
-   [

    Article

    Unit Testing race conditions by creating chaos (Swift)

    Sean Berry

    ](/writing/unit-testing-race-conditions-by-creating-chaos-swift/)
-   [

    Article

    UIApplicationDelegate call sequence reference

    Sean Berry

    ](/writing/uiapplicationdelegate-call-sequence-reference/)
