1
1
import Foundation
2
2
import CoreLocation
3
3
4
- public protocol SpeedManagerTrigger {
5
- func startUpdatingSpeed( )
6
- func startMonitoringSpeed( )
7
- }
8
-
9
- public class SpeedManager : NSObject , ObservableObject , SpeedManagerTrigger {
4
+ /// A class that manages the monitoring and updating of speed using CoreLocation.
5
+ public class SpeedManager : NSObject , ObservableObject , SpeedManagerTrigger {
6
+
7
+ // MARK: - Properties
10
8
11
- // MARK: Private
9
+ /// The CoreLocation manager used to get location updates.
12
10
private let locationManager = CLLocationManager ( )
11
+
12
+ /// The unit of speed to be used.
13
13
private var speedUnit : SpeedManagerUnit
14
+
15
+ /// The trigger for starting speed updates.
14
16
private var trigger : SpeedManagerTrigger ?
15
- private var allowsBackgroundLocationUpdates : Bool = false
16
-
17
- // MARK: Public
18
- public var delegate : SpeedManagerDelegate ?
19
-
20
- @Published public var authorizationStatus : SpeedManagerAuthorizationStatus = . notDetermined
21
- @Published public var speed : Double = 0
22
- @Published public var speedAccuracy : Double = 0
17
+
18
+ /// Indicates whether background location updates are allowed.
19
+ private var allowsBackgroundLocationUpdates : Bool
20
+
21
+ /// The delegate to receive updates from the SpeedManager.
22
+ public weak var delegate : SpeedManagerDelegate ?
23
+
24
+ /// The current authorization status for location services.
25
+ @Published public private( set) var authorizationStatus : SpeedManagerAuthorizationStatus = . notDetermined {
26
+ didSet {
27
+ DispatchQueue . main. async {
28
+ self . delegate? . speedManager ( self , didUpdateAuthorizationStatus: self . authorizationStatus)
29
+ }
30
+ }
31
+ }
32
+
33
+ /// The current speed.
34
+ @Published public var speed : Double = 0 {
35
+ didSet {
36
+ DispatchQueue . main. async {
37
+ self . delegate? . speedManager ( self , didUpdateSpeed: self . speed, speedAccuracy: self . speedAccuracy)
38
+ }
39
+ }
40
+ }
41
+
42
+ /// The accuracy of the current speed.
43
+ @Published public private( set) var speedAccuracy : Double = 0
23
44
24
- private var isRequestingLocation = false
45
+ // MARK: - Initializer
25
46
26
- public init ( _ speedUnit: SpeedManagerUnit ,
47
+ /// Initializes a new SpeedManager.
48
+ /// - Parameters:
49
+ /// - speedUnit: The unit of speed measurement.
50
+ /// - trigger: An optional trigger for starting speed updates. If nil, the SpeedManager will trigger itself.
51
+ /// - allowsBackgroundLocationUpdates: A Boolean value indicating whether background location updates are allowed.
52
+ public init ( speedUnit: SpeedManagerUnit ,
27
53
trigger: SpeedManagerTrigger ? = nil ,
28
54
allowsBackgroundLocationUpdates: Bool = false ) {
29
55
30
56
self . speedUnit = speedUnit
31
- self . delegate = nil
32
57
self . allowsBackgroundLocationUpdates = allowsBackgroundLocationUpdates
33
58
super. init ( )
34
59
self . trigger = trigger ?? self
@@ -40,63 +65,73 @@ public class SpeedManager : NSObject, ObservableObject, SpeedManagerTrigger {
40
65
self . locationManager. requestAlwaysAuthorization ( )
41
66
}
42
67
68
+ // MARK: - Public Methods
69
+
70
+ /// Starts updating the speed.
43
71
public func startUpdatingSpeed( ) {
44
72
trigger? . startMonitoringSpeed ( )
45
73
}
46
74
75
+ /// Starts monitoring the speed.
47
76
public func startMonitoringSpeed( ) {
48
-
49
- switch self . authorizationStatus {
50
-
77
+ switch authorizationStatus {
51
78
case . authorized:
52
- if allowsBackgroundLocationUpdates { self . locationManager. allowsBackgroundLocationUpdates = true
79
+ if allowsBackgroundLocationUpdates {
80
+ locationManager. allowsBackgroundLocationUpdates = true
53
81
}
54
- self . locationManager. startUpdatingLocation ( )
82
+ locationManager. startUpdatingLocation ( )
55
83
case . notDetermined:
56
- self . locationManager. requestAlwaysAuthorization ( )
84
+ locationManager. requestAlwaysAuthorization ( )
57
85
case . denied:
58
- fatalError ( " No location services available " )
86
+ DispatchQueue . main. async {
87
+ self . delegate? . speedManagerDidFailWithLocationServicesUnavailable ( self )
88
+ }
59
89
}
60
90
}
61
91
}
62
92
63
- // MARK: CLLocationManagerDelegate methods
93
+ // MARK: - CLLocationManagerDelegate
64
94
65
95
extension SpeedManager : CLLocationManagerDelegate {
66
96
97
+ /// Called when the authorization status changes.
98
+ /// - Parameter manager: The location manager reporting the change.
67
99
public func locationManagerDidChangeAuthorization( _ manager: CLLocationManager ) {
68
100
switch manager. authorizationStatus {
69
-
70
- case . authorizedWhenInUse,
71
- . authorizedAlways:
101
+ case . authorizedWhenInUse, . authorizedAlways:
72
102
authorizationStatus = . authorized
73
- locationManager. requestLocation ( )
74
- break
75
-
103
+ locationManager. requestLocation ( )
76
104
case . notDetermined:
77
105
authorizationStatus = . notDetermined
78
106
manager. requestWhenInUseAuthorization ( )
79
- break
80
-
81
107
default :
82
108
authorizationStatus = . denied
83
109
}
84
110
85
- self . startMonitoringSpeed ( )
111
+ startMonitoringSpeed ( )
86
112
}
87
113
114
+ /// Called when new location data is available.
115
+ /// - Parameters:
116
+ /// - manager: The location manager providing the data.
117
+ /// - locations: An array of new location data objects.
88
118
public func locationManager( _ manager: CLLocationManager , didUpdateLocations locations: [ CLLocation ] ) {
119
+ guard let lastLocation = locations. last else { return }
89
120
90
- let currentSpeed = locations . last ? . speed ?? 0
121
+ let currentSpeed = lastLocation . speed
91
122
speed = currentSpeed >= 0 ? currentSpeed * speedUnit. rawValue : . nan
92
- speedAccuracy = locations . last ? . speedAccuracy ?? . nan
123
+ speedAccuracy = lastLocation . speedAccuracy
93
124
94
- self . delegate? . speedManager ( self , didUpdateSpeed: speed, speedAccuracy: speedAccuracy)
95
-
96
- self . locationManager. requestLocation ( )
125
+ locationManager. requestLocation ( )
97
126
}
98
127
128
+ /// Called when the location manager encounters an error.
129
+ /// - Parameters:
130
+ /// - manager: The location manager reporting the error.
131
+ /// - error: The error encountered by the location manager.
99
132
public func locationManager( _ manager: CLLocationManager , didFailWithError error: Error ) {
100
- self . delegate? . speedManager ( self , didFailWithError: error)
133
+ DispatchQueue . main. async {
134
+ self . delegate? . speedManager ( self , didFailWithError: error)
135
+ }
101
136
}
102
137
}
0 commit comments