https://developer.apple.com/videos/play/wwdc2023/10043/
https://laurentbrusa.hashnode.dev/summarising-meet-mapkit-for-swiftui-from-wwdc23
위에 분이 상세하게 정리를 잘 해주셨습니다. 한번 보고오시는 것도 괜찮습니다
저는 해당 내용을 한국 버전으로 설명해보겠습니다!!!!
Map을 지도에 표시해보자!!!
import SwiftUI
import MapKit
struct ContentView: View {
var body: some View {
Map ()
}
}
끝 엄청 쉽습니다!!!!
지도의 Marker를 표시해보자!
extension CLLocationCoordinate2D {
static let lotteTower = CLLocationCoordinate2D(latitude: 37.5125, longitude: 127.102778)
}
struct ContentView: View {
var body: some View {
Map() {
Marker("lotteTower", coordinate: .lotteTower)
}
}
}
롯데타워를 찍어볼 거예요!!!
기본적으로 Marker를 하나 찍는다면 지도가 켜질 때 마커를 찍은 곳으로 카메라의 초점이 맞춰집니다.
CLLocationCoordinate2D 은 Core Location 프레임워크에서 제공되는 구조체로, 지리적인 위치를 나타내는 데 사용됩니다. 이 구조체는 위도(latitude)와 경도(longitude)의 두 속성을 가지며, 지구상의 특정 지점을 나타냅니다.
Marker는 기본적으로 LLocationCoordinate2D 값을 가져요. 어디인지 알아야 찍어주겠죠??
커스텀 Marker를 만들어보자
Marker는 기본적인 pin의 View를 보여주지만, Annotation을 사용하면 커스텀을 통해 보여주고 싶은 pin을 찍을 수 있어요.
//
// ContentView.swift
// MapKitStudy
//
// Created by 정정욱 on 1/7/24.
//
import SwiftUI
import MapKit
extension CLLocationCoordinate2D {
static let lotteTower = CLLocationCoordinate2D(latitude: 37.5125, longitude: 127.102778)
}
struct ContentView: View {
var body: some View {
Map() {
Annotation("lotteTower", coordinate: .lotteTower) {
ZStack {
RoundedRectangle(cornerRadius: 5)
.fill(.background)
RoundedRectangle(cornerRadius: 5)
.stroke(.secondary, lineWidth: 5)
Image(systemName: "house.circle.fill")
.padding(5)
}
}
.annotationTitles(.hidden) // 제목 감추기
}
}
}
#Preview {
ContentView()
}
mapStyle을 알아보자!!!!
apple은 다양한 MapStyle을 제공해 주고 있습니다.
지금 저희가 보고 있는 지도의 style은
.mapStyle(.standard)
이것이 표준 지도 스타일입니다. 기본적으로 실제 종이 지도와 매우 유사한 평면 프레젠테이션을 제공합니다.
.mapStyle(.imagery(elevation: .realistic))
해당 스타일은 위성 사진을 이용하여 지도를 표시합니다.
.mapStyle(.hybrid(elevation: .realistic))
하이브리드 지도 스타일은 다양한 도로 표지판까지 보여줍니다.
심화 과정 1 : 찾고 싶은 장소를 찾아봅시다!!! ex (주차장, 병원)
지도에서 롯데타워 근처 주차장, 병원을 찾아볼 거예요
따라오시는 여러분은 다른 장소를 찾아서 확인해 보세요!!!!
조금이라고 응용해 봐야 자기 것이 됩니다!!! ㅎㅎ
MKLocalSearch를 사용하여 lotteTower 근처의 특정 장소를 찾아보겠습니다.
우선 검색 버튼을 만들어 보겠습니다
//
// BeantownButtonView.swift
// MapKitStudy
//
// Created by 정정욱 on 1/7/24.
//
import SwiftUI
import MapKit
struct BeanTownButtons: View {
@Binding var searchResults: [MKMapItem]
var body: some View {
HStack {
Button {
search(for: "parking")
} label: {
Label("parking lot", systemImage: "car")
}
.buttonStyle(.borderedProminent)
Button {
search(for: "hospital")
} label: {
Label("restroom", systemImage: "cross.case")
}
.buttonStyle(.borderedProminent)
}
.labelStyle(.iconOnly)
}
func search(for query: String) {
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = query
request.resultTypes = .pointOfInterest
request.region = MKCoordinateRegion(
center: .lotteTower,
span: MKCoordinateSpan (latitudeDelta: 0.0125, longitudeDelta: 0.0125)
)
Task {
let search = MKLocalSearch(request: request)
let response = try? await search.start()
searchResults = response?.mapItems ?? []
}
}
}
중점적으로 봐야할 부분은 search함수 내부 코드 입니다.
func search(for query: String) {
// MKLocalSearch의 Request를 생성하여 검색 조건을 설정합니다.
let request = MKLocalSearch.Request()
// 검색할 키워드를 설정합니다.
request.naturalLanguageQuery = query
// 검색 결과의 타입을 관심 지점(POI)으로 설정합니다.
request.resultTypes = .pointOfInterest
// 검색을 수행할 지역을 설정합니다. 여기서는 .lotteTower 위치 주변으로 설정합니다.
request.region = MKCoordinateRegion(
center: .lotteTower,
span: MKCoordinateSpan(latitudeDelta: 0.0125, longitudeDelta: 0.0125)
)
// 비동기 함수로서의 Task를 사용하여 검색을 시작합니다.
Task {
// MKLocalSearch 객체를 생성합니다.
let search = MKLocalSearch(request: request)
// 검색을 비동기로 실행하고 결과를 받아옵니다.
let response = try? await search.start()
// 검색 결과를 searchResults에 업데이트합니다.
searchResults = response?.mapItems ?? []
}
}
쉽게 설명하면 버튼을 누르면 롯데타워 근처 주차장과 병원이 검색됩니다.
MKLocalSearch.Request(): MKLocalSearch.Request()는 MapKit에서 제공하는 지역 검색 요청 객체를 생성하는 메서드입니다. 이 객체를 사용하여 검색에 필요한 매개변수를 설정할 수 있습니다.
쉽게 설명하면 버튼을 누르면 롯데타워 근처 주차장과 병원이 검색됩니다.
예를 들어, 검색할 키워드, 검색 결과의 타입, 검색을 수행할 지역 등을 설정할 수 있습니다.
애플이 만든 거라 그냥 이용해서 사용하면 됩니다. 하하 항상 쉽게 쉽게 생각하고 사용합시다
request.resultTypes = .pointOfInterest: 이 부분은 생성한 MKLocalSearch.Request 객체에 대한 설정 중 하나입니다. resultTypes 속성은 검색 결과의 타입을 나타내며, 여기서는 .pointOfInterest로 설정되어 있습니다.
이는 관심 지점(POI)을 의미하며, 주변의 특정 지점들에 대한 정보를 검색하고자 할 때 사용됩니다.
예를 들면 레스토랑, 상점, 공원 등이 관심 지점에 해당합니다. 즉 검색을 하는데 추가적인 정보를 넣어준다고 생각하면 됩니다.
MKCoordinateRegion: MKCoordinateRegion은 지도에서 특정 지역을 표현하는 데 사용되는 객체입니다. 매개변수로 받는 것은 중심 좌표(center)와 지도 영역의 스팬(span)입니다.
- center: .lotteTower: 중심 좌표를 설정합니다. 여기서는 정적으로 정의된 CLLocationCoordinate2D.lotteTower를 사용하여 Lotte Tower의 좌표를 중심으로 설정하고 있습니다.
- span: MKCoordinateSpan(latitudeDelta: 0.0125, longitudeDelta: 0.0125): 지도의 스팬을 설정합니다.
- latitudeDelta와 longitudeDelta는 각각 위도 및 경도의 변화를 나타냅니다.
- 이를 조절하여 지도의 확대 수준을 조절할 수 있습니다. 작은 값은 더 큰 확대 수준을 의미합니다.
쉽게 롯데타워 주변(위도, 경도 값을 이용하여)으로 검색 결과를 찾아서 넣어주겠다는 이야기입니다.
searchResults = response?.mapItems ?? []
MKMapItem 이 뭔가요 ?
MKMapItem은 MapKit 프레임워크에서 제공되는 클래스로, 지도 위의 특정 지점이나 장소를 나타냅니다.
MKMapItem은 주로 지도 검색 결과를 나타내거나, 특정 위치에 대한 정보를 표현하는 데 사용됩니다.
MKMapItem의 인스턴스는 일반적으로 MKLocalSearch를 사용하여 수행된 지역 검색의 결과로 반환됩니다.
각 MKMapItem은 특정 위치에 대한 정보를 가지고 있으며, 이 정보에는 위치의 이름, 주소, 좌표 등이 포함될 수 있습니다.
여러 MKMapItem을 배열로 관리하면, 지도 상에 여러 장소를 표시하거나 검색 결과를 나타낼 수 있습니다.
각 MKMapItem은 지도에 표시되는 항목의 기본 데이터를 캡슐화합니다.
예를 들어, MKMapItem을 사용하여 레스토랑, 호텔, 상점 등의 장소에 대한 정보를 가져와서 지도에 표시하거나 해당 장소로 길 안내 등의 작업을 수행할 수 있습니다.
검색 결과를 뿌려보자!!!
//
// ContentView.swift
// MapKitStudy
//
// Created by 정정욱 on 1/7/24.
//
import SwiftUI
import MapKit
extension CLLocationCoordinate2D {
static let lotteTower = CLLocationCoordinate2D(latitude: 37.5125, longitude: 127.102778)
}
struct ContentView: View {
/* 💁 검색결과를 담을 배열
MKLocalSearch와 같은 MapKit API가 장소를 표시할 때 사용하는 MKMapItem임
MKMapItem로 작업하면 Marker가 콘텐츠와 형식을 자동으로 지원해 무척 유용함
*/
@State private var searchResults: [MKMapItem] = []
var body: some View {
Map() {
Annotation("lotteTower", coordinate: .lotteTower) {
ZStack {
RoundedRectangle(cornerRadius: 5)
.fill(.background)
RoundedRectangle(cornerRadius: 5)
.stroke(.secondary, lineWidth: 5)
Image(systemName: "house.circle.fill")
.padding(5)
}
}
.annotationTitles(.hidden) // 제목 감추기
// 💁 검색 결과 마커 추가
ForEach(searchResults, id: \.self) { result in
Marker(item: result)
// 결과가 MKMapItem type이였는데
// MKMapItem로 작업하면 Marker가 콘텐츠와 형식을 자동으로 지원해서 넣어주기만 하면 끝이에요
}
}
.mapStyle(.standard)
.safeAreaInset(edge: .bottom) {
HStack {
Spacer()
// 💁 바인딩이 되어 있어서 버튼을 누르면 바로바로 결과를 확인 할 수 있어요
BeanTownButtons(searchResults: $searchResults)
.padding(.top)
Spacer()
}
.background(.ultraThinMaterial)
}
}
}
#Preview {
ContentView()
}
'APP > iOS' 카테고리의 다른 글
MapKit with SwiftUI 기초부터 심화까지 2 : MapKit 다루기 심화 과정 (0) | 2024.01.09 |
---|---|
iOS23 SkillUpThon 2주차 정리 (0) | 2023.06.22 |
iOS23 SkillUpThon 1주차 정리 (0) | 2023.06.21 |
앱의 생명주기(Life Cycle) (0) | 2023.04.16 |
12주차 : doit Swift 분석 (0) | 2022.11.21 |