首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用选择器将mapType更改为.satellite等

使用选择器将mapType更改为.satellite等
EN

Stack Overflow用户
提问于 2022-03-29 04:52:56
回答 1查看 509关注 0票数 0

我希望能够将mapType从.standard更改为xCode 13.3中的.satellite和.hybrid,有人能告诉我这段代码是否可能吗?我执行了一个选择器来完成这项工作,但不幸的是,我无法使它工作。我成功地用不同的代码更改了它,但是按钮map +和map -将不再工作了。

代码语言:javascript
复制
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的代码,但是按钮不再工作了:

代码语言:javascript
复制
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),但没有区别。以下是我的变化:

代码语言:javascript
复制
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
            }
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-31 20:23:02

因此,要使用MKMapView,我们需要正确地设置UIViewRepresentableMKMapView有一个委托,因此我们需要为我们的mapView设置委托。我们通过在UIViewRepresentable中添加一个协调员来做到这一点

因此,这里有一个完整的例子,它可能不是100%完美,但它显示了一般的想法,你可以做什么。

我创建了自己的ContentView,因为您的代码缺少了几样东西(比如Quake)。

MapViewUIKit采用三个参数。

ContentView

  • The

  • A绑定对于MKCoordinateRegion,它需要是一个绑定,因为我们将将数据传递回 mapType,即MKMapType,这是用于更改映射类型
  • (注释),这是一个自定义Annotation类型,用于保存我们希望在地图上显示的注释的信息。

代码语言:javascript
复制
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结构,用于保存有关我们希望显示的注释的信息。

代码语言:javascript
复制
struct Annotation {
    let pointAnnotation: MKPointAnnotation

    init(title: String, coordinate: CLLocationCoordinate2D) {
        pointAnnotation = MKPointAnnotation()
        pointAnnotation.title = title
        pointAnnotation.coordinate = coordinate
    }
}

最后,我们需要UIViewRepresentable来把它连接在一起。我在代码中进行了注释,以显示它的功能。

代码语言:javascript
复制
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://imgur.com/a/gH42UED

我建议你熟悉苹果的文档,并且有大量的教程可以帮助你。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71656633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档