[iOS] MapKit Privacy & Authorization


Info.plist(権限設定)


ユーザーの情報を使用するには、まずplistにユーザー権限を取得する必要がある部分と内容を追加する必要があります.「プライバシーの場所」を検索すると、場所関連データに使用可能なアイテムが表示されます.
権限設定は非常に重要な部分ですが、必要な部分だけを設定する必要があります.不要な部分に権限を設定したり、詳細な説明権限を設定したりしていない場合は、アプリケーションのパブリッシュ時のイベントの原因になる可能性があります.🥲
  • Privacy - Location When In Use Usage Description
    (iOS 11以降)iOSアプリケーションがバックグラウンドで実行する場合のみ、ロケーション情報
  • にアクセスする.
  • Privacy - Location Always and When In Use Usage Description
    (iOS 11以降)アプリケーションがバックグラウンドから位置情報にアクセスする場合は
  • である.
  • Privacy - Location Default Accuracy Reduced
    (iOS 14以降)Bool Typeは、デフォルトでアプリケーションが要求する場所が正しくないことを設定するために使用できます.
    →true:すべてのコア・ロケーション・サービスが低下-正確なレベルで情報を提供
    →false:値をfalseに設定すると、詳細な位置情報
  • が表示されます.
  • キー値を別途設定しない場合、デフォルトはfalseに設定されます.
  • Privacy - Location Temporary Usage Description Dictionary
    (iOS 14以降)Dictionary Typeは、アプリケーションがユーザに一時的なアクセスを要求した理由に関する情報を収集するために使用される.
    →周辺の友人を探す機能を使う場合
    「friends」:「近くのfriendsに接続する場所を使用」
    requestTemporaryFullAccuracyAuthorization(withPurposeKey:)メソッドに必要な鍵を提供することによって
  • へのアクセスを要求する.
    // Request location access to find coffee shops.
    manager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "friends")
  • Privacy - Location Always Usage Description
    Depevented(iOS 11以前のターゲットに配備されている場合)
  • Privacy - Location Usage Description
    MacOSアプリケーションの開発
  • 1. CLLocationManager()


    アプリケーションへのロケーション関連イベントの送信を開始または停止するオブジェクト.
    The object that you use to start and stop the delivery of location-related events to your app.
    CLLocation Managerクラスは、場所に関連するイベントを制御するために使用されます.まずインスタンスを作成し、場所マネージャに割り当てます.
    let locationManager = CLLocationManager()
    依頼を宣言することもできます.
    locationManager.delegate = self

    2. CLLocationManagerDelegate


    拡張は委託プロトコルを採用する.
    extension LocationViewController: CLLocationManagerDelegate {
    }

    3.(ロケーションサービスが開いている場合)ユーザー権限の検証


    ユーザーがロケーション・サービスを使用している場合(一般設定でロケーション・サービスを使用している場合)は、「認可ステータス」を使用してユーザー権限をチェックし、各ケースで必要なことを処理する必要があります.

    3-1. CLAuthorizationStatus


    ユーザー権限承認ステータスは、次の5つに分けられます.
    1. case notDetermined
    ユーザーは「場所の許可」権限を選択していません.
    2. case restricted
    アプリケーションはロケーションサービスを使用できません
    →主に保護者制御モードのため、ユーザーはアプリケーションの許可権限を変更できない.
    3. case denied
    ユーザーは、「要求権限」「脱文字」ウィンドウで「拒否」を選択します.
    →「許可」を選択し、設定を無効にします.
    →断る場合
    →利用場所サービス自体の停止
    →飛行機モードで位置サービスが利用できない状態
    4. case authorizedAlways
    バックグラウンドを含む任意の場所サービスの使用が承認されました
    5. case authorizedWhenInUse
    アプリケーションの使用中のみのロケーションサービスの使用を許可
  • は、プロトコルで定義された方法をロードするのではなく、カスタム関数を実装し、ユーザー権限を検証し、各ケースで処理します.
  •     func checkCurrentLocationAuthorization(_ authorizationStatus: CLAuthorizationStatus) {
            switch authorizationStatus {
            case .notDetermined:
                // 앱이 받고 싶어하는 위치 데이터의 정확도 설정
                // 이 설정은 배터리 사용량에도 영향을 미친다. 그러니 사용용도에 적합한 value를 할당하는 것이 중요함
                // 설정하지 않으면 KCLLocationAuccracyBest가 default값으로 적용됨
                locationManager.desiredAccuracy = kCLLocationAccuracyBest
                // 앱을 사용하는 동안에 대한 위치 권한 요청(위치 권한 띄우기)
                // 해당 메서드는 현재 authorization status가 not determined 상태일 때 부르는 것이 적합함
                locationManager.requestWhenInUseAuthorization()
                // 반드시 들어가야함. 위치 접근 시작~ 사용자 위치를 얻어주세요~ 시작해주세요~
                // 이 메서드를 실행하면 초기 위치 수정 사항에 대해 가져오고
                // didUpdateLocations 메서드를 통해 delegate에게 알려준다.
                locationManager.startUpdatingLocation()
            case .restricted, .denied:
                // 보통 이 부분에서 alert창을 이용해 설정으로 이동시키는 코드를 구현함
                print("denied, 설정으로 유도")
            case .authorizedWhenInUse:
                // 앱을 사용하는 동안만, 위치 접근 시작 => didUpdateLocations 실행
                locationManager.startUpdatingLocation()
            case .authorizedAlways:
                print("always")
            @unknown default:
                print("default")
            }
         }

    3-2. CLAccuracyAuthorization

    enum CLAccuracyAuthorization : Int
  • iOS 14以降.
  • 位置精度レベルのIntタイプ
    1. fullAccuracy
    ユーザーが最も正確な方法で位置データにアクセスできるようにします.
    2. reducedAccuracy
  • ユーザーが場所データにアクセスすることを許可する精度が低い
            if #available(iOS 14.0, *) {
                let accurancyState = locationManager.accuracyAuthorization
                
                switch accurancyState {
                case .fullAccuracy:
                    print("Full")
                case .reducedAccuracy:
                    print("reduced")
                @unknown default:
                    print("DEFAULT")
                }
            }

    4.ロケーションサービスがオープンしていることを確認する(ブランチ処理)


    iOSバージョンのブランチ処理とiOSロケーションサービスを提供するかどうかを確認します.
        func checkUserLocationServicesAuthorization() {
            let authorizationStatus: CLAuthorizationStatus
            
            if #available(iOS 14.0, *) {
                authorizationStatus = locationManager.authorizationStatus // iOS14 이상
            } else {
                authorizationStatus = CLLocationManager.authorizationStatus() // iOS14 미만
            }
            
            // iOS 위치 서비스 확인
            if CLLocationManager.locationServicesEnabled() {
            // 만약 사용자가 위치 서비스를 사용하고 있다면 위치 권한을 확인 후 이에 맞는 메서드를 실행한다.
                // 권한 상태 확인 및 권한 요청 가능
                checkCurrentLocationAuthorization(authorizationStatus)
            } else {
                // iOS 위치 권한을 허락해달라는 alert 띄우기
                print("iOS 위치 서비스 켜주세요")
            }
        }

    5.権限ステータスの変更時に実行する方法


    次の2つの方法は、ユーザーが権限ステータスを変更するたびに実行する方法です.
        // 6. iOS14 미만: 앱이 위치 관리자를 생성하고, 승인 상태가 변경이 될 때 대리자에게 승인 상태를 알려줌
        func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
            print(#function)
            checkUserLocationServicesAuthorization()
        }
        
        // 7. iOS14 이상: 앱이 위치 관리자를 생성하고, 승인 상태가 변경이 될 때 대리자에게 승인 상태를 알려줌
        // 14부터 정확도에 대한 내용이 추가됨
        func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
            print(#function)
            checkUserLocationServicesAuthorization() // viewDidLoad에서 실행하지않음!
        }

    6.ユーザーが場所の使用を許可する場合は、MapViewを現在の場所に変更します。

     // 4. 사용자가 위치 허용을 한 경우
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            print(#function)
            print(locations)
            
            if let coordinate = locations.last?.coordinate {
                let annotation = MKPointAnnotation()
                annotation.title = "CURRENT LOCATION"
                annotation.coordinate = coordinate
                mapView.addAnnotation(annotation)
                
                // 지도의 중심 바꾸기
                let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
                let region = MKCoordinateRegion(center: coordinate, span: span)
                mapView.setRegion(region, animated: true)
                
                // 10. (중요) 업데이트가 너무 많이 되는 경우, 비효율적 -> 업데이트 멈춰달라고 요청
                // 비슷한 반경에서!
                locationManager.stopUpdatingLocation()
            } else {
                print("Location Can not find")
            }
        }

    7.場所アクセス失敗

    // 5. 위치 접근이 실패했을 경우
        func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
            print(#function)
        }