Skip to content
Open
2 changes: 1 addition & 1 deletion Sources/SwiftLocation/Async Tasks/AnyTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ public extension AnyTask {

public protocol CancellableTask: AnyObject {

func cancel(task: any AnyTask)
func cancel(task: any AnyTask, completion: (([AnyTask]) -> Void)?)

}
4 changes: 2 additions & 2 deletions Sources/SwiftLocation/Async Tasks/LocatePermission.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ extension Tasks {
switch event {
case .didChangeAuthorization(let authorization):
guard let continuation = continuation else {
cancellable?.cancel(task: self)
cancellable?.cancel(task: self, completion: nil)
return
}

continuation.resume(returning: authorization)
self.continuation = nil
cancellable?.cancel(task: self)
cancellable?.cancel(task: self, completion: nil)
default:
break
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftLocation/Async Tasks/SingleUpdateLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ extension Tasks {

continuation?.resume(returning: .didUpdateLocations(filteredLocations))
continuation = nil
cancellable?.cancel(task: self)
cancellable?.cancel(task: self, completion: nil)
case let .didFailWithError(error):
continuation?.resume(returning: .didFailed(error))
continuation = nil
cancellable?.cancel(task: self)
cancellable?.cancel(task: self, completion: nil)
default:
break
}
Expand Down
24 changes: 17 additions & 7 deletions Sources/SwiftLocation/Location Managers/LocationAsyncBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class LocationAsyncBridge: CancellableTask {

// MARK: - Private Properties

private var tasks = [AnyTask]()
private var tasks = SynchronizedArray<AnyTask>()
weak var location: Location?

// MARK: - Internal function
Expand All @@ -49,21 +49,23 @@ final class LocationAsyncBridge: CancellableTask {
/// Cancel the execution of a task.
///
/// - Parameter task: task to cancel.
func cancel(task: AnyTask) {
cancel(taskUUID: task.uuid)
func cancel(task: AnyTask, completion: (([AnyTask]) -> Void)? = nil) {
cancel(taskUUID: task.uuid, completion: completion)
}

/// Cancel the execution of a task with a given unique identifier.
///
/// - Parameter uuid: unique identifier of the task to remove
private func cancel(taskUUID uuid: UUID) {
tasks.removeAll { task in
private func cancel(taskUUID uuid: UUID, completion: (([AnyTask]) -> Void)? = nil) {
tasks.removeAll(where: { task in
if task.uuid == uuid {
task.didCancelled()
return true
} else {
return false
}
}) { removedTasks in
completion?(removedTasks)
removedTasks.forEach { $0.didCancelled() }
}
}

Expand All @@ -90,7 +92,7 @@ final class LocationAsyncBridge: CancellableTask {
///
/// - Parameter event: event to dispatch.
func dispatchEvent(_ event: LocationManagerBridgeEvent) {
for task in tasks {
tasks.forEach { task in
task.receivedLocationManagerEvent(event)
}

Expand All @@ -100,4 +102,12 @@ final class LocationAsyncBridge: CancellableTask {
}
}

/// Count the task of the given class
///
/// - Parameters:
/// - type: type of `AnyTask` conform task to remove.
func count(tasksTypes type: AnyTask.Type) -> Int {
let typeToCount = ObjectIdentifier(type)
return tasks.filter({ $0.taskType == typeToCount }).count
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,25 @@ public protocol LocationManagerProtocol {
var activityType: CLActivityType { get set }
#endif

#if !os(tvOS)
var pausesLocationUpdatesAutomatically: Bool { get set }
#endif

#if !os(tvOS)
var showsBackgroundLocationIndicator: Bool { get set }
#endif

var distanceFilter: CLLocationDistance { get set }
var desiredAccuracy: CLLocationAccuracy { get set }

#if !os(tvOS)
var headingFilter: CLLocationDegrees { get set }
#endif

#if !os(tvOS)
var headingOrientation: CLDeviceOrientation { get set }
#endif

#if !os(tvOS)
var allowsBackgroundLocationUpdates: Bool { get set }
#endif
Expand Down
42 changes: 41 additions & 1 deletion Sources/SwiftLocation/Location.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ public final class Location {
}
#endif

#if !os(tvOS)
/// A Boolean value that indicates whether the location-manager object may pause location updates.
/// By defualt is `true`.
public var pausesLocationUpdatesAutomatically: Bool {
get { locationManager.pausesLocationUpdatesAutomatically }
set { locationManager.pausesLocationUpdatesAutomatically = newValue }
}
#endif

#if !os(tvOS)
/// A Boolean value that indicates whether the status bar changes its appearance when an app uses location services in the background.
/// By defualt is `false`.
public var showsBackgroundLocationIndicator: Bool {
get { locationManager.showsBackgroundLocationIndicator }
set { locationManager.showsBackgroundLocationIndicator = newValue }
}
#endif

/// The minimum distance in meters the device must move horizontally before an update event is generated.
/// By defualt is set to `kCLDistanceFilterNone`.
///
Expand All @@ -107,6 +125,24 @@ public final class Location {
set { locationManager.distanceFilter = newValue }
}

#if !os(tvOS)
/// The minimum angular change in degrees required to generate new heading events.
/// By defualt is `1` degree.
public var headingFilter: CLLocationDegrees {
get { locationManager.headingFilter }
set { locationManager.headingFilter = newValue }
}
#endif

#if !os(tvOS)
/// The device orientation to use when computing heading values.
/// By defualt is `CLDeviceOrientation.portrait`.
public var headingOrientation: CLDeviceOrientation {
get { locationManager.headingOrientation }
set { locationManager.headingOrientation = newValue }
}
#endif

/// Indicates whether the app receives location updates when running in the background.
/// By default is `false`.
///
Expand Down Expand Up @@ -272,7 +308,11 @@ public final class Location {

locationManager.startUpdatingLocation()
stream.onTermination = { @Sendable _ in
self.asyncBridge.cancel(task: task)
self.asyncBridge.cancel(task: task) { _ in
if self.asyncBridge.count(tasksTypes: Tasks.ContinuousUpdateLocation.self) <= 0 {
self.stopUpdatingLocation()
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftLocation/Support/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ extension UserDefaults {
}

func location(forKey key: String) -> CLLocation? {
guard let locationData = UserDefaults.standard.data(forKey: key) else {
guard let locationData = data(forKey: key) else {
return nil
}

Expand Down
Loading