Startseite Improving Location Tracking in an iOS Application: Case Study of the Parkplatzmanager App
Eintrag
Abbrechen

Improving Location Tracking in an iOS Application: Case Study of the Parkplatzmanager App

In today’s blog post, we’ll be exploring how we can leverage Apple’s SwiftUI and Combine frameworks to improve location tracking within our iOS apps. Our use case involves a parking management app, where we want to keep track of the user’s current location to provide accurate services.

Initial State

Initially, our code had a lack of continuous location updates while the user was interacting with the app. This could potentially lead to inaccurate location data, which would affect the functionality of our parking management app.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct ParkingView: View {
    @EnvironmentObject var locationService: LocationService
    @State private var currentLocation: CLLocation?
    
    var body: some View {
        // Other views...
        
        .onAppear {
            os_log("Location updates started", log: viewLog, type: .debug)
            locationService.startLocationUpdates()
                .sink { location in
                    self.currentLocation = location
                    os_log("Current location: %@", log: viewLog, type: .debug, location.description)
                }
        }
    }
}

Continuous Location Updates

To make location tracking more accurate, we decided to implement continuous location updates.

First, we made changes in LocationService by replacing the getCurrentLocation() method with startLocationUpdates(). This method would return a publisher emitting new locations as they were updated by the CLLocationManager.

1
2
3
4
5
6
7
8
9
class LocationService: NSObject, ObservableObject {
    private let locationManager = CLLocationManager()
    private var locationSubject = PassthroughSubject<CLLocation, Never>()

    func startLocationUpdates() -> AnyPublisher<CLLocation, Never> {
	    locationManager.startUpdatingLocation()
	    return locationSubject.eraseToAnyPublisher()
    }
}

Next, we modified the SwiftUI View’s .onAppear method to subscribe to this publisher, storing the returned AnyCancellable in a @State property. This is important because we need to manage the lifecycle of the subscription and make sure it gets cancelled when the view disappears.

In the .onAppear method, we started the location updates and stored the new location updates in currentLocation:

1
2
3
4
5
6
.onAppear {
    self.locationUpdateCancellable = self.locationService.startLocationUpdates()
        .sink { location in
            self.currentLocation = location
        }
}

To make sure that location updates stop when the view is no longer on screen, we added an .onDisappear method that cancels the subscription and stops location updates:

1
2
3
4
.onDisappear {
    self.locationService.stopUpdatingLocation()
    self.locationUpdateCancellable?.cancel()
}

Enhanced Button Actions

We also improved the action buttons within the app. Each button has a role-based action which uses the camera to scan VIN numbers and license plates, and then sends the updated status of the vehicle to the backend.

Here is an anonymized example of an action button within the ParkingView:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private func actionButton(title: String, iconName: String, statusText: String, action: @escaping () -> Void) -> some View {
    Button(action: {
        AVCaptureDevice.requestAccess(for: .video) { granted in
            if granted {
                action()
                self.vehicleStatus = statusText
                self.isShowingScannerModal = true 
            } else {
                os_log("Camera access not granted", log: errorLog, type: .error)
            }
        }
    }) {


        HStack {
            Image(systemName: "qrcode")
            Text(title)
            Image(systemName: iconName)
        }
    }
    .padding()
    .background(Color.blue) 
    .foregroundColor(.white)
    .cornerRadius(10)
}

Conclusion

With these changes, our location tracking is now more accurate and efficient. The use of Combine allowed us to reactively update our app’s state based on the user’s location, and SwiftUI made it easy to manage the lifecycle of these updates. Additionally, the role-based actions provide a user-friendly way to update vehicle statuses within the parking management app.

[YouTube Video Placeholder]

In our next post, we’ll explore further improvements we can make to our parking management app using more advanced SwiftUI and Combine techniques. Stay tuned!

1
tags: [SwiftUI, Combine, iOS, Location Services]
Dieser Eintrag ist vom Autor unter CC BY 4.0 lizensiert.