SwiftUI - Mapkit - 绑定 mapkit 并在注释标注按钮上显示视图 [英] SwiftUI - Mapkit - Binding mapkit and show view on annotation callout buttons

查看:66
本文介绍了SwiftUI - Mapkit - 绑定 mapkit 并在注释标注按钮上显示视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个SwiftUI应用程序,其中显示了一个地图(使用UIViewRepresentable制作的Mapkit)并显示了不同的注释.在每个注释上,我都实现了一个标注按钮,并且我想在按下按钮时完全更改主视图.

I have a SwiftUI app where I show a map (using Mapkit made with UIViewRepresentable) with different annotations being displayed. On each annotation, I have implemented a callout button and I would like to completely change the main View when the button is pressed.

我的想法是使用主视图和地图视图的状态/绑定参数.这个想法可行,但是在使用地图视图"的方式来实现状态/绑定时,我遇到了一些困难.困难在于我将地图用作第二个视图的参数,该视图包含与地图进行交互的菜单.我试图更改我使用地图视图的方式,但没有找到任何解决方案...

My idea was to use a State/Binding parameter of the main view and the mapView. The idea works but I have some difficulties to implement the State/Binding with the way I use the Map View. The difficulty is that I am using the map as a parameter for a second view containing the menu to interact with the map. I tried to change how I use the map view but I did not find any solution...

我的想法是在主体之前创建地图: @State var map = MapView(displaySP:$ displayStorePage),但我做不到(错误:无法在其中使用实例成员'$ displayStorePage'属性初始值设定项;属性初始值设定项在'self'可用之前运行)

My idea was to create the map : @State var map = MapView(displaySP: $displayStorePage) before body but I can not do it (err : Cannot use instance member '$displayStorePage' within property initializer; property initializers run before 'self' is available)

非常欢迎任何帮助:)

显示其他代码,我试图做最轻的版本.

edit: Additional code display, I tried to do the lightest version.

因此在代码中,目标是从激活的用于注释单击的Mapview函数中切换Mainview中的 displayStorePage .:UIControl)

So in the code, the goal is to toggle the displayStorePage in Mainview from the Mapview function activated for annotation click func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl)

主视图:

import SwiftUI
import MapKit

struct MainView: View {
    @State var researchStore: String = ""
    @State var displayStorePage: Bool = false
    @State var map = MapView()
    
    var body: some View {
        ZStack{
            if displayStorePage == false {
                VStack{
                  map.frame(height: 400)
                }
            TopMapMenu(map: $map)
            }
            
            if displayStorePage == true {
                Text("This is a win !")
                }
            
            }
        }
    }

MapKit视图:

import Combine

var storeLocation = [MKAnnotation]()
var newAnnotation = MKPointAnnotation()

let mapView = MKMapView()
var displayRedMarker: Bool = true
var displayStore: Bool = false


struct MapView: UIViewRepresentable {

    class Coordinator: NSObject, MKMapViewDelegate{
        var parent : MapView

        init(_ parent: MapView){
            self.parent = parent
        }
        
        
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "AnnotationView")
            
                annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "AnnotationView")
            
            let annotationLabel = UILabel(frame: CGRect(x: -25, y: 12, width: 105, height: 30))
            if displayRedMarker {
            annotationLabel.text = annotation.title!!
            } else {
            annotationLabel.text = "Annotation to be hidden"
            }
            
            //Other markers done there ....

            annotationView?.canShowCallout = true
            let btn = UIButton(type: .detailDisclosure)
                        annotationView?.rightCalloutAccessoryView = btn
            return annotationView
        }
        
        // Gestion click Annotation button
        func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
               // Here : Changing the Main View parameter : displayStorePage to true
        }
        
}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    
    func makeUIView(context: Context) -> some UIView {
        
       
        let region = MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: 47.510053, longitude: 6.798374),
            span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
        
        mapView.delegate = context.coordinator
        mapView.showsUserLocation = true
        mapView.setRegion(region, animated: false)
        
        mapView.addAnnotation(AddAnnotations())
        
        return mapView
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        
    }
 
    func AddAnnotations() -> MKAnnotation {
        
        newAnnotation = MKPointAnnotation()
        newAnnotation.title = "Title1"
        newAnnotation.coordinate = CLLocationCoordinate2D(latitude: 47.510053, longitude: 6.798374)
        
        return newAnnotation
    }
    
}

TopMenuMap:

struct TopMapMenu: View {
    
     @Binding var map : MapView
     @State var searching: Bool = false
     @State var redStore: Bool = true
     @State var storeFound : Bool = false
    
    var body: some View {
            
                HStack{
                    VStack(alignment: .leading, spacing: 10){
                        
                        Button(action: {
                            displayRedMarker.toggle()
                         //   map.DeleteMarkers()
                         //   map.AddMarkers()
                            redStore = displayRedMarker
                        }) {
                            HStack {
                            if redStore { Image(systemName: "heart.fill") }
                            else { Image(systemName: "heart") }
                                
                                Text("Restaurant")
                                }
                            Spacer()
                                .background(Color(.white))
                            }
                        // Other Buttons(Pins) are display here
                    }// End VStack Pin stores
                }
    }
}

推荐答案

import SwiftUI
import MapKit
class Store: Identifiable, ObservableObject {
    let id: UUID = UUID()
    @Published var title: String?
    @Published var latitude: Double
    @Published var longitude: Double
    @Published var displayStoreImage: Bool
    @Published var displayRedMarker: Bool
    @Published var redStore: Bool
    init(title: String, latitude: Double , longitude: Double, displayStoreImage: Bool, displayRedMarker: Bool, redStore: Bool ) {
        self.title = title
        self.latitude = latitude
        self.longitude = longitude
        self.displayRedMarker = displayRedMarker
        self.displayStoreImage = displayStoreImage
        self.redStore = redStore
        
    }
}
extension Store{
    var coordinate: CLLocationCoordinate2D{
        get{
            return CLLocationCoordinate2D(latitude: self.latitude, longitude: self.longitude)
        }
    }
}

struct MapViewParent: View {
    @State var selectedListing: Store?
    @State var results: [Store] = [Store(title: "Point 1 title", latitude: 38.3 , longitude: 123.2, displayStoreImage: true, displayRedMarker: true, redStore: false ), Store(title: "Point 2 title", latitude: 38.4 , longitude: 123.1, displayStoreImage: true, displayRedMarker: false, redStore: true )
    ]
    var body: some View {
        VStack{
            Button("clear-storepage", action: {
                selectedListing = nil
            })
            if selectedListing != nil{
                TopMapMenu(results: $results, selectedListing: $selectedListing)
            }else{
                MapViewAnnotations(selectedListing: $selectedListing, results: $results)
            }
        }
    }
}
struct MapViewAnnotations: View {
    @State var region: MKCoordinateRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 38.3 , longitude: 123.2 ), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
    
    @Binding var selectedListing: Store?
    @Binding var results: [Store]
    
    var body: some View {
        Map(coordinateRegion: $region, annotationItems: results, annotationContent: {
            listing in
            MapAnnotation(coordinate: listing.coordinate, content: {
                Button(action: {
                    self.selectedListing = listing as Store?
                    self.region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: listing.coordinate.latitude , longitude: listing.coordinate.longitude ), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
                }, label: {
                    if listing.displayStoreImage{
                        if listing.displayRedMarker{
                            Image(systemName: "mappin.circle.fill").foregroundColor(.red).contentShape(Circle())
                        }else{
                            Image(systemName: "mappin").foregroundColor(.green).contentShape(Circle())
                        }
                    }
                    else{
                        Image(systemName: "mappin.circle.fill").foregroundColor(.red).contentShape(Circle())
                    }
                }).buttonStyle(PlainButtonStyle())
            })
        })
        
    }
}

struct TopMapMenu: View {
    @Binding var results: [Store]
    @Binding var selectedListing: Store?
    var body: some View {
        List{
            ForEach(results, id: \.id){store in
                StoreView(store: store, selectedListing: $selectedListing, results: $results)
            }
        }
    }
}
struct StoreView: View {
    @ObservedObject var store: Store
    @Binding var selectedListing: Store?
    @Binding var results: [Store]
    var body: some View{
        HStack{
            VStack(alignment: .leading, spacing: 10){
                Button(action: {
                    store.displayRedMarker.toggle()
                    store.redStore = store.displayRedMarker
                }, label: {
                    HStack {
                        if store.redStore {
                            Image(systemName: "heart.fill")
                        }
                        else { Image(systemName: "heart") }
                        
                        Text("Restaurant")
                    }
                    Spacer()
                        .background(Color(.white))
                }
                )}
            MapViewAnnotations(selectedListing: $selectedListing, results: Binding(get: {
                return [store]
            }, set: {
                let idx = results.firstIndex(where: {
                    store.id == $0.id
                })
                if idx != nil && $0.first != nil{
                    results[idx!] = $0.first!
                }
            }))
        }
    }
}
struct MapViewParent_Previews: PreviewProvider {
    static var previews: some View {
        MapViewParent()
    }
}

这篇关于SwiftUI - Mapkit - 绑定 mapkit 并在注释标注按钮上显示视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆