Вопрос или проблема
У меня есть карта с яблоками пред–определенными элементами, такими как “пляжи”. И я установил несколько собственных маркеров (которые показывают “мои пляжи”).
Маркеры установлены следующим образом:
private let myMarkers: [(id: Int, name: String, coordinate: CLLocationCoordinate2D)] = [
(1, "Apple Developer Academy", CLLocationCoordinate2D(latitude: 40.836639, longitude: 14.306602)),
(2, "Ресторан", CLLocationCoordinate2D(latitude: 40.834890, longitude: 14.304400)),
(3, "Кофейня", CLLocationCoordinate2D(latitude: 40.836901, longitude: 14.302562)),
(4, "Пляж", CLLocationCoordinate2D(latitude: 54.41621, longitude: 10.18242))
]
Когда я инициализирую карту, я определяю “позицию” и “выбор” (как указано ниже).
Теперь:
Если у меня только элементы карты Apple, я объявляю:
@State private var mySelectedAppleItem: MKMapItem?
и инициализирую:
Map(position: $position, selection: $mySelected**AppleItem**) {//
Тип: MKMapItem
И:
Если у меня только “Элементы”-Карт (которые, если я вижу это правильно, не являются MKMapItems, а “только” отмеченными местами), я объявляю:
@State private var mySelectedTag: Int?
и инициализирую:
Map(position: $position, selection: $mySelected**Tag**) {//
Тип: Int
Итак:
Когда я выбираю выбор Apple (selection: $mySelectedAppleItem), я могу легко выбрать элементы Apple, но мои собственные маркеры, хотя и отмечены тегом, НЕ выбираются. А когда я выбираю свой выбор (selection: $mySelectedTag), я могу выбрать только свои отмеченные маркеры.
Вот мой вопрос: Есть ли способ, чтобы я мог выбирать ОБА? Например, через расширение MapItem (могу ли я объявить свои “элементы” как “элементы Mapkit”?)
Большое спасибо!
Я много искал, но не смог найти ни одной статьи на эту тему.
Ответ или решение
Вам нужно создать возможность выбора как MKMapItem (предопределенные элементы карты Apple), так и собственных маркеров (например, "мои пляжи") в приложении на SwiftUI, использующем MapKit. К сожалению, в SwiftUI Map, которое по умолчанию предоставляет селектор, нельзя напрямую смешивать разные типы выбора (MKMapItem и Int). Однако, вы можете обойти это ограничение, создав вместе с отдельными элементами карту с кастомизированными маркерами.
Ниже приведен подход к решению вашей задачи. Мы будем использовать один объединенный тип для выбора элементов, что позволит комбинировать данные из различных источников.
Шаги для реализации решения
- Создайте объединяющую структуру: Создайте тип данных, который будет представлять как
MKMapItem
, так и ваши собственные маркеры.
import SwiftUI
import MapKit
// Объединяющий тип для выбора как MKMapItem, так и ваших собственных маркеров
enum MapItemType {
case appleItem(MKMapItem)
case customMarker((id: Int, name: String, coordinate: CLLocationCoordinate2D))
}
struct MapAnnotationView: View {
var item: MapItemType
var body: some View {
switch item {
case .appleItem(let mapItem):
Text(mapItem.name ?? "Unknown")
.padding(5)
.background(Color.blue)
.cornerRadius(5)
case .customMarker(let marker):
Text(marker.name)
.padding(5)
.background(Color.green)
.cornerRadius(5)
}
}
}
- Передайте данные в карту: Используйте
Map
из SwiftUI с общим типом выбора.
@State private var selectedMapItem: MapItemType? = nil
var body: some View {
Map(position: $position, selection: $selectedMapItem) {
ForEach(myMarkers, id: \.id) { marker in
MapAnnotation(coordinate: marker.coordinate, anchorPoint: CGPoint(x: 0.5, y: 0.5)) {
MapAnnotationView(item: .customMarker(marker))
.onTapGesture {
selectedMapItem = .customMarker(marker)
}
}
}
// Добавление Apple MKMapItems
ForEach(appleMapItems, id: \.self) { mapItem in
MapAnnotation(coordinate: mapItem.placemark.coordinate, anchorPoint: CGPoint(x: 0.5, y: 0.5)) {
MapAnnotationView(item: .appleItem(mapItem))
.onTapGesture {
selectedMapItem = .appleItem(mapItem)
}
}
}
}
}
- Отображение выбранного элемента: Обработайте отображение информации о выбранном элементе.
if let selectedItem = selectedMapItem {
switch selectedItem {
case .appleItem(let mapItem):
Text("Выбранный Apple элемент: \(mapItem.name ?? "Неизвестно")")
case .customMarker(let marker):
Text("Выбранный собственный маркер: \(marker.name)")
}
}
Заключение
Этот подход позволяет вам комбинировать как стандартные элементы карты от Apple, так и собственные маркеры, используя единый тип для выбора. Вы можете легко адаптировать логику показов и действий в зависимости от выбранного элемента. Надеюсь, этот ответ поможет вам реализовать необходимую функциональность в вашем приложении.