본문 바로가기

Project/CafePoCa

✅ 위치 정보 및 권한 설정하기

https://explorer89.tistory.com/159

 

위치정보를 받아오는 방법

참고 사이트 https://velog.io/@maddie/iOS-UIKit-CoreLocation-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%A0%95%EB%A6%AC" data-og-host="velog.io" data-og-source-url="https://velog.io/@maddie/iOS-UIKit-CoreLocation-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%A0%95%EB%A6%AC" da

explorer89.tistory.com

 

이전에 작성한 위치 정보를 받아오는 법에서 좀 더 업데이트 했습니다.

 

✅ Import CoreLocation 선언

import UIKit
import CoreLocation

 

 

✅ viewDidLoad() 내에 delegate 선언

override func viewDidLoad() {
    super.viewDidLoad()        
    locationManager.delegate = self       
}

 

✅ CLLocationManagerDelegate 채택 및 메서드 설정

extension HomeViewController: CLLocationManagerDelegate {
    
    /*
    func checkUserDeviceLocationServiceAuthorization() {
        // 1. 디바이스 차원의 위치 서비스가 켜져 있는지 확인
        guard CLLocationManager.locationServicesEnabled() else {
            showRequestLocationServiceAlert()
            return
        }
        
        // 2. 위치 권한 요청 (결과는 delegate 메서드에서 처리)
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
    }
    */
    
    // iOS 14 이상 권한 변경 감지 콜백
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        handleAuthorizationStatus(manager.authorizationStatus)
    }
    
    // iOS 14 미만 권한 변경 감지 콜백
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        handleAuthorizationStatus(status)
    }
    
    // 실제 권한 상태에 따라 분기 처리하는 함수
    private func handleAuthorizationStatus(_ status: CLAuthorizationStatus) {
        switch status {
        case .notDetermined:
            // 사용자가 아직 권한 선택을 하지 않은 상태 (다시 request 요청함)
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.requestWhenInUseAuthorization()
            
        case .restricted, .denied:
            // 설정에서 위치 권한을 꺼뒀거나 제한된 경우
            showRequestLocationServiceAlert()
            
        case .authorizedWhenInUse, .authorizedAlways:
            // 권한이 허용된 상태 → 위치 정보 요청
            locationManager.startUpdatingLocation()
            
        default:
            print("Unhandled status: \(status.rawValue)")
        }
    }
    
    // 위치 업데이트 콜백
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let coordinate = locations.last?.coordinate {
            // ⭐️ 사용자 위치 정보 활용
            print("사용자 위치: \(coordinate.latitude), \(coordinate.longitude)")
        }
        locationManager.stopUpdatingLocation()
    }
    
    // 위치 요청 실패 콜백
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("❌ 위치 정보 가져오기 실패: \(error.localizedDescription)")
    }
    
    // 위치 권한이 꺼져있는 경우 사용자 설정 유도
    func showRequestLocationServiceAlert() {
        let alert = UIAlertController(
            title: "위치 정보 이용",
            message: "위치 서비스를 사용할 수 없습니다.\n디바이스의 '설정 > 개인정보 보호'에서 위치 서비스를 켜주세요.",
            preferredStyle: .alert
        )
        let goSetting = UIAlertAction(title: "설정으로 이동", style: .destructive) { _ in
            if let appSetting = URL(string: UIApplication.openSettingsURLString) {
                UIApplication.shared.open(appSetting)
            }
        }
        let cancel = UIAlertAction(title: "취소", style: .default) { [weak self] _ in
            self?.reloadDataIfNeeded()
        }
        alert.addAction(cancel)
        alert.addAction(goSetting)
        
        present(alert, animated: true)
    }
    
    // `reloadData` 대체용 (선택사항)
    private func reloadDataIfNeeded() {
        // 권한이 거부된 후 UI를 갱신하거나 데이터를 다시 로드하고 싶다면 여기에 작성
        print("🔄 위치 권한 거부: UI 갱신 필요 시 이곳에서 처리")
    }
}

 

 

🔍 왜 viewDidLoad()에서 권한 요청을 호출하지 않아도 동작할까?

CLLocationManager는 delegate를 설정하고 앱이 실행되면, 시스템이 알아서 locationManagerDidChangeAuthorization(_:)을 호출

 

그리고 거기서 authorizationStatus를 읽고 .notDetermined 상태일 경우에 우리가 직접 requestWhenInUseAuthorization()을 호출

 

private func handleAuthorizationStatus(_ status: CLAuthorizationStatus) {
    switch status {
    case .notDetermined:
        // 사용자가 아직 권한 선택을 하지 않은 상태 (다시 request 요청함)
        // ✅ 이 부분을 말함 
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()

    case .restricted, .denied:
        // 설정에서 위치 권한을 꺼뒀거나 제한된 경우
        showRequestLocationServiceAlert()

    case .authorizedWhenInUse, .authorizedAlways:
        // 권한이 허용된 상태 → 위치 정보 요청
        locationManager.startUpdatingLocation()

    default:
        print("Unhandled status: \(status.rawValue)")
    }
}