diff --git a/apps/ios/Sources/Gateway/GatewayConnectionController.swift b/apps/ios/Sources/Gateway/GatewayConnectionController.swift index dc94f3d0797..b27589f6279 100644 --- a/apps/ios/Sources/Gateway/GatewayConnectionController.swift +++ b/apps/ios/Sources/Gateway/GatewayConnectionController.swift @@ -37,6 +37,14 @@ final class GatewayConnectionController { private(set) var pendingTrustPrompt: TrustPrompt? private let discovery = GatewayDiscoveryModel() + /// Reused instance — avoids creating CLLocationManager on the main thread + /// each time currentPermissions() is called, which triggers a UI-thread warning. + private let locationManager = CLLocationManager() + /// Cached off the main thread to avoid the UI-responsiveness warning from + /// calling SFSpeechRecognizer.authorizationStatus() on the main actor. + private nonisolated var speechRecognitionStatus: SFSpeechRecognizerAuthorizationStatus { + SFSpeechRecognizer.authorizationStatus() + } private weak var appModel: NodeAppModel? private var didAutoConnect = false private var pendingServiceResolvers: [String: GatewayServiceResolver] = [:] @@ -891,9 +899,9 @@ final class GatewayConnectionController { var permissions: [String: Bool] = [:] permissions["camera"] = AVCaptureDevice.authorizationStatus(for: .video) == .authorized permissions["microphone"] = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized - permissions["speechRecognition"] = SFSpeechRecognizer.authorizationStatus() == .authorized + permissions["speechRecognition"] = self.speechRecognitionStatus == .authorized permissions["location"] = Self.isLocationAuthorized( - status: CLLocationManager().authorizationStatus) + status: self.locationManager.authorizationStatus) && CLLocationManager.locationServicesEnabled() permissions["screenRecording"] = RPScreenRecorder.shared().isAvailable