사용자의 정보를 사용하기 위해서는 가장 먼저 plist에 사용자 권한을 얻어야 하는 부분과 멘트를 추가해야합니다. 위치 관련 데이터는 Privacy - Location까지 검색하면 사용 가능한 항목들을 확인할 수 있습니다.
권한 설정은 굉장히 중요한 부분인데 꼭 필요한 부분만 설정해야합니다. 필요하지 않은 부분에 대한 권한을 설정하거나 권한에 대한 자세한 설명(Description)이 없을 경우 앱 출시 시 리젝의 사유가 될 수 있다고 합니다🥲
requestTemporaryFullAccuracyAuthorization(withPurposeKey:)
메서드에 필요한 key를 제공함으로써 접근할 수 있음// Request location access to find coffee shops.
manager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "friends")
앱으로 위치 관련 이벤트 전달을 시작하거나 멈추는데 사용하는 개체
The object that you use to start and stop the delivery of location-related events to your app.
위치와 관련된 이벤트를 제어하는데 사용되는 CLLocationManager class를 사용하기 위해서 먼저 인스턴스를 생성해주고 locationManager에 할당해줍니다.
let locationManager = CLLocationManager()
delegate도 선언해줍니다.
locationManager.delegate = self
extension을 통해 delegate 프로토콜을 채택해줍니다.
extension LocationViewController: CLLocationManagerDelegate {
}
사용자가 위치 서비스를 사용하는 경우(일반 설정에서 위치 서비스 사용 on인 상태) CLAuthorizationStatus를 통해 사용자 권한을 확인하고 각 Case별로 해야할 일을 처리해줘야합니다.
사용자 권한 승인 상태는 총 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")
}
}
enum CLAccuracyAuthorization : Int
if #available(iOS 14.0, *) {
let accurancyState = locationManager.accuracyAuthorization
switch accurancyState {
case .fullAccuracy:
print("Full")
case .reducedAccuracy:
print("reduced")
@unknown default:
print("DEFAULT")
}
}
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 위치 서비스 켜주세요")
}
}
아래 두 메서드는 사용자가 권한 상태를 변경할 때 마다 실행되는 메서드입니다.
// 6. iOS14 미만: 앱이 위치 관리자를 생성하고, 승인 상태가 변경이 될 때 대리자에게 승인 상태를 알려줌
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print(#function)
checkUserLocationServicesAuthorization()
}
// 7. iOS14 이상: 앱이 위치 관리자를 생성하고, 승인 상태가 변경이 될 때 대리자에게 승인 상태를 알려줌
// 14부터 정확도에 대한 내용이 추가됨
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
print(#function)
checkUserLocationServicesAuthorization() // viewDidLoad에서 실행하지않음!
}
// 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")
}
}
// 5. 위치 접근이 실패했을 경우
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(#function)
}