M6L3 : We’ve Got Your Location

After spending far too much time on the Info.plist issue, we’ve now moved on to how to get the user’s location. As this has taken seemingly forever, I’m jotting down a few pointers here.

To set up our ViewModel to work with the location manager, we have to jump through a few hoops (something to do with Objective-C, whatever that is, that is what was previously used when creating apps).

The hoops we’re jumping through result in the following code:

 1. import Foundation
 2. import CoreLocation
 3.
 4. class ContentModel: NSObject, CLLocationManagerDelegate, ObservableObject {
 5.   
 6.   var locationManager = CLLocationManager()
 7.   
 8.   override init() {
 9.
10.       super.init()
11.        
12.       locationManager.delegate = self
13.        
14.       locationManager.requestWhenInUseAuthorization()        
15.        
16.   }
17.    
18.   func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
19.        
20.       if locationManager.authorizationStatus == .authorizedAlways ||
21.           locationManager.authorizationStatus == .authorizedWhenInUse {
22.                 
23.            locationManager.startUpdatingLocation()
24.            
25.       } else if locationManager.authorizationStatus == .denied {
26.            
27.           // We don't have permission
28.       }
29.        
30.   }
31.    
32.   func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
33.        
34.       print(locations.first ?? "no location") 
35.       
36.       locationManager.stopUpdatingLocation()
37.        
38.   }
39.    
40. }

What It All Means:

Line #2 : To do what we wish to do with the location data, we first need to import the CoreLocation framework, which contains the classes related to location.

We need to access the Core Location Manager class (CLLocationManager()). After creating a new object instance of the class and assigning it to our property locationManager (line #6) we can use it in our init() method.

Line #12 : We set ContentModel as the ‘delegate’ of the location manager. However, in order to do this the ‘delegate’ must conform to the CLLocationManagerDelegate protocol (line #4).

Line #4 : The CLLocationManagerDelegate protocol must conform to the NSObject protocol.

Line #8 : To conform to the NSObject protocol, we need to override NSObject‘s own init() method.

Line #10 : Having overridden NSObject‘s own init() method, we need to call it as part of our own init() method – so we’re effectively just adding our own init() method to the parent init() method.

Now that we’ve done all of this, and line # 12 has assigned ContentModel as the ‘delegate’ of the location manager, we can proceed to handle the methods that the location manager will call (such as whenever the permission has been granted, or changes, etc).