User Location
체크center
는 좌표, 두 세번째 파라미터는 지도에 표시할 구역의 크기 지정func move(to location: CLLocation){
let region = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: 100, longitudinalMeters: 100)
mapView.setRegion(region, animated: true)
}
이후 extension의 didUpdateLocations
메소드에서 실행하면 된다.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let currentLocation = locations.last{
move(to: currentLocation)
}
}
let manager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
}
extension MapViewController: CLLocationManagerDelegate{
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .notDetermined:
manager.requestWhenInUseAuthorization()
break
case .restricted, .denied:
let alert = UIAlertController(title: "알림", message: "위치 서비스를 활성화시켜 주세요.", preferredStyle: .alert)
let settingAction = UIAlertAction(title: "설정", style: .default){ _ in
//string에 저장된 문자열로 url을 만든 다음에 open으로 전달하면 설정 앱으로 바로 이동 가능
if let url = URL(string: UIApplication.openSettingsURLString){
UIApplication.shared.open(url)
}
}
alert.addAction(settingAction)
let cancelAction = UIAlertAction(title: "취소", style: .cancel)
alert.addAction(cancelAction)
present(alert, animated: true)
break
case .authorizedAlways:
manager.startUpdatingLocation()
break
case .authorizedWhenInUse:
manager.requestAlwaysAuthorization()
@unknown default:
break
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
//에러를 확인하려면 NSError타입으로 캐스팅해야함.
let error = error as NSError
guard error.code != CLError.Code.locationUnknown.rawValue else {return}
print(error)
manager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let currentLocation = locations.last{
move(to: currentLocation)
}
}
}
하나의 앱에서 locationManager을 두 개 사용해도 문제는 없으나, 지금처럼 didChangeAuthorization이 호출되지 않을 수 있음을 유의하고, 하나의 화면에서만 LocationService 를 사용할 수 있도록 유의해야 한다.
현재 짠 코드에서는 이미 Location 탭에서의 manager 인스턴스에서 권한을 받고didChangeAuthorization을 실행할 수 있었으나, Map 탭에서의 vc의 manager은 이미 권한을 획득한 상태이므로 didChangeAuthorization이 실행되지 않아, case문 안에 작성해뒀던 startUpdatingLocation 메소드가 실행되지 않는다.
MapView vc에서 하단의 코드를 작성하여 권한 이 있을 때 따로 startUpdatingLocation 메소드를 실행하도록 처리해준다.
또한 화면을 벗어날 때(viewWIllDisappear) 위치 업데이트를 꺼 하나의 화면에서만 locationManager을 쓸 수 있도록 처리해준다.
이렇게 해도 startUpdatingLocation이 두 번 호출될 수 있으나, 여러번 호출한다고 해서 중복된 이벤트가 전달되는 것은 아니기 때문에 문제는 없다.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if manager.authorizationStatus == .authorizedWhenInUse || manager.authorizationStatus == .authorizedAlways{
manager.startUpdatingLocation()
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
manager.stopUpdatingLocation()
}