Skip to content

Commit 75c8753

Browse files
committed
fix(ios): bound location permission wait
1 parent fdc9aa8 commit 75c8753

2 files changed

Lines changed: 30 additions & 7 deletions

File tree

apps/ios/Sources/Location/LocationService.swift

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ final class LocationService: NSObject, CLLocationManagerDelegate, LocationServic
8989
Task { @MainActor in
9090
let clock = ContinuousClock()
9191
let noPromptDeadline = clock.now.advanced(by: .milliseconds(1500))
92+
var activeUndeterminedDeadline: ContinuousClock.Instant?
9293
var observedPrompt = UIApplication.shared.applicationState != .active
9394
// A slow system prompt must not trigger the no-callback fallback. Once iOS makes
9495
// the app inactive, wait until the user dismisses the prompt and the app returns.
@@ -97,32 +98,50 @@ final class LocationService: NSObject, CLLocationManagerDelegate, LocationServic
9798
let applicationIsActive = UIApplication.shared.applicationState == .active
9899
if !applicationIsActive {
99100
observedPrompt = true
101+
activeUndeterminedDeadline = nil
100102
continue
101103
}
102104
guard observedPrompt || clock.now >= noPromptDeadline else { continue }
103105
let status = self.manager.authorizationStatus
104-
guard Self.shouldCompleteAuthorizationWait(
106+
if Self.shouldCompleteAuthorizationWait(
105107
status: status,
106108
requiresDeterminedStatus: requiresDeterminedStatus)
107-
else { continue }
108-
self.finishAuthorizationWait(waitID: waitID, status: status)
109+
{
110+
self.finishAuthorizationWait(waitID: waitID, status: status)
111+
continue
112+
}
113+
if observedPrompt, activeUndeterminedDeadline == nil {
114+
activeUndeterminedDeadline = clock.now.advanced(by: .milliseconds(1500))
115+
}
116+
let fallbackDeadline = activeUndeterminedDeadline ?? noPromptDeadline
117+
guard clock.now >= fallbackDeadline else { continue }
118+
self.finishAuthorizationWait(
119+
waitID: waitID,
120+
status: status,
121+
allowUndeterminedFallback: true)
109122
}
110123
}
111124
}
112125
}
113126

114127
nonisolated static func shouldCompleteAuthorizationWait(
115128
status: CLAuthorizationStatus,
116-
requiresDeterminedStatus: Bool) -> Bool
129+
requiresDeterminedStatus: Bool,
130+
allowUndeterminedFallback: Bool = false) -> Bool
117131
{
118-
!requiresDeterminedStatus || status != .notDetermined
132+
allowUndeterminedFallback || !requiresDeterminedStatus || status != .notDetermined
119133
}
120134

121-
private func finishAuthorizationWait(waitID: UUID, status: CLAuthorizationStatus) {
135+
private func finishAuthorizationWait(
136+
waitID: UUID,
137+
status: CLAuthorizationStatus,
138+
allowUndeterminedFallback: Bool = false)
139+
{
122140
guard self.authWaitID == waitID, let cont = self.authContinuation else { return }
123141
guard Self.shouldCompleteAuthorizationWait(
124142
status: status,
125-
requiresDeterminedStatus: self.authWaitRequiresDeterminedStatus)
143+
requiresDeterminedStatus: self.authWaitRequiresDeterminedStatus,
144+
allowUndeterminedFallback: allowUndeterminedFallback)
126145
else { return }
127146
self.authWaitID = nil
128147
self.authWaitRequiresDeterminedStatus = false

apps/ios/Tests/LocationPermissionSummaryTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ import Testing
101101
#expect(LocationService.shouldCompleteAuthorizationWait(
102102
status: .notDetermined,
103103
requiresDeterminedStatus: false))
104+
#expect(LocationService.shouldCompleteAuthorizationWait(
105+
status: .notDetermined,
106+
requiresDeterminedStatus: true,
107+
allowUndeterminedFallback: true))
104108
}
105109

106110
@MainActor @Test func `off mode stops significant location monitoring`() async {

0 commit comments

Comments
 (0)