맵이나 위성 이미지를 앱에 보여줄 수 있는 프레임워크입니다.
쓰는 방법을 위주로 블로깅 하겠습니다.
import MapKit
MapKit 을 쓰겠다고 선어해줍니다.
private var mapView = MKMapView()
...
view.addSubview(mapView)
mapView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
mapView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
mapView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
mapView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
mapView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
그리고 이런식으로 레이아웃을 잡아줍니다.
private extension MKMapView {
func centerToLocation(
_ location: CLLocation,
regionRadius: CLLocationDistance = 1000
) {
let coordinateRegion = MKCoordinateRegion(
center: location.coordinate,
latitudinalMeters: regionRadius,
longitudinalMeters: regionRadius
)
setRegion(coordinateRegion, animated: true)
}
}
그리고 MKMapView 를 확장해주고 위와 같은 코드를 입력해줍니다.
해당 코드는 중심 좌표를 기준으로 어느 정도의 범위를 잡을 지를 정해주는 코드입니다.
여기서 CLLocationDistance 를 쓰는 데 이는 미터 단위를 나타내는 것입니다.
따라서 위의 메서드가 의마하는 것은 location 정보를 가져와 그것을 중심으로 위,경도 1000미터를 보여주는 맵을 보여주겠다는 것입니다.
그럼 저희 한번 한강대교를 배경으로 맵을 만들어 보죠?
let initialLocation = CLLocation(latitude: 37.517496, longitude: 126.959118)
mapView.centerToLocation(initialLocation)
자 이렇게 위치를 지정하고 메서드를 사용해서 보여줄 범위를 지정해주면?
Yes!!!
잘 되네요!!!
그런데 한 가지 문제점이 있습니다. 해당 사진을 드래그 하게 된다면? 범위를 한참 벗어납니다.
private func cameraConstraining() {
let initialLocation = CLLocation(latitude: 37.517496, longitude: 126.959118)
let region = MKCoordinateRegion(
center: initialLocation.coordinate,
latitudinalMeters: 500,
longitudinalMeters: 500
)
mapView.setCameraBoundary(
MKMapView.CameraBoundary(coordinateRegion: region),
animated: true
)
let zoomRange = MKMapView.CameraZoomRange(maxCenterCoordinateDistance: 20000)
mapView.setCameraZoomRange(zoomRange, animated: true)
}
이런식으로 범위를 정해주고 줌의 범위도 정해줄 수 있습니다.
근데 이제 좀 심심하지 않으신가요 ?
자 맵은 이제 어떻게 다룰 줄 알꺼 같으면 이 맵에다가 먼가를 추가해 봅시다.
한번 이런식으로 된 것을 만들어 보도록 합시다 !!!
class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String?
let discipline: String?
let coordinate: CLLocationCoordinate2D
init(
title: String?,
locationName: String?,
discipline: String?,
coordinate: CLLocationCoordinate2D
) {
self.title = title
self.locationName = locationName
self.discipline = discipline
self.coordinate = coordinate
super.init()
}
var subtitle: String? {
return locationName
}
}
이런 식으로 된 파일을 만들어 줍니다.
참고로 위의 Artwork 는 NSObject, MKAnnotation 이라는 프로토콜을 채택하고 있습니다.
그 중 MKAnnotation 프로토콜을 잠시 알아보도록 하겠습니다.
특정 맵의 위치에 관련된 컨텐츠를 띄워줄 수 있도록 하는 protocol 입니다.
해당 프로토콜은 위와 같이 정의 되어 있습니다.
이 프로토콜은 직접적으로 맵에 보여주는 것을 하지는 않지만, MapView 가 제공하는 딜리게이트가 제공하는 MKAnnotationView 라는 오브젝트에서 먼가를 보여주고 싶다고 할때 필요합니다.
만약 특정한 맵의 위치에 먼가를 보여주고 싶다면, annotation 오브젝트를 맵뷰에 추가해주어야 합니다.
만약 맵의 좌표에 주석을 보여줄 수 있다면, 맵 뷰는 자신의 딜리게이트에 주석과 관련된 적절한 뷰를 제공합니다.
mapView(_:viewFor:) 라는 딜리게이트의 메서드를 통해서 뷰를 제공합니다.
이 프로토콜을 채택한 객체는 coordinate 라는 프로퍼티가 필요하고 나머지는 optional 입니다.
즉, MKAnnotation 을 채택한 객체를 이용해야 맵에 무엇인가를 그려줄 수 있다 이런 이야기군요. (멋지다)
다시 돌아가서 Annotation 즉 주석을 추가해 봅시다 !
let nodeulArtwork = Artwork(
title: "한강",
locationName: "노들섬",
discipline: "공원",
coordinate: CLLocationCoordinate2D(latitude: 37.517892, longitude: 126.957671)
)
mapView.addAnnotation(nodeulArtwork)
이렇게 addAnnotation 메서드를 이용해서 Annotation 을 추가해주면???
핀이 찍히네요 ㅎㅎ
그러나 먼가 이걸론 부족합니다.
그림도 띄우고 싶고, 정보도 보여주고 싶고 해주고 싶은 게 많지 않으신가요?
extension ViewController: MKMapViewDelegate {
func mapView(
_ mapView: MKMapView,
viewFor annotation: MKAnnotation
) -> MKAnnotationView? {
guard let annotation = annotation as? Artwork else { return nil }
let identifier = "artwork"
var view: MKMarkerAnnotationView
if let dequeuedView = mapView
.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView {
dequeuedView.annotation = annotation
view = dequeuedView
} else {
view = MKMarkerAnnotationView(
annotation: annotation,
reuseIdentifier: identifier
)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -10, y: 10)
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
return view
}
}
...
mapView.delegate = self
이런식으로 코드를 짜줍니다.
그리고 실행시켜보면?
이렇게 뜨게 됩니다.
이제 코드를 설명해보도록 하겠습니다.
MKAnnotation 쪽을 제대로 읽어 보신분은 어? 먼가 익숙한데? 라는 게 보이실 껍니다.
중간에 딜리게이트 관련 부분이 있는 데 당시는 이해가 안 되셨을 지도 모르셨을 텐데 바로 이 부분이 위의 코드에 들어 들어 있습니다.
바로 이게 뷰에 먼가를 보여주는 뷰입니다. 이 View 에 annotation 정보를 넣어서 보여주는 것입니다.
view = MKMarkerAnnotationView(
annotation: annotation,
reuseIdentifier: identifier
)
바로 이 부분
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -10, y: 10)
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
그리고 이 부분은 핀이 클릭 될떄 나오는 뷰와 관련된 부분입니다.
https://www.kodeco.com/7738344-mapkit-tutorial-getting-started#toc-anchor-002