Ch.6 Silver: Displaying the User’s Region
# 유저의 위치 나타내기
- 지도에 현재 유저의 위치를 줌인해서 보여주는 게 과제!
- 유저로부터 위치 정보 사용을 승인 받고, 승인되는 경우 줌인하도록 구현했다.
# 위치 정보 사용 동의 받기
1. Info.plist 에 "Privacy-Location When In Use Usage Description" 키 추가
- 얘의 역할은 위치 정보 사용 동의를 받을 때 유저에게 나타낼 메시지를 설정할 수 있게 해준다.
- value 에 나타낼 메시지를 적으면 된다!
- value 에 나타낼 메시지를 적으면 된다!
- 주의할 점은 "When In Use" 일 때, 즉 앱이 실행되고 있을 때의 위치 정보 접근 권한을 요청하는 경우에만 알림창을 띄운다는 것
- 즉, requestWhenInUseAuthorization() 메서드를 호출할 때만 알림을 띄우고, requestAlwaysAuthorization() 메서드를 호출하면 아무것도 띄우지 않는다.
2. CLLocationManager 오브젝트로 위치 접근 권한 요청하기
- 얘는 위치 관련 이벤트를 관리하는 역할로, 유저에게 위치 접근 권한을 요청할 수 있는 requestWhenInUseAuthorization() 메서드를 포함하고 있다.
- requestWhenInUseAuthorization() 메서드가 호출되면 아래와 같은 알림창이 뜨는 데, 유저가 허용 여부를 선택하면 델리게이트의 locationManagerDidChangeAuthorization(_:) 가 호출된다.
-
따라서 MapViewController 를 CLLocationManagerDelegate 프로토콜에 따르게 하고 CLLocationManager 오브젝트의 델레게이트로 선언해 locationManagerDidChangeAuthorization(_:) 메서드에 권한에 따라 작업을 수행하도록 한다.
- CLLocationManager 타입의 locationManager 프로퍼티를 선언한 다음 viewDidLoad() 함수에서 초기화하고 델리게이트를 지정했다.
- 그 다음 requestWhenInUseAuthorization() 메서드를 호출하고, 이에 따라 호출 될 locationManagerDidChangeAuthorization(_:) 메서드에서 authorization status 를 확인해서 .authorizedWhenInUse 인 경우 지도에서 유저의 위치를 계속 추적해서 업데이트할 수 있도록 showsUserLocation 프로퍼티를 토글했다.
- CLLocationManager 타입의 locationManager 프로퍼티를 선언한 다음 viewDidLoad() 함수에서 초기화하고 델리게이트를 지정했다.
-
import UIKit
import MapKit
class MapViewController: UIViewController, CLLocationManagerDelegate {
private var mapView: MKMapView!
private var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
print("MapViewController loaded its view")
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedWhenInUse {
mapView.showsUserLocation.toggle()
}
}
}
# 사용자의 위치에 줌인하기
- 위의 단계까지 하면 지도에 사용자의 위치가 파란 점으로 표시는 되는데 줌인이 안 된 상태다. setRegion(_:animated) 메서드를 사용하면 디스플레이 되는 지역을 바꿀 수 있고, 첫 번째 인자의 설정을 통해 줌 정도를 변경할 수 있다.
- 따라서 유저의 위치가 바뀔 때마다 setRegion(_:animated) 메서드를 호출하면 되는데, 유저의 위치가 업데이트 될 때마다 이에 대한 알림을 받기 위해서는 mapview 델레게이트의 메서드 중 mapView(_:didUpdate:) 메서드를 사용할 수 있다.
-
즉, MapViewController 를 mapView 의 델리게이트로 선언한 다음, mapView(_:didUpdate:) 메서드에서 setRegion(_:animated) 메서드를 호출하게 하면 유저의 위치가 바뀔 때마다 유저의 현재 위치로 줌인하게 할 수 있다.
-
mapView(_:didUpdate:) 메서드에서 setRegion(_:animated) 메서드를 바로 호출하게 하지 않고 별도로 zoomIntoUserLocation(userLocation:) 메서드를 사용해서 구현했는데, center 가 userLocation 의 좌표와 일치하고, span 이 0.01 인 MKUserLocation 오브젝트를 생성해 setRegion(_:animated) 메서드의 인자로 보냈다.
- span 은 0 일때 최대로 줌인된 상태!
class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
private var mapView: MKMapView!
private var locationManager: CLLocationManager!
override func loadView() {
super.loadView()
mapView = MKMapView()
view = mapView
mapView.delegate = self // 델리게이트 설정
...
}
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
zoomIntoUserLocation(userLocation: userLocation)
}
private func zoomIntoUserLocation(userLocation: MKUserLocation) {
let locationDegrees: Double = 0.01
let region = MKCoordinateRegion(
center: userLocation.coordinate,
span: MKCoordinateSpan(
latitudeDelta: locationDegrees,
longitudeDelta: locationDegrees
)
)
mapView.setRegion(region, animated: true)
}
}
☀️ 느낀점
- 이번 과제를 하면서 델리게이트의 가치에 대해 배울 수 있었다. 사실 델리게이트의 개념조차도 아직 확실하게 이해한 게 아니라서 처음에는 왜 델리게이트 설정을 해줘야하는지 궁금했는데(얼렁뚱땅으로 코드를 짰는데 델리게이트 없이 수동으로도 과제에서 요구하는 바를 구현할 수는 있었기 때문에...) 델리게이트의 메서드를 활용하면 더 깔끔하게 코드를 작성할 수 있다는 점을 배웠다.
- 줌인을 할 때 처음에는 userLocation 프로퍼티를 따로 선언하고 didSet 을 사용해서 위치가 바뀔 때마다 setRegion(_:animated) 메서드를 호출하려고 했는데, mapView(_:didUpdate:) 메서드를 활용하면 어차피 유저의 위치가 바뀔 때마다 해당 메서드가 호출되므로 프로퍼티 선언이나 didSet 호출의 과정이 필요없었다...!
Author And Source
이 문제에 관하여(Ch.6 Silver: Displaying the User’s Region), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sunnysideup/Ch.6-Silver-Challenge-9u6hc72u저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)