

Discover more from Blinking Cursor ▌ by daniele margutti
SwiftLocation moves to 6.0
With the introduction of the new Swift Concurrency Manifesto, I've taken on the delightful task of revisiting an old-but-awesome library I developed several years ago.
Even old projects need attention; I developed SwiftLocation years ago to enhance the management of CLLocationManager APIs without depending on the delegate pattern.
Back then, the best approach I could take was to employ callback/completion handlers.
Later it’s evolved into the standard practice, streamlining the verbosity of Objective-C initially, and later in Swift, preceding the arrival of async-await (initially using a naive implementation of JS promises, and eventually a better native implementation).
As you can imagine, the new milestone involves a complete rewrite of the old approach while retaining several ideas from the previous infrastructure.
For instance, the concept of managing units of work remains, acting as a bridge between delegate and async stream instances.
However, to simplify the library overall, I've made changes such as moving away from a singleton approach to a per-instance usage.
Using this new version is quite straightforward.
With a newly instantiated Location object, you can obtain the user's location in just two lines of code:
try await location.requestPermission(.whenInUse)
let userLocation = try await location.requestLocation()
Most of the functions return an AsyncStream, an asynchronous sequence generated from a closure that invokes a continuation to generate new elements.
You can observe the authorization status changes with a simple 'for' loop:
for await event in await location.startMonitoringAuthorization() {
print("Authorization status did change: \(event.authorizationStatus)")
}
Each method generates a new type of event (which is an enum) that you can observe and stop when you're done.
For example, this code snippet monitors new locations as they occur:
for await event in try await location.startMonitoringLocations() {
switch event {
case .didPaused:
// location updates paused
case .didResume:
// location updates resumed
case let .didUpdateLocations(locations):
// new locations received
case let .didFailed(error):
// an error has occurred
}
}
SwiftLocation 6 uses SPM as distribution channel.
More good news pertains to compatibility: it's now compatible with all Apple platforms - iOS primarily and foremost, but also watchOS, tvOS, and macOS.
The entire library is covered by a comprehensive unit testing suite.
The LocationManager itself is supported by a protocol, allowing you to provide your implementation and simplify testing, even with Core Location services.
Some services previously available in version 5.x, such as Autocomplete, Geocoder, and IP Location, are not yet accessible. However, I'll strive to port them into a separate package to keep the entire library lightweight for implementation.
As usual, the entire work is licensed under MIT.
A friendly reminder: if you plan to use it or find my work beneficial in your everyday life as a developer, consider becoming a sponsor or making a one-time donation. Your support will assist me in continuously maintaining this software.