Lorenzo Piombini

Mar 12, 2021

6 min read

Setting up a Location Manager (Swift)

I wanted to talk about this really cool feature that I have being learning lately,
As you guessed from my previous articles I am working on a weather app, fairly easy if you might think, but very exiting because it has brought up tons of aspect in developing such as Location Manager, HTTP REQUEST, JSON file, API, error handling and so fort , moreover, another aspect of this simple app is that it pushed me in Data structure and Design Patterns, and honestly , I wasn't aware that you can study those subjects with a specific language like data Structure with C ++ or C, or you can study that with Python (or whichever language you prefer)and I have decided to study those things with SWIFT! why all of this words to introduce the Location Manager ? because we are going to see this topic along the Singleton design pattern.

I used the following set up for a run app project working with MapKit.

I used to start setting up Location code within the View Controller, however it is a way better if you create a separate swift file and then you build there your Location Services.
Go ahead and create a new group called Location Services under your app Project, then create a swift file right in this folder called LocationController, LocationManager or even Location Services; you can pick whatever name you prefer. To work with location you have to import CoreLocation Framework after that, you can create a class that is going to inherit form NSObject, CLLocationManagerDelegate protocols .

right below this line of code, we can create our shared property which is fundamental to build this class as a singleton:

public static let shared = LocationServices()

we will access our LocationServices class from everywhere within the app using this shared property. I chose to use public because I will set the the init() as private.

remember that the primary goal of a singleton is to guarantee that we can create just one instance of a given type. at this moment we can access the class methods and properties using this shared variable.

Let’s create a Location Manager and a variable which will store our Coordinates.

let locationManager = CLLocationManager()
var currentLocation : CLLocationCoordinates2D?

let’s write the init()

as you can see we will create our configurations using the locationManager properties, first off you will set the delegate and the desired accuracy, you can pick the best one for your purpose I picked kCLLocationAccuracy Best ! why not 😃. then you set up distanceFilter which will call the method locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) when the User will move for a distance bigger 50 meters in order to update the location, do not set this filter to detected smaller changes, because it will trig the aforementioned method really often and there is no need in this case, also if you don’t set up a value of this property its default value with be kCLDistanceFilterNone and the delegate will be notified of every movement.
we can finish up our init() with the startUpdatingLocation() method.
when I first started to study Locations i used the requestLocation() method which it took seconds to find the location needed and it is not user friendly behavior.

we can now SetUp locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) to find our location :

we are going to set our variable currentLocation as :

currentLocation = manager.location?.coordinate like so :

There is one issue at this point, as you probably know or you have seen in a lot of app, we need to ask the permission to use the location to our Users so we need to add a property in the info.plist file and setting the key Privacy — Location When In Use Usage Description with a string that specify the reason why wee need the location, in the weather app it could be “We need your location to deliver always up to date forecast ” or in the Run App we could say “We need your location to show you the circuit/ path you made ”,
How to add at a key and Value to the info.Plist file? access your info.plist file within your project and the hit the last plus, like in the picture on the left hand side, now you can type the description Privacy — Location When In Use Usage Description and as a value you can explain why you need the location, there is one more step, we need to define a function checking the authorization and if there is not one, the method will ask at the user an authorization. we need to implement this in our ViewController and call the method into the viewDidLoad() function.

func checkLocationStatus(){

if LocationServices.shared.locationManager.authorizationStatus == .authorizedWhenInUse {

//do something

} else {

LocationServices.shared.locationManager.requestWhenInUseAuthorization()

}

}

now call this method in the viewDidLoad method and if you run your app you will be asked to give authorization if it is not already given.

so far we can’t really do a lot with our Location, we need to find a way to pass the location to the View Controller in order to use the Location data, the best approach among the others will be to use protocol and delegate, move back in our Location class and right above the class declaration write a protocol like so :

protocol CustomUserLocationDelegate {

func userLocationUpdated(location: CLLocation)

}

thus, we need to create a property in our class using our protocol :

var userLocationDelegate: CustomUserLocationDelegate?

a further step is writing a statement in the didUpdateLocations method, then will look like this:

so now you can go back to the ViewController and update the function that checks the authorization, where above we wrote //do something we can actually write :

if LocationServices.shared.locationManager.authorizationStatus == .authorizedWhenInUse {

LocationServices.shared.userLocationDelegate = self

} else {

LocationServices.shared.locationManager.requestWhenInUseAuthorization()

}

}

to have the location in our ViewController we have to write this extension:

now we can access to the the location from our Class.
to wrap Up the discussion regarding the singleton, we should worry about thread safety : what is it going to happen if more parts of our application have access at the class concurrently ? it should not be this case , however, there will be cases where you have to use GCD (Grand Central Dispatch ) to prevent weird bugs and crushes.
one of the best solutions would be probably use a technology called readers/writer, lock, I am going to write an article on this topic cause it deserve more time to be developed, anyway we will used GCD and its dispatch barriers to change a concurrent queue into a serial one.

create the barrier :
private let concurrentQueue = DispatchQueue(label: “concurrentQueue”, attributes: .concurrent )

and then change the only method in our Location Class in this way:

your location class should look like :

as always I hope you found this reading helpful, I will write more regarding design Pattern, like singleton cause I love the subject and i believe could be relevant in a career path.

see you soon.