我希望能够将mapType从.standard更改为xCode 13.3中的.satellite和.hybrid,有人能告诉我这段代码是否可能吗?我执行了一个选择器来完成这项工作,但不幸的是,我无法使它工作。我成功地用不同的代码更改了它,但是按钮map +和map -将不再工作了。
import Foundation
import SwiftUI
import MapKit
struct QuakeDetail: View {
var quake: Quake
@State private var region : MKCoordinateRegion
init(quake : Quake) {
self.quake = quake
_region = State(wrappedValue: MKCoordinateRegion(center: quake.coordinate,
span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10)))
}
@State private var mapType: MKMapType = .standard
var body: some View {
VStack {
Map(coordinateRegion: $region, annotationItems: [quake]) { item in
MapMarker(coordinate: item.coordinate, tint: .red)
} .ignoresSafeArea()
HStack {
Button {
region.span.latitudeDelta *= 0.5
region.span.longitudeDelta *= 0.5
} label: {
HStack {
Text("map")
Image(systemName: "plus")
}
}.padding(5)//.border(Color.blue, width: 1)
Spacer()
QuakeMagnitude(quake: quake)
Spacer()
Button {
region.span.latitudeDelta /= 0.5
region.span.longitudeDelta /= 0.5
} label: {
HStack {
Text("map")
Image(systemName: "minus")
}
}
}.padding(.horizontal)
Text(quake.place)
.font(.headline)
.bold()
Text("\(quake.time.formatted())")
.foregroundStyle(Color.secondary)
Text("\(quake.latitude) \(quake.longitude)")
VStack {
Picker("", selection: $mapType) {
Text("Standard").tag(MKMapType.standard)
Text("Satellite").tag(MKMapType.satellite)
Text("Hybrid").tag(MKMapType.hybrid)
}
.pickerStyle(SegmentedPickerStyle())
.font(.largeTitle)
}
}
}
}下面是更改mapType的代码,但是按钮不再工作了:
import Foundation
import SwiftUI
import MapKit
struct QuakeDetail: View {
var quake: Quake
@State private var region : MKCoordinateRegion
init(quake : Quake) {
self.quake = quake
_region = State(wrappedValue: MKCoordinateRegion(center: quake.coordinate,
span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10)))
}
@State private var mapType: MKMapType = .standard
var body: some View {
VStack {
MapViewUIKit(region: region, mapType: mapType)
.edgesIgnoringSafeArea(.all)
HStack {
Button {
region.span.latitudeDelta *= 0.5
region.span.longitudeDelta *= 0.5
} label: {
HStack {
Text("map")
Image(systemName: "plus")
}
}.padding(5)//.border(Color.blue, width: 1)
Spacer()
QuakeMagnitude(quake: quake)
Spacer()
Button {
region.span.latitudeDelta /= 0.5
region.span.longitudeDelta /= 0.5
} label: {
HStack {
Text("map")
Image(systemName: "minus")
}
}
}.padding(.horizontal)
Text(quake.place)
.font(.headline)
.bold()
Text("\(quake.time.formatted())")
.foregroundStyle(Color.secondary)
Text("\(quake.latitude) \(quake.longitude)")
Picker("", selection: $mapType) {
Text("Standard").tag(MKMapType.standard)
Text("Satellite").tag(MKMapType.satellite)
Text("Hybrid").tag(MKMapType.hybrid)
//Text("Hybrid flyover").tag(MKMapType.hybridFlyover)
}
.pickerStyle(SegmentedPickerStyle())
.font(.largeTitle)
}
}
}
struct MapViewUIKit: UIViewRepresentable {
let region: MKCoordinateRegion
let mapType : MKMapType
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.setRegion(region, animated: false)
mapView.mapType = mapType
return mapView
}
func updateUIView(_ mapView: MKMapView, context: Context) {
mapView.mapType = mapType
}
}我实现了代码,现在按钮工作正常,mapType更改正确,也非常感谢您提供了指向文档的指针。不幸的是,注释没有在地震地点显示引脚。我将标题从伦敦更改为quake.place,坐标改为坐标:CLLocationCoordinate2D(纬度: region.span.latitudeDelta,经度: region.span.longitudeDelta),但没有区别。以下是我的变化:
import SwiftUI
import MapKit
struct QuakeDetail: View {
var quake: Quake
@State private var region : MKCoordinateRegion
init(quake : Quake) {
self.quake = quake
_region = State(wrappedValue: MKCoordinateRegion(center: quake.coordinate,
span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10)))
}
@State private var mapType: MKMapType = .standard
var body: some View {
VStack {
MapViewUIKit(
region: $region,
mapType: mapType,
annotation: Annotation(
title: quake.place,
coordinate: CLLocationCoordinate2D(latitude: region.span.latitudeDelta, longitude: region.span.longitudeDelta)
) // annotation
).ignoresSafeArea() // MapViewUIKit
Spacer()
HStack {
Button {
region.span.latitudeDelta *= 0.5
region.span.longitudeDelta *= 0.5
} label: {
HStack {
Image(systemName: "plus")
}
}//.padding(5)
Spacer()
QuakeMagnitude(quake: quake)
Spacer()
Button {
region.span.latitudeDelta /= 0.5
region.span.longitudeDelta /= 0.5
} label: {
HStack {
Image(systemName: "minus")
}
}
}.padding(.horizontal) // HStack + - buttons and quake magnitude
Text(quake.place)
Text("\(quake.time.formatted())")
.foregroundStyle(Color.secondary)
Text("\(quake.latitude) \(quake.longitude)")
.padding(.bottom, -5)
Picker("", selection: $mapType) {
Text("Standard").tag(MKMapType.standard)
Text("Satellite").tag(MKMapType.satellite)
Text("Hybrid").tag(MKMapType.hybrid)
}
.pickerStyle(SegmentedPickerStyle())
}
}
}
struct Annotation {
let pointAnnotation: MKPointAnnotation
init(title: String, coordinate: CLLocationCoordinate2D) {
pointAnnotation = MKPointAnnotation()
pointAnnotation.title = title
pointAnnotation.coordinate = coordinate
}
}
struct MapViewUIKit: UIViewRepresentable {
@Binding var region: MKCoordinateRegion
let mapType : MKMapType
let annotation: Annotation
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.setRegion(region, animated: false)
mapView.mapType = mapType
// Set the delegate so that we can listen for changes and
// act appropriately
mapView.delegate = context.coordinator
// Add the annotation to the map
mapView.addAnnotation(annotation.pointAnnotation)
return mapView
}
func updateUIView(_ mapView: MKMapView, context: Context) {
mapView.mapType = mapType
// Update your region so that it is now your new region
mapView.setRegion(region, animated: true)
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, MKMapViewDelegate {
var parent: MapViewUIKit
init(_ parent: MapViewUIKit) {
self.parent = parent
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// We should handle dequeue of annotation view's properly so we have to write this boiler plate.
// This basically dequeues an MKAnnotationView if it exists, otherwise it creates a new
// MKAnnotationView from our annotation.
guard annotation is MKPointAnnotation else { return nil }
let identifier = "Annotation"
guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) else {
let annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.canShowCallout = true
return annotationView
}
annotationView.annotation = annotation
return annotationView
}
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
// We need to update the region when the user changes it
// otherwise when we zoom the mapview will return to its original region
DispatchQueue.main.async {
self.parent.region = mapView.region
}
}
}
}发布于 2022-03-31 20:23:02
因此,要使用MKMapView,我们需要正确地设置UIViewRepresentable。MKMapView有一个委托,因此我们需要为我们的mapView设置委托。我们通过在UIViewRepresentable中添加一个协调员来做到这一点
因此,这里有一个完整的例子,它可能不是100%完美,但它显示了一般的想法,你可以做什么。
我创建了自己的ContentView,因为您的代码缺少了几样东西(比如Quake)。
MapViewUIKit采用三个参数。
ContentView
MKCoordinateRegion,它需要是一个绑定,因为我们将将数据传递回 mapType,即MKMapType,这是用于更改映射类型Annotation类型,用于保存我们希望在地图上显示的注释的信息。struct ContentView: View {
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(
latitude: 51.507222,
longitude: -0.1275),
span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
)
@State private var mapType: MKMapType = .standard
var body: some View {
VStack {
Picker("", selection: $mapType) {
Text("Standard").tag(MKMapType.standard)
Text("Satellite").tag(MKMapType.satellite)
Text("Hybrid").tag(MKMapType.hybrid)
}
.pickerStyle(SegmentedPickerStyle())
MapViewUIKit(
region: $region,
mapType: mapType,
annotation: Annotation(
title: "London",
coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275)
)
)
HStack {
Button {
region.span.latitudeDelta *= 0.5
region.span.longitudeDelta *= 0.5
} label: {
HStack {
Image(systemName: "plus")
}
}.padding(5)
Button {
region.span.latitudeDelta /= 0.5
region.span.longitudeDelta /= 0.5
} label: {
HStack {
Image(systemName: "minus")
}
}.padding(5)
}
}
}
}这是我创建的Annotation结构,用于保存有关我们希望显示的注释的信息。
struct Annotation {
let pointAnnotation: MKPointAnnotation
init(title: String, coordinate: CLLocationCoordinate2D) {
pointAnnotation = MKPointAnnotation()
pointAnnotation.title = title
pointAnnotation.coordinate = coordinate
}
}最后,我们需要UIViewRepresentable来把它连接在一起。我在代码中进行了注释,以显示它的功能。
struct MapViewUIKit: UIViewRepresentable {
@Binding var region: MKCoordinateRegion
let mapType : MKMapType
let annotation: Annotation
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.setRegion(region, animated: false)
mapView.mapType = mapType
// Set the delegate so that we can listen for changes and
// act appropriately
mapView.delegate = context.coordinator
// Add the annotation to the map
mapView.addAnnotation(annotation.pointAnnotation)
return mapView
}
func updateUIView(_ mapView: MKMapView, context: Context) {
mapView.mapType = mapType
// Update your region so that it is now your new region
mapView.setRegion(region, animated: true)
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, MKMapViewDelegate {
var parent: MapViewUIKit
init(_ parent: MapViewUIKit) {
self.parent = parent
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// We should handle dequeue of annotation view's properly so we have to write this boiler plate.
// This basically dequeues an MKAnnotationView if it exists, otherwise it creates a new
// MKAnnotationView from our annotation.
guard annotation is MKPointAnnotation else { return nil }
let identifier = "Annotation"
guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) else {
let annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.canShowCallout = true
return annotationView
}
annotationView.annotation = annotation
return annotationView
}
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
// We need to update the region when the user changes it
// otherwise when we zoom the mapview will return to its original region
DispatchQueue.main.async {
self.parent.region = mapView.region
}
}
}
}这提供了以下输出
我建议你熟悉苹果的文档,并且有大量的教程可以帮助你。
https://developer.apple.com/documentation/mapkit/mkmapview https://developer.apple.com/documentation/mapkit/mkmapviewdelegate https://www.raywenderlich.com/7738344-mapkit-tutorial-getting-started https://www.hackingwithswift.com/example-code/location/how-to-add-annotations-to-mkmapview-using-mkpointannotation-and-mkpinannotationview https://talk.objc.io/episodes/S01E195-wrapping-map-view
https://stackoverflow.com/questions/71656633
复制相似问题