이번 글은 프로젝트를 진행하며 내가 알아내고 구현한 것 위주로 서술하였다. 다른 더 좋은 방법이 있을 수도 있다!
화면 가운데 마커 설정하기
택시 호출 앱 등을 살펴보면 화면 정 가운데 마커가 있고,
화면을 드래그하면 드래그가 끝났을 때, 현 위치 주소가 바뀌는 것을 본적이 있을 것이다.
이번 글에선 이 기능에 대해 설명해보려한다.
마커 만들기
우선 간단하게 마커를 찍는 방법부터 알아보자면
import UIKit
import NMapsMap
class CenterMarkerViewController: UIViewController, NMFMapViewCameraDelegate {
let centerMarker = NMFMarker()
override func viewDidLoad() {
super.viewDidLoad()
let naverMap = NMFNaverMapView(frame: view.frame)
view.addSubview(naverMap)
centerMarker.position = naverMap.mapView.cameraPosition.target //지도 화면 가운데 위치
centerMarker.captionText = "마커"
centerMarker.captionAligns = [NMFAlignType.top] //캡션의 위치
centerMarker.mapView = naverMap.mapView //마커 지도에 추가
}
}
위와 같이 NMFMarker 객체를 추가해 주고,
position을 지정해 준 뒤 지도에 추가해주면추가해 주면 끝이다.
그 외에 여러 옵션들은 필요하다면 추가해 주면 된다.
Delegate 살펴보기
이제 여기서 카카오 T나 여러 택시앱들처럼 지도를 드래그해도 마커는 화면 가운데에 고정되게 해 보자.
화면 가운데 마커를 구현하기 위해서는 Delegate를 이용해야 한다.
naverMap.mapView.addCameraDelegate(delegate: self)
간단하게 메서드를 톺아보자면
1. Camera Is Chaing By Reason 메서드
- 지도 화면이 움직였을 때 호출되는 메서드로 코드로 카메라 위치가 바뀌든, 드래그를 통해 바뀌든 상관없이 호출된다.
- 매개변수로 주어지는 Reason을 통해 왜 지도뷰가 이동했는지 알 수 있다.
- NMFMapChangedByDeveloper는 코드로 화면이 움직였을 때 (기본값)
- NMFMapChangedByGesture는 사용자의 드래그로 화면이 움직였을 때
- NMFMapChangedByControl는 버튼 선택으로 화면이 움직였을 때
- NMFMapChangedByLocation은 네이버 지도가 제공하는 위치 트래킹 기능으로 화면이 움직였을 때
- 만약 이 메서드가 없다면 사용자가 드레그를 빠르게 하고 손을 놓아버렸을 때 마커가 따라오지 않게 된다.(빠르게 드래그하고 손을 놓아도 움직임이 계속되는 것을 관성 드래깅이라고 한다.) 그 후 이동이 끝나면 마커가 따라오게 되는데, 마커가 따라오지 않아 사용자가 불편함을 느낄 수 있는 부분이다.
2. Camera Did Change By Reason 메서드
- 지도 화면의 이동을 계속해서 추적하는 메서드이다. 나름대로 추측해 보건대 카메라의 움직임이 끝났을 때라고 나와있는데 드래그로 움직일 때 조금의 이동 자체도 한 움직임이 시작되었다가 끝났다고 인식하는 것 같다. 이 조금의 이동이 연속적으로 있고, 이동이 끝날 때마다(조금씩 이동할 때마다) 호출되는 메서드인 것 같다. 나머지 부분은 위와 같다.
- 만약 이 메서드가 없다면 드래그 시 마커가 따라오지 않는다. 그 후 드래그가 끝나면 마커가 따라오게 된다.
- cameraIsChangingByReason 메서드와의 차이점은 cameraIsChangingByReason는 드래그를 빨리 해서 손을 놓았을 때, 아직 화면이 움직이는 상태일 때 따라오지 않는 것이고, 이 메서드는 드래그로 움직였을 때 따라오지 않는 것이다.
3. Camera Idle 메서드
- 카메라의 움직임 즉, 화면 이동이 완전히 끝나면 호출되는 메서드이다.
- 이 메서드가 없어도 화면 중앙에 마커를 고정시킬 수는 있지만, 이 메서드를 사용해 준다면 드레그를 완료한 시점에 좌표만 손쉽게 얻을 수 있다.
4. 구현 코드
이제 코드로 구현을 해보자.
방법은 마커를 만들고
드래그 시 마커가 화면 가운데에 고정되게 position을 계속해서 업데이트해 준다.
마지막으로 이동이 끝났을 때 좌표값을 print 해보겠다.
import UIKit
import NMapsMap
class CenterMarkerViewController: UIViewController, NMFMapViewCameraDelegate {
let centerMarker = NMFMarker()
override func viewDidLoad() {
super.viewDidLoad()
let naverMap = NMFNaverMapView(frame: view.frame)
view.addSubview(naverMap)
let cameraUpdate = NMFCameraUpdate(scrollTo: NMGLatLng(lat: 37.479132, lng: 127.011770))
naverMap.mapView.moveCamera(cameraUpdate)
centerMarker.position = naverMap.mapView.cameraPosition.target
centerMarker.captionText = "마커"
centerMarker.captionAligns = [NMFAlignType.top]
centerMarker.mapView = naverMap.mapView
naverMap.mapView.addCameraDelegate(delegate: self)
}
// 화면 이동을 추적
func mapView(_ mapView: NMFMapView, cameraIsChangingByReason reason: Int) {
centerMarker.position = mapView.cameraPosition.target
}
// 화면 이동을 추적
func mapView(_ mapView: NMFMapView, cameraDidChangeByReason reason: Int, animated: Bool) {
centerMarker.position = mapView.cameraPosition.target
}
// 이동이 끝났을 때 좌표값 print
func mapViewCameraIdle(_ mapView: NMFMapView) {
print(mapView.cameraPosition.target)
}
}
위와 같이 코딩하면 콘솔 창에 드래그가 끝날 때마다 좌표값이 반환되는 것을 볼 수 있다.
결과물은 아래와 같다.
이 기능을 이용하면 <택시팟>에 구현한 기능처럼 Naver Cloud API를 활용해서 실시간으로 주소로 변환도 가능하다.
또 출발점과 도착지점을 설정하면 내비게이션처럼 최적의 길을 표시해주기도 한다.
이 부분은 다음 글에서 다뤄보겠다.
'# 개발 > Swift' 카테고리의 다른 글
[iOS] SOLID 원칙 (feat. Swift로 알아보는..) (0) | 2024.05.27 |
---|---|
[iOS] NaverMap - Clustering(클러스터링) (0) | 2024.05.24 |
[iOS] NaverMap 지도 객체 (0) | 2024.05.15 |
[iOS] NaverMap 기본 설정 (feat. CocoaPods & 클라이언트ID 발급) (0) | 2024.05.12 |
[GameKit] 게임센터를 활용해서 데이터 공유하기 (0) | 2024.05.12 |