@@ -24,7 +24,7 @@ import Foundation
24
24
import CoreLocation
25
25
26
26
public typealias AuthotizationContinuation = CheckedContinuation < CLAuthorizationStatus , Never >
27
- public typealias AccuracyAuthorizationContinuation = CheckedContinuation < CLAccuracyAuthorization ? , Never >
27
+ public typealias AccuracyAuthorizationContinuation = CheckedContinuation < CLAccuracyAuthorization ? , Error >
28
28
public typealias LocationOnceContinuation = CheckedContinuation < LocationUpdateEvent ? , Error >
29
29
public typealias LocationEnabledStream = AsyncStream < LocationEnabledEvent >
30
30
public typealias LocationStream = AsyncStream < LocationUpdateEvent >
@@ -59,8 +59,7 @@ public final class AsyncLocationManager {
59
59
// Though undocumented, `locationServicesEnabled()` must not be called from the main thread. Otherwise,
60
60
// we get a runtime warning "This method can cause UI unresponsiveness if invoked on the main thread"
61
61
// Therefore, we use `Task.detached` to ensure we're off the main thread.
62
- // Also, we force `try` as we expect no exceptions to be thrown from `locationServicesEnabled()`
63
- try ! await Task . detached { CLLocationManager . locationServicesEnabled ( ) } . value
62
+ await Task . detached { CLLocationManager . locationServicesEnabled ( ) } . value
64
63
}
65
64
66
65
@available ( watchOS 6 . 0 , * )
@@ -133,7 +132,7 @@ public final class AsyncLocationManager {
133
132
@available ( * , deprecated, message: " Use new function requestPermission(with:) " )
134
133
@available ( watchOS 7 . 0 , * )
135
134
public func requestAuthorizationWhenInUse( ) async -> CLAuthorizationStatus {
136
- let authorizationPerformer = RequestAuthorizationPerformer ( )
135
+ let authorizationPerformer = RequestAuthorizationPerformer ( currentStatus : getAuthorizationStatus ( ) )
137
136
return await withTaskCancellationHandler ( operation: {
138
137
await withCheckedContinuation { continuation in
139
138
let authorizationStatus = getAuthorizationStatus ( )
@@ -155,7 +154,7 @@ public final class AsyncLocationManager {
155
154
@available ( watchOS 7 . 0 , * )
156
155
@available ( iOS 14 , * )
157
156
public func requestAuthorizationAlways( ) async -> CLAuthorizationStatus {
158
- let authorizationPerformer = RequestAuthorizationPerformer ( )
157
+ let authorizationPerformer = RequestAuthorizationPerformer ( currentStatus : getAuthorizationStatus ( ) )
159
158
return await withTaskCancellationHandler ( operation: {
160
159
await withCheckedContinuation { continuation in
161
160
#if os(macOS)
@@ -197,8 +196,8 @@ public final class AsyncLocationManager {
197
196
}
198
197
199
198
@available ( iOS 14 , watchOS 7 , * )
200
- public func requestTemporaryFullAccuracyAuthorization( purposeKey: String ) async -> CLAccuracyAuthorization ? {
201
- await locationPermissionTemporaryFullAccuracy ( purposeKey: purposeKey)
199
+ public func requestTemporaryFullAccuracyAuthorization( purposeKey: String ) async throws -> CLAccuracyAuthorization ? {
200
+ try await locationPermissionTemporaryFullAccuracy ( purposeKey: purposeKey)
202
201
}
203
202
204
203
public func startUpdatingLocation( ) async -> LocationStream {
@@ -316,7 +315,7 @@ public final class AsyncLocationManager {
316
315
317
316
extension AsyncLocationManager {
318
317
private func locationPermissionWhenInUse( ) async -> CLAuthorizationStatus {
319
- let authorizationPerformer = RequestAuthorizationPerformer ( )
318
+ let authorizationPerformer = RequestAuthorizationPerformer ( currentStatus : getAuthorizationStatus ( ) )
320
319
return await withTaskCancellationHandler ( operation: {
321
320
await withCheckedContinuation { continuation in
322
321
let authorizationStatus = getAuthorizationStatus ( )
@@ -334,7 +333,7 @@ extension AsyncLocationManager {
334
333
}
335
334
336
335
private func locationPermissionAlways( ) async -> CLAuthorizationStatus {
337
- let authorizationPerformer = RequestAuthorizationPerformer ( )
336
+ let authorizationPerformer = RequestAuthorizationPerformer ( currentStatus : getAuthorizationStatus ( ) )
338
337
return await withTaskCancellationHandler ( operation: {
339
338
await withCheckedContinuation { continuation in
340
339
#if os(macOS)
@@ -361,24 +360,61 @@ extension AsyncLocationManager {
361
360
}
362
361
363
362
@available ( iOS 14 , watchOS 7 , * )
364
- private func locationPermissionTemporaryFullAccuracy( purposeKey: String ) async -> CLAccuracyAuthorization ? {
363
+ private func locationPermissionTemporaryFullAccuracy( purposeKey: String ) async throws -> CLAccuracyAuthorization ? {
365
364
let authorizationPerformer = RequestAccuracyAuthorizationPerformer ( )
366
- return await withTaskCancellationHandler ( operation: {
367
- await withCheckedContinuation { continuation in
368
- if locationManager. authorizationStatus != . notDetermined && locationManager. accuracyAuthorization == . fullAccuracy {
369
- continuation. resume ( with: . success( locationManager. accuracyAuthorization) )
370
- } else if locationManager. authorizationStatus == . notDetermined {
365
+ return try await withTaskCancellationHandler ( operation: {
366
+ try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < CLAccuracyAuthorization ? , Error > ) in
367
+ if locationManager. authorizationStatus == . notDetermined {
371
368
continuation. resume ( with: . success( nil ) )
369
+ } else if locationManager. accuracyAuthorization == . fullAccuracy {
370
+ continuation. resume ( with: . success( locationManager. accuracyAuthorization) )
372
371
} else if !CLLocationManager. locationServicesEnabled ( ) {
373
372
continuation. resume ( with: . success( nil ) )
374
373
} else {
375
374
authorizationPerformer. linkContinuation ( continuation)
376
375
proxyDelegate. addPerformer ( authorizationPerformer)
377
- locationManager. requestTemporaryFullAccuracyAuthorization ( withPurposeKey: purposeKey)
376
+ locationManager. requestTemporaryFullAccuracyAuthorization ( withPurposeKey: purposeKey) { error in
377
+ if let error {
378
+ continuation. resume ( with: . failure( error) )
379
+ return
380
+ }
381
+
382
+ // If the user chooses reduced accuracy, the didChangeAuthorization delegate method
383
+ // will not called. So we must emulate that here.
384
+ if self . locationManager. accuracyAuthorization == . reducedAccuracy {
385
+ self . proxyDelegate. eventForMethodInvoked (
386
+ . didChangeAccuracyAuthorization( authorization: self . locationManager. accuracyAuthorization)
387
+ )
388
+ }
389
+ }
378
390
}
379
391
}
380
392
} , onCancel: {
381
393
proxyDelegate. cancel ( for: authorizationPerformer. uniqueIdentifier)
382
394
} )
383
395
}
384
396
}
397
+
398
+ extension CLAuthorizationStatus : CustomStringConvertible {
399
+ public var description : String {
400
+ switch self {
401
+ case . notDetermined: return " .notDetermined "
402
+ case . restricted: return " .restricted "
403
+ case . denied: return " .denied "
404
+ case . authorizedWhenInUse: return " .authorizedWhenInUse "
405
+ case . authorizedAlways: return " .authorisedAlways "
406
+ @unknown default : return " unknown \( rawValue) "
407
+ }
408
+ }
409
+ }
410
+
411
+ extension CLAccuracyAuthorization : CustomStringConvertible {
412
+ public var description : String {
413
+ switch self {
414
+ case . fullAccuracy: return " .fullAccuracy "
415
+ case . reducedAccuracy: return " .reducedAccuracy "
416
+ @unknown default : return " unknown \( rawValue) "
417
+ }
418
+ }
419
+ }
420
+
0 commit comments