스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
위치 인증 기능의 새로운 사항
위치 인증이 새롭게 향상되었습니다. 현재 인증 수준을 확인하는 데 활용할 수 있는 새로운 기술 및 제안 사항과, 인증 요청을 위한 새로운 상호작용에 대해 알아보세요.
챕터
- 0:00 - Introduction
- 1:52 - Authorization goals
- 9:25 - Session lifecycle
- 13:29 - Diagnostic properties
리소스
-
다운로드
안녕하세요! 저는 Core Location 팀 엔지니어 Adam Driscoll입니다 이 영상에서는 위치 승인의 새로운 기능을 살펴보겠습니다 지금 저를 보고 계시다면 아마 Core Location을 통해 이 지도 같은 앱이 여러분 위치를 파악한다는 것을 아실 겁니다 여러분의 앱도 마찬가지입니다 주변에서 일어나는 흥미로운 일을 사람들에게 보여 주거나 Core Location API를 사용해서 전시회장의 동선을 안내합니다 작년에 제 동료 Siraj와 Nivash가 API 객체 두 개를 소개했습니다 CLLocationUpdate와 CLMonitor였죠 각 API는 AsyncSequence 인터페이스를 나타냅니다 기기가 움직일 때마다 위도와 경도 업데이트를 쉽게 가져오거나 설명하는 공간 조건이 만족되거나 만족되지 않을 때 상태 변경 이벤트를 가져옵니다
두 API를 사용하려면 먼저 앱의 각 사용자로부터 권한을 받아야 합니다 Core Location 승인 API로 권한을 받으면 됩니다 하지만 Swift에서는 승인받기가 상당히 복잡할 수 있습니다 오늘은 이 모든 코드를 이렇게 축소하도록 도와 드리겠습니다 그리고 그 과정에서 코드를 더 강력하게 만들 것입니다 핵심은 CLServiceSession과 진단 속성의 새로운 시스템인데 세 가지 주제를 통해 모두 말씀드리겠습니다 첫째, CLServiceSession은 새로운 선언적 방법인데 Core Location에 승인 목표와 함께 앱이 실행 중일 때 각 기능에 필요한 사항을 말해 주는 것입니다
그런 다음 이것이 세션 객체이므로 언제 만들어야 하는지 조금 더 자세히 살펴보고 앱이 정지되거나 종료되면 어떻게 되는지도 살펴보겠습니다
마지막으로, 진단 속성의 새로운 시스템에 대해 알려 드리겠습니다 진단 속성은 앱이 현재 승인과 다른 Core Location API 객체의 기능을 맥락적으로 완전히 이해할 수 있게 해 줍니다
첫 번째는 목표입니다 절차적 모델에서 선언적 모델로 옮겨서 위치 승인과 상호작용하는 것입니다 설정에서 앱의 LocationMonitorSample에 대한 승인은 이런 모습입니다 정확한 위치 토글과 위 옵션 사이에서 다이어그램을 만들고 조금 단순화한다면 이런 모습일 것입니다
모든 앱은 NotDetermined에서 시작합니다 그런 다음 사람들이 앱을 오른쪽 상태 중 하나로 승인하면 전체 정확도를 제공하도록 선택하거나 대략적인 액세스 권한을 선택할 수 있습니다
이 프로세스를 시작하려면 전에는 승인을 요청해야 했습니다 CLLocationManager와 requestWhenInUseAuthorization과 같은 메서드를 이용해서요 그러면 NotDetermined에서 WhenInUse 또는 Denial로 바뀝니다 이렇게 물어보는 것도 명확한 방법이지만 사용자가 보통은 대략적인 위치만 필요한 방식으로 앱을 사용해서 그렇게 승인할 수도 있습니다 그러다가 언젠가는 경로의 지점마다 길안내를 요청하거나 정확한 전체 위치 정보가 있어야만 작동하는 다른 기능을 사용할 수도 있습니다 그러면 requestTemporaryFullAccuracy withPurposeKey를 요청해서 사용자에게 일시적으로 승인을 확대할 기회를 줘야 하지만 임시 승인은 소멸됩니다 사용자가 애초에 임시 WhenInUse 승인을 ‘한 번 허용‘과 함께 부여한 다음 잠깐 다른 앱으로 옮겨가서 채팅을 한다면 어떻게 될까요? requestWhenInUseAuthorization을 다시 요청해야 하고 아마도 requestTemporaryFullAccuracy withPurposeKey도 요청해야겠죠 이 예에서처럼 경로의 지점마다 길안내를 하려면 전체 정확도의 WhenInUse 승인이 필요하고 이것을 승인 목표라고 한다면 이 승인 목표가 지금까지 다이어그램의 단계마다 무엇을 해야 할지 선택했습니다 올해 추가된 CLServiceSession으로 승인 목표를 직접 표현할 수 있고 유도하는 작업과 연결할 수 있습니다 예시에서 어떤 사람들은 일반적으로 대략적인 액세스 권한만 부여하고 대개는 그래도 괜찮다는 것을 알았습니다 그래서 그 선택을 존중하는 목표를 세울 수 있습니다 이것처럼 CLServiceSession을 인스턴스화하고 보유한 다음 .whenInUse를 인수로 사용하면 됩니다 Core Location은 필요에 따라 각 사람에게 요청을 제시하여 앱을 이 상태 중 하나로 바꾸려고 합니다 그러면 언젠가 사용자가 내비게이션 기능을 사용하면 fullAccuracyPurposeKey와 함께 추가 CLServiceSession을 생성하여 목표의 범위를 좁힙니다 이것을 레이어링이라고 생각하세요 앱의 일반적인 목표는 유지되지만 이제 전체 임시 정확도를 요구하는 무언가를 추가하는 것입니다 원래 세션은 그대로 유지한 채로 이것도 추가하는 것이죠 어쨌든, 이 ‘Nav‘ 키가 위치 승인 목적의 현지화 리소스에서 검색되는데 이 경우에 Core Location은 이 목적을 위해 임시 전체 정확도 승인을 요청해야 합니다 내비게이션 목적을 설명하는 문자열을 제공했습니다 전체 정확도가 지금 왜 필요한지 모두가 이해할 수 있도록 말이죠
몇 가지 중요한 사항을 말씀드렸습니다 첫째는 CLServiceSession 객체가 스크립트를 약간 바꾼다는 겁니다 Core Location에 해야 할 일이 아니라 필요한 것을 알려 줍니다 그러니까 테스트하기 힘든 문제의 클래스에 대해서는 걱정하지 않아도 되는 거죠 앱이 승인을 요청해야 하는데 잘못된 순간에 백그라운드로 전환되는 것에 대해서요 복구될까요? 네, CLServiceSession을 보유하고 있기 때문에 Core Location이 목표를 알고 다음에 목표를 달성할 수 있을 때 작업을 수행합니다
이와 관련해 CLServiceSessions를 선제적으로 사용해야 합니다 예를 들어 사용자가 전체 정확도를 특별히 요청해야 하는 기능을 이용할 때 앱이 이미 전체 정확도를 가졌어도 전체 정확도에 대한 요청을 하나 보유합니다 기능이 전체 정확도를 이렇게 명시적인 방식으로 보장하는 것을 어떻게 알 수 있을까요? 대략적인 위치로 앱을 사용해야 하는 경우를 생각해 보세요 액세스를 전부 거부할 수 있었는데 그러지 않은 겁니다 그렇다면 사용할 때 예외적으로 필요하다고 생각할 만한 특별한 상황별 기능에는 무엇이 있을까요? 그러한 기능이 사용될 때만 전체 정확도 서비스 세션을 보유하세요 마지막으로 CLServiceSessions는 불변하고 전송 가능한 객체입니다 대개 요구 사항이 변화하면 대체 대신 겹친다고 생각하세요
앱에 각기 다른 기능을 구현하는 다양한 구성 요소가 있고 관련된 승인 목표가 각기 다르며 그러한 기능이 때때로 겹치거나 중첩된다면 해당 구성 요소는 무슨 서비스 세션을 생성해야 할지 조정할 필요가 없습니다 필요한 시점에 각각 개별적으로 필요한 것을 생성할 것입니다 서비스 세션에서 겹친 각 기능이 그 자체로 충분하게 만들면 Core Location이 나머지를 처리합니다
레이어링을 이야기했는데 지금까지 새로운 CLServiceSession 구조에 대해 이야기했습니다 하지만 작년에 소개한 각 API는 liveUpdates나 이벤트 시퀀스가 반복되면 일종의 세션을 정의합니다 많은 경우에 예를 들어서 앱이 liveUpdates를 반복하는 경우 그것을 수신하는 목표가 있겠죠? Core Location은 liveUpdates 또는 Monitor.events를 반복하는 작업이 암시적으로 CLServiceSession을 보유한다고 취급할 수 있습니다 정말 멋진 기능인데 코드를 삭제하기만 하면 앱이 서비스 세션과 함께 Core Location 승인을 처리하도록 업데이트할 수 있기 때문입니다 사실 작년의 샘플 앱도 그런 방법으로 CLLocationUpdate에 대해 업데이트했습니다 이 동작은 기본적으로 활성화되어 있으니 암시적 서비스 세션을 사용해서 승인 목표를 정의할 수 있습니다 반복될 비대칭 시퀀스를 제공하는 각 최신 Core Location API는 반복되는 동안 .whenInUse의 목표 승인 상태를 나타내므로 몇 분 전에 보여드렸던 승인 처리에 유용한 코드 스니펫이 이제 더 유용해집니다 여러분 마음에 드셨으면 좋겠습니다 하지만 때때로 특히 대규모 프로젝트에서는 앱 사용자에게 승인을 요청하는 것이 적절하지 않을 때가 있습니다 그럴 때는 코드가 업데이트 반복을 완전히 못하게 하는 것이 마땅치 않을 때가 있죠 따라서 API 사용이 앱에서 승인 요청을 암시적으로 유도하지 않게 하고 싶다면 이 암시적 세션의 효과를 완전히 비활성화할 수 있습니다 앱의 Info.plist에 있는 NSLocationRequireExplicitServiceSession 키를 설정하면 되죠 그런 다음 그 명시적 세션을 다시 실행하면 됩니다 그러니까 암시적인 객체만 사용하는 대신 실제 CLServiceSession 객체를 사용하는 것이 좋은 이유는 세 가지입니다 첫째, 암시적 서비스 세션은 전체 정확도를 요구하지 않습니다 사용자가 정확도 제한을 설정하면 앱의 대부분에서 정확도 제한을 존중해야 하기 때문입니다 전체 정확도가 정말 필요할 때만 명시적으로 요청하세요 마찬가지로 Core Location은 앱에 늘 승인이 필요하다고 보지 않아요 따라서 정말 필요하다면 추가적인 액세스가 필요할 때마다 명시적 CLServiceSession와 함께 .always를 목표로 사용해야 합니다 참고로 올해부터 항상 승인은 이 중 하나를 보유할 때만 유효하며 앱이 포그라운드에 있는 경우에만 하나를 보유하기 시작할 수 있죠 잠시 후에 세션 수명 주기에서 더 자세히 이야기하겠습니다 마지막으로 info.plist 키와 조합하여 특정 시간에 명시적인 서비스 세션을 생성하거나 .none 승인 목표와 함께 Core Location이 사용자에게 앱 대신 승인을 요청하는 시점을 더 엄격하게 통제할 수 있습니다 내부적으로 Core Location을 많이 사용하는 앱과 위치 정보를 사용할지 아니면 사용하지 않을지를 사용자가 주도적으로 결정하게 하는 앱의 경우 이 방법이 가장 간단합니다 그러니까 CLServiceSessions를 사용하거나 liveUpdates와 이벤트를 반복해서 얻게 되는 암시적 세션을 활용합니다 이러한 세션은 사용자 기능에 맞춰져 있기 때문에 앱 수명 주기 전체에서 이벤트와 상호작용하게 됩니다 자세히 설명하겠습니다
사용자가 앱을 실행하고 Core Location이 필요한 기능을 사용할 부분을 예정해 놓았다고 합시다 그 기능 중 일부는 사진의 위치 정보 태그 추가처럼 수명이 짧을 수도 있지만 수명이 더 긴 기능도 있습니다 잠시 동안 MapKit을 둘러본다고 합시다 몇 기능이 중복될 수도 있습니다 예를 들면 탐색하는 동안 예상 이동 시간을 찾아볼 수 있죠 이러한 기능 세션에서 CLServiceSession 객체를 만들고 보유하기는 쉽습니다 기능을 구현하는 구성 요소와 함께 코드에 연결하고 필요에 따라 레이어링만 하면 됩니다 물론 기본적으로 암시적 세션이 대신 이 작업을 해 주기도 합니다
하지만 사람들이 반드시 하나의 앱 내에서 기능을 사용하지는 않죠 운동 트랙을 기록하는 기능은 자연스럽게 몇 초 이상 지속되는데 사용자는 이 앱을 백그라운드에서 실행되도록 둘 가능성이 큽니다 그러고는 다른 작업으로 관심을 돌리죠 예를 들면 다른 앱에서 음악을 만지작거리다가 운동이 끝날 때쯤 다시 운동 트랙 앱으로 돌아오는 거죠
해당 기능이 개념적으로 계속되면 모든 묵시적 세션도 계속되고 생성하는 명시적 CLServiceSession 객체도 마찬가지입니다 이유가 궁금하시죠? 이유는 세 가지입니다 첫째, 이렇게 하면 앱이 계속해서 승인 목표에 관심을 갖도록 할 수 있습니다 Core Location은 백그라운드에 앱이 있을 때 앱의 승인 수준을 조정하라고 요청하지 않지만 예기치 않게 포그라운드로 오면 무엇이 필요한지 알고 있기 때문에 필요하다면 Core Location은 즉시 단계대로 승인을 복구할 수 있죠
앱이 항상 승인된 경우 liveUpdates와 CLMonitor.events는 앱이 사용 중이 아닐 때는 포그라운드에서 시작된 세션이나 다른 세션이 유효할 때 시작된 세션이 그 지속적인 관심을 주장해야만 결과를 반환합니다
마지막으로, 처음 두 가지 이유가 납득이 잘 안 된다면 이 방법이 더 간단하기 때문입니다 세션 수명을 직접 기능 수명에 연결하고 다른 요인은 신경 쓰지 않는 것입니다 암시적 세션이 이를 수행하니까 여러분도 그렇게 해보세요 백그라운드까지 세션을 보유하면 앱이 나중에 업데이트가 잠잠해져 중지되었지만 여전히 운동을 추적하기 위해 사용되는 중에도 세션이 유효합니다
더 중요한 것은 앱이 중지되는 동안 종료되어도 유효하다는 것입니다 운동을 여전히 추적해야 합니다 그게 사용자가 이 앱에 요청한 것이니까요 하지만 여기 포함된 앱 프로세스와 모든 CLServiceSession 객체 또는 암시적 세션은 말 그대로 모두 사라졌습니다 Core Location은 앱에 전달할 것이 없을 때는 계속 앱을 실행시키는 조치를 취하지 않으며 승인받지 않은 것에는 업데이트를 생성하거나 전달하지 않습니다 예를 들어 .whenInUse 승인이 있고 LiveActivity 없이 백그라운드로 작동하거나 CLBackgroundActivitySession이 유효한 경우죠 하지만 처리되지 않은 각 API 객체는 여전히 추적합니다 CLServiceSession, liveUpdates 또는 기타 시퀀스 등에 대해서는 중지 또는 종료가 발생해도 계속해서 실행합니다 새로운 정보가 전달될 준비가 되면 백그라운드에서 앱을 재개하거나 재시작할 것이라는 뜻이고 앱의 승인이 이를 허용한다는 뜻입니다
그래서 이 다이어그램에서 파란색 세션 막대는 앱의 실제 프로세스에서 일어나는 일과는 상관없이 여전히 이어지죠
하지만 Core Location은 이런 명시적 및 암시적 세션을 영원히 추적하지 않습니다 그 대신에 앱이 다시 시작되고 몇 초 동안만 추적하죠 그 시작의 원인이 Core Location API 이벤트인지 사용자 상호작용인지 다른 원인인지는 상관없습니다 이 제한된 기간은 그렇게 지속되는 기능을 결국 재개하지 않을 경우 세션 상태가 유출되지 않도록 방지하는 데 중요합니다 따라서 이런 앱을 개발하실 때 여러분이 할 일은 프로세스 시작 로직이 어떤 기능을 추구해야 하는지 알게 하고 가능한 한 빠르게 세션 객체를 다시 취하거나 중단된 liveUpdates 또는 Monitor.events 반복을 재개하도록 하는 것입니다 이렇게 하면 새로운 객체가 이전 객체를 대신하고 Core Location이 앱이 계속 관심을 가진다는 것을 알 수 있습니다 이제 진단 속성에 대해 이야기하겠습니다 진단 속성은 승인 목표 미달성의 이유와 그 상황을 알려 줍니다 CLServiceSession을 보유함으로써 그 효과를 얻을 수 있지만 각 인스턴스는 진단 AsyncSequence도 노출하는데 ‘for try await‘과 상호작용하여 무슨 일이 있었는지 알 수 있죠 이 코드에서처럼 말이죠
여기 부울 속성을 보세요 이것을 진단 속성이라고 하고 예상치 못한 일이 발생하면 진단 속성이 알려 줍니다 이 경우에는 앱 사용자가 앱에 위치를 공유하지 않고 싶어 합니다 .authorizationDenied 외에 .insufficientlyInUse를 포함해서 몇 가지가 더 있는데 이 경우 Core Location이 앱 대신 승인을 요청할 수 없고 .alwaysAuthorizationDenied는 항상 승인을 목표로 했지만 승인을 받지 못한 경우입니다 .authorizationDeniedGlobally를 특히 주의 깊게 보시기 바랍니다 위치 서비스가 시스템 전체에서 비활성화되면 참입니다 사용자가 기기를 이렇게 구성하면 앱도 해당 승인이 거부되므로 .authorizationDenied가 참이 됩니다 진단 속성에서는 이를 다르지만 관련된 두 속성으로 간주합니다 따라서 앱이 액세스가 명시적으로 거부되었을 때만 알고 싶어 하면 예를 들어 UI에서 예상 이동 시간을 생략한다고 하면 일반적인 것만 확인하면 됩니다
하지만 앱을 설치하기 훨씬 전에 전체 설정을 결정한 사람들에게 다른 지침을 주고 싶다면 어떻게 해야 할까요? 더 구체적인 속성을 확인해서 그런 일이 벌어졌는지 확인하면 됩니다 다시 코드를 보면 진단 처리 로직을 좀 더 중립적으로 만들어서 이것을 활용할 수 있습니다 사용자가 언제 결정을 내렸는지 알아야 할 수도 있겠죠? 참고로 이 코드가 실행될 때 사용자가 이미 앱 승인을 부여했거나 거부했다면 Core Location이 아무것도 물어볼 필요가 없기 때문에 첫 번째 진단이 도착할 때 .authorizationRequestInProgress 속성이 이미 거짓이고 여러분이 원하는 대로 코드가 즉시 실행될 수 있습니다 하지만 앱의 승인은 역동적으로 변경될 수 있다는 점을 기억하세요 사용자가 설정에서 조정하거나 임시 승인만 부여한 경우에는 승인이 변경될 수 있습니다 따라서 앱이 세션에서 응답하는 기능을 제공하고 있다면 세션 진단을 계속해서 추적하는 것이 좋고 UI가 반응할 수 있도록 @Published vars를 설정하는 것도 좋습니다
앱이 위치 정보를 필요로 하는 동안 세션 범위와 작업 내의 반복 범위를 지정하고 완료되면 취소하는 경우 세션은 적절한 수명 주기를 갖게 되고 앱 사용자가 부여하기로 선택한 승인에 따라 UI가 적절하게 응답할 것입니다 진단 속성은 CLServiceSession에 승인 목표 상태를 달성하지 못할 때 실행 가능한 방식으로 표시하는 유연성과 기능을 부여합니다 그리고 아시다시피 liveUpdates와 CLMonitor.Event도 암시적 세션을 제공합니다 따라서 진단 속성은 CLLocationUpdate 또는 CLMonitor.Event에서 각각 사용할 수 있습니다 이 객체는 앞에서 봤는데 특히 CLLocationUpdate에 이미 .stationary라는 부울 진단 속성이 있습니다 업데이트가 중지되기 전에 마지막 업데이트에서 이 값은 참입니다 기기가 움직임을 멈췄기 때문입니다
하지만 이제 각각에 추가 부울 속성이 포함되어 있는데 암시적 서비스 세션으로서의 역할 때문에 발생할 수 있는 문제를 해결하기 위한 것입니다 그리고 더 있습니다 CLLocationUpdate에 두 개가 있는데 추가 업데이트가 한동안 도착하지 않는 이유를 설명합니다 .accuracyLimited는 대략적 위치로 15~20분마다 업데이트되며 Core Location의 경우 .locationUnavailable은 현재 위치를 전혀 파악할 수 없습니다 CLMonitor.Event 역시 어떤 조건에서 이벤트가 반환되지 않음을 보고할 수 있습니다 이유는 정확도 제한 또는 다른 이유 때문인데 이러한 유형의 조건이 이미 너무 많이 모니터링되고 있는 경우입니다 종합하면 각 API 객체의 이러한 진단 속성은 과거에 있었던 시간 초과를 없애고 추측을 하지 않아도 되게 해 줍니다 이제 어떤 이유로든 Core Location이 여러분이 기대하는 업데이트나 이벤트를 줄 수 없는 경우 그 대신에 그 이유를 알려 주는 진단 속성을 하나 제공할 것입니다 여기까지입니다 CLServiceSession을 사용하여 Core Location에 필요한 승인을 알려 줄 수 있다는 것을 기억하세요 자연스럽게 반복하는 API와 이벤트가 여러분을 대신해서 처리하지 않는다면 말이죠 이제 업데이트, 이벤트 또는 서비스 세션이 의도한 결과를 반환할 수 없을 때마다 Core Location이 진단 속성을 통해 항상 그 이유를 알려 줍니다 원하시면 작년의 CLLocationUpdate 및 CLMonitor 영상에서 자세한 내용을 알아보세요 새로운 기능을 꼭 사용해 보시고 어떤지 알려 주시기 바랍니다!
-
-
0:31 - CLLocationUpdate and CLMonitor
// Iterating liveUpdates to reflect current location Task { let updates = CLLocationUpdate.liveUpdates() for try await update in updates { if let loc = update.location { updateLocationUI(location: loc) } } } // Iterating monitor events to report condition state changes Task { let monitor = await CLMonitor(monitorName) await monitor.add(CLMonitor.CircularGeographicCondition(center: applePark, radius: 50), identifier: "ApplePark") for try await event in await monitor.events { updateConditionsUI(for: event.identifier, state: event.state) } }
-
0:52 - Handle updates with CLLocationManagerDelegate
// Adapting location authorization to Swift with a MainActor singleton @MainActor class LocationReflector: NSObject, CLLocationManagerDelegate, ObservableObject { static let shared = LocationReflector() private let manager = CLLocationManager() override init() { super.init() manager.delegate = self } func locationManagerDidChangeAuthorization(_ manager: CLLocationManager){ if (manager.authorizationStatus == .notDetermined) { manager.requestWhenInUseAuthorization() } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations:[CLLocation]) { // Process locations[0] } // ... }
-
1:07 - CLServiceSession simplifies
// CLServiceSession in action Task { let session = CLServiceSession(authorization: .whenInUse) for try await update in CLLocationUpdate.liveUpdates { // Process update.location or update.authorizationDenied } }
-
7:15 - Implicit service sessions
// CLServiceSession in action Task { let session = CLServiceSession(authorization: .whenInUse) for try await update in CLLocationUpdate.liveUpdates { // Process update.location or update.authorizationDenied } }
-
7:34 - Implicit service sessions
Task { for try await update in CLLocationUpdate.liveUpdates { // Process update.location or update.authorizationDenied } }
-
13:37 - Diagnostics – Following the progress of location authorization
// Following the progress of location authorization with CLServiceSession let mySession = CLServiceSession(authorization:.whenInUse) for try await diagnostic in mySession.diagnostics { if (diagnostic.authorizationDenied) { // Ok, let’s let them pick a location instead? } }
-
15:00 - Diagnostics – Following the progress of location authorization
// Following the progress of location authorization with CLServiceSession let mySession = CLServiceSession(authorization:.whenInUse) for try await diagnostic in mySession.diagnostics { if (!diagnostic.authorizationRequestInProgress) { // They’ve decided (maybe already). We can move on! break } }
-
15:25 - Diagnostics – Following the progress of location authorization
// Following the progress of location authorization with CLServiceSession let mySession = CLServiceSession(authorization:.whenInUse) for try await diagnostic in mySession.diagnostics { if (!diagnostic.authorizationRequestInProgress) { reactToChanges(authorized:!diagnostic.authorizationDenied) } }
-
15:46 - Diagnostics – Following the progress of location authorization
// Following the progress of location authorization with CLServiceSession Task { let mySession = CLServiceSession(authorization:.whenInUse) for try await diagnostic in mySession.diagnostics { if (!diagnostic.authorizationRequestInProgress) { reactToChanges(authorized:!diagnostic.authorizationDenied) } } }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.