@@ -97,7 +97,7 @@ extension CLLocationManager {
97
97
}
98
98
}
99
99
100
- private class LocationManager : CLLocationManager , CLLocationManagerDelegate {
100
+ private class LocationManager : CLLocationManager , CLLocationManagerDelegate , CancellableTask {
101
101
let ( promise, seal) = Promise< [ CLLocation] > . pending( )
102
102
let satisfyingBlock : ( ( CLLocation ) -> Bool ) ?
103
103
@@ -120,6 +120,9 @@ private class LocationManager: CLLocationManager, CLLocationManagerDelegate {
120
120
satisfyingBlock = block
121
121
super. init ( )
122
122
delegate = self
123
+
124
+ promise. setCancellableTask ( self , reject: seal. reject)
125
+
123
126
#if !os(tvOS)
124
127
startUpdatingLocation ( )
125
128
#else
@@ -138,6 +141,13 @@ private class LocationManager: CLLocationManager, CLLocationManagerDelegate {
138
141
seal. reject ( error)
139
142
}
140
143
}
144
+
145
+ func cancel( ) {
146
+ self . stopUpdatingLocation ( )
147
+ isCancelled = true
148
+ }
149
+
150
+ var isCancelled = false
141
151
}
142
152
143
153
@@ -203,14 +213,16 @@ extension CLLocationManager {
203
213
}
204
214
205
215
@available ( iOS 8 , * )
206
- private class AuthorizationCatcher : CLLocationManager , CLLocationManagerDelegate {
216
+ private class AuthorizationCatcher : CLLocationManager , CLLocationManagerDelegate , CancellableTask {
207
217
let ( promise, fulfill) = Guarantee< CLAuthorizationStatus> . pending( )
208
218
var retainCycle : AuthorizationCatcher ?
209
219
let initialAuthorizationState = CLLocationManager . authorizationStatus ( )
210
220
211
221
init ( type: PMKCLAuthorizationType ) {
212
222
super. init ( )
213
223
224
+ promise. setCancellableTask ( self )
225
+
214
226
func ask( type: PMKCLAuthorizationType ) {
215
227
delegate = self
216
228
retainCycle = self
@@ -263,6 +275,13 @@ private class AuthorizationCatcher: CLLocationManager, CLLocationManagerDelegate
263
275
fulfill ( status)
264
276
}
265
277
}
278
+
279
+ func cancel( ) {
280
+ self . retainCycle = nil
281
+ isCancelled = true
282
+ }
283
+
284
+ var isCancelled = false
266
285
}
267
286
268
287
#endif
@@ -306,7 +325,7 @@ private enum PMKCLAuthorizationType {
306
325
case whenInUse
307
326
}
308
327
309
- //////////////////////////////////////////////////////////// Cancellation
328
+ //////////////////////////////////////////////////////////// Cancellable wrappers
310
329
311
330
extension CLLocationManager {
312
331
/**
@@ -325,105 +344,10 @@ extension CLLocationManager {
325
344
last location.
326
345
*/
327
346
public class func cancellableRequestLocation( authorizationType: RequestAuthorizationType = . automatic, satisfying block: ( ( CLLocation ) -> Bool ) ? = nil ) -> CancellablePromise < [ CLLocation ] > {
328
-
329
- func std( ) -> CancellablePromise < [ CLLocation ] > {
330
- return CancellableLocationManager ( satisfying: block) . promise
331
- }
332
-
333
- func auth( ) -> CancellablePromise < Void > {
334
- #if os(macOS)
335
- return CancellablePromise { seal in seal. fulfill ( ( ) ) }
336
- #else
337
- func auth( type: PMKCLAuthorizationType ) -> CancellablePromise < Void > {
338
- return CancellableAuthorizationCatcher ( type: type) . promise. done ( on: nil ) {
339
- switch $0 {
340
- case . restricted, . denied:
341
- throw PMKError . notAuthorized
342
- default :
343
- break
344
- }
345
- }
346
- }
347
-
348
- switch authorizationType {
349
- case . automatic:
350
- switch Bundle . main. permissionType {
351
- case . always, . both:
352
- return auth ( type: . always)
353
- case . whenInUse:
354
- return auth ( type: . whenInUse)
355
- }
356
- case . whenInUse:
357
- return auth ( type: . whenInUse)
358
- case . always:
359
- return auth ( type: . always)
360
- }
361
- #endif
362
- }
363
-
364
- switch CLLocationManager . authorizationStatus ( ) {
365
- case . authorizedAlways, . authorizedWhenInUse:
366
- return std ( )
367
- case . notDetermined:
368
- return auth ( ) . then ( std)
369
- case . denied, . restricted:
370
- return CancellablePromise ( error: PMKError . notAuthorized)
371
- }
347
+ return cancellable ( requestLocation ( authorizationType: authorizationType, satisfying: block) )
372
348
}
373
349
}
374
350
375
- private class CancellableLocationManager : CLLocationManager , CLLocationManagerDelegate , CancellableTask {
376
- let ( promise, seal) = CancellablePromise< [ CLLocation] > . pending( )
377
- let satisfyingBlock : ( ( CLLocation ) -> Bool ) ?
378
-
379
- init ( satisfying block: ( ( CLLocation ) -> Bool ) ? = nil ) {
380
- satisfyingBlock = block
381
- super. init ( )
382
- delegate = self
383
-
384
- promise. appendCancellableTask ( task: self , reject: seal. reject)
385
-
386
- #if !os(tvOS)
387
- startUpdatingLocation ( )
388
- #else
389
- requestLocation ( )
390
- #endif
391
- _ = self . promise. ensure {
392
- self . stopUpdatingLocation ( )
393
- }
394
- }
395
-
396
- @objc fileprivate func locationManager( _ manager: CLLocationManager , didUpdateLocations locations: [ CLLocation ] ) {
397
- if let block = satisfyingBlock {
398
- let satisfiedLocations = locations. filter ( block)
399
- if !satisfiedLocations. isEmpty {
400
- seal. fulfill ( satisfiedLocations)
401
- } else {
402
- #if os(tvOS)
403
- requestLocation ( )
404
- #endif
405
- }
406
- } else {
407
- seal. fulfill ( locations)
408
- }
409
- }
410
-
411
- @objc func locationManager( _ manager: CLLocationManager , didFailWithError error: Error ) {
412
- let ( domain, code) = { ( $0. domain, $0. code) } ( error as NSError )
413
- if code == CLError . locationUnknown. rawValue && domain == kCLErrorDomain {
414
- // Apple docs say you should just ignore this error
415
- } else {
416
- seal. reject ( error)
417
- }
418
- }
419
-
420
- func cancel( ) {
421
- self . stopUpdatingLocation ( )
422
- isCancelled = true
423
- }
424
-
425
- var isCancelled = false
426
- }
427
351
428
352
#if !os(macOS)
429
353
@@ -435,127 +359,8 @@ extension CLLocationManager {
435
359
*/
436
360
@available ( iOS 8 , tvOS 9 , watchOS 2 , * )
437
361
public class func cancellableRequestAuthorization( type requestedAuthorizationType: RequestAuthorizationType = . automatic) -> CancellablePromise < CLAuthorizationStatus > {
438
-
439
- let currentStatus = CLLocationManager . authorizationStatus ( )
440
-
441
- func std( type: PMKCLAuthorizationType ) -> CancellablePromise < CLAuthorizationStatus > {
442
- if currentStatus == . notDetermined {
443
- return CancellableAuthorizationCatcher ( type: type) . promise
444
- } else {
445
- return cancellable ( Promise . value ( currentStatus) )
446
- }
447
- }
448
-
449
- switch requestedAuthorizationType {
450
- case . always:
451
- func iOS11Check( ) -> CancellablePromise < CLAuthorizationStatus > {
452
- switch currentStatus {
453
- case . notDetermined, . authorizedWhenInUse:
454
- return CancellableAuthorizationCatcher ( type: . always) . promise
455
- default :
456
- return cancellable ( Promise . value ( currentStatus) )
457
- }
458
- }
459
- #if PMKiOS11
460
- // ^^ define PMKiOS11 if you deploy against the iOS 11 SDK
461
- // otherwise the warning you get below cannot be removed
462
- return iOS11Check ( )
463
- #else
464
- if #available( iOS 11 , * ) {
465
- return iOS11Check ( )
466
- } else {
467
- return std ( type: . always)
468
- }
469
- #endif
470
-
471
- case . whenInUse:
472
- return std ( type: . whenInUse)
473
-
474
- case . automatic:
475
- if currentStatus == . notDetermined {
476
- switch Bundle . main. permissionType {
477
- case . both, . whenInUse:
478
- return CancellableAuthorizationCatcher ( type: . whenInUse) . promise
479
- case . always:
480
- return CancellableAuthorizationCatcher ( type: . always) . promise
481
- }
482
- } else {
483
- return cancellable ( Promise . value ( currentStatus) )
484
- }
485
- }
486
- }
487
- }
488
-
489
- @available ( iOS 8 , * )
490
- private class CancellableAuthorizationCatcher : CLLocationManager , CLLocationManagerDelegate , CancellableTask {
491
- let ( promise, seal) = CancellablePromise< CLAuthorizationStatus> . pending( )
492
- var retainCycle : CancellableAuthorizationCatcher ?
493
- let initialAuthorizationState = CLLocationManager . authorizationStatus ( )
494
-
495
- init ( type: PMKCLAuthorizationType ) {
496
- super. init ( )
497
-
498
- promise. appendCancellableTask ( task: self , reject: seal. reject)
499
-
500
- func ask( type: PMKCLAuthorizationType ) {
501
- delegate = self
502
- retainCycle = self
503
-
504
- switch type {
505
- case . always:
506
- #if os(tvOS)
507
- fallthrough
508
- #else
509
- requestAlwaysAuthorization ( )
510
- #endif
511
- case . whenInUse:
512
- requestWhenInUseAuthorization ( )
513
- }
514
-
515
- _ = promise. done { _ in
516
- self . retainCycle = nil
517
- }
518
- }
519
-
520
- func iOS11Check( ) {
521
- switch ( initialAuthorizationState, type) {
522
- case ( . notDetermined, . always) , ( . authorizedWhenInUse, . always) , ( . notDetermined, . whenInUse) :
523
- ask ( type: type)
524
- default :
525
- seal. fulfill ( initialAuthorizationState)
526
- }
527
- }
528
-
529
- #if PMKiOS11
530
- // ^^ define PMKiOS11 if you deploy against the iOS 11 SDK
531
- // otherwise the warning you get below cannot be removed
532
- iOS11Check ( )
533
- #else
534
- if #available( iOS 11 , * ) {
535
- iOS11Check ( )
536
- } else {
537
- if initialAuthorizationState == . notDetermined {
538
- ask ( type: type)
539
- } else {
540
- seal. fulfill ( initialAuthorizationState)
541
- }
542
- }
543
- #endif
362
+ return cancellable ( requestAuthorization ( type: requestedAuthorizationType) )
544
363
}
545
-
546
- @objc fileprivate func locationManager( _ manager: CLLocationManager , didChangeAuthorization status: CLAuthorizationStatus ) {
547
- // `didChange` is a lie; it fires this immediately with the current status.
548
- if status != initialAuthorizationState {
549
- seal. fulfill ( status)
550
- }
551
- }
552
-
553
- func cancel( ) {
554
- self . retainCycle = nil
555
- isCancelled = true
556
- }
557
-
558
- var isCancelled = false
559
364
}
560
365
561
366
#endif
0 commit comments