Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swiftui didSelect上的MapKit/MKMapViewDelegate:底页不';如果启用了用户位置,则无法打开_Swiftui_Mapkit_Core Location_Mapkitannotation_Mkmapviewdelegate - Fatal编程技术网

Swiftui didSelect上的MapKit/MKMapViewDelegate:底页不';如果启用了用户位置,则无法打开

Swiftui didSelect上的MapKit/MKMapViewDelegate:底页不';如果启用了用户位置,则无法打开,swiftui,mapkit,core-location,mapkitannotation,mkmapviewdelegate,Swiftui,Mapkit,Core Location,Mapkitannotation,Mkmapviewdelegate,我正在尝试在iOS上重建Apple Maps的注释选择行为。如果我点击地图上的图钉,它会打开一张底部的纸,上面有关于这个地方的更多信息 虽然已经对所有基本组件进行了编码,但如果在地图上启用了用户位置,则我的底部工作表不会打开 如果启用了用户位置,为什么底部工作表不打开?我真的很感谢你的意见。谢谢 如何复制它: 根据要测试的内容,在MapMainView.swift中更改变量showCurrentLocation 请不要忘记添加Info.plist条目Privacy-Location In U

我正在尝试在iOS上重建Apple Maps的注释选择行为。如果我点击地图上的图钉,它会打开一张底部的纸,上面有关于这个地方的更多信息

虽然已经对所有基本组件进行了编码,但如果在地图上启用了用户位置,则我的底部工作表不会打开

如果启用了用户位置,为什么底部工作表不打开?我真的很感谢你的意见。谢谢

如何复制它:

  • 根据要测试的内容,在
    MapMainView.swift
    中更改变量
    showCurrentLocation
  • 请不要忘记添加
    Info.plist
    条目
    Privacy-Location In Use Description
    Privacy-Location Always Usage Description
    ,以访问设备的本机位置
  • ContentView.swift

    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            MapMainView()
        }
    }
    
    import Foundation
    import SwiftUI
    import MapKit
    
    struct MapMainView: View {
        let showCurrentLocation = false
        let locationFetcher = LocationFetcher()
        @State var selectedPin: MapPin? = nil
        @State var isBottomSheetOpen: Bool = false
        @State var examplePins = [MapPin]()
    
        var body: some View {
            GeometryReader { geometry in
                ZStack() {
                    VStack() {
                        Spacer()
                        BottomSheetView(isOpen: self.$isBottomSheetOpen, maxHeight: geometry.size.height * 0.3) {
                            Text(String(self.selectedPin?.title ?? "no title")).foregroundColor(Color.black)
                        }
                    }
                    .edgesIgnoringSafeArea(.all)
                    .zIndex(1)
                
                    MapView(locationFetcher: self.locationFetcher, showCurrentLocation: self.showCurrentLocation, displayedPins: self.$examplePins, selectedPin: self.$selectedPin, isBottomSheetOpen: self.$isBottomSheetOpen)
                        .edgesIgnoringSafeArea(.all)
                        .onAppear{
                            var currentLat: Double
                            var currentLng: Double
                        
                            if self.showCurrentLocation {
                                currentLat = self.locationFetcher.getCurrentCoordinates()?.latitude ?? 46.9457590197085
                                currentLng = self.locationFetcher.getCurrentCoordinates()?.longitude ?? 8.007923669708498
                            } else {
                                currentLat = 46.9457590197085
                                currentLng = 8.007923669708498
                            }
                        
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.004, longitude: currentLng - 0.002), title: "First Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat + 0.002, longitude: currentLng + 0.002), title: "Second Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.002, longitude: currentLng + 0.004), title: "Third Pin"))
                    }
                }
            }
        }
    }
    
    class MapPin: NSObject, MKAnnotation {
        let coordinate: CLLocationCoordinate2D
        let title: String?
    
        init(coordinate: CLLocationCoordinate2D, title: String? = nil) {
            self.coordinate = coordinate
            self.title = title
        }
    }
    
    import SwiftUI
    import MapKit
    
    struct MapView: UIViewRepresentable {
        let locationFetcher: LocationFetcher
        let showCurrentLocation: Bool
        @Binding var displayedPins: [MapPin]
        @Binding var selectedPin: MapPin?
        @Binding var isBottomSheetOpen: Bool
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    
        func makeUIView(context: Context) -> MKMapView {
            let mapView = MKMapView()
            mapView.delegate = context.coordinator
        
            if showCurrentLocation {
                mapView.showsUserLocation = true
                self.locationFetcher.attemptLocationAccess()
                centerLocation(mapView: mapView, locationCoordinate: locationFetcher.getCurrentCoordinates())
            } else {
                centerLocation(mapView: mapView, locationCoordinate: CLLocationCoordinate2D(latitude: 46.9457590197085, longitude: 8.007923669708498))
            }
        
            return mapView
        }
    
        func updateUIView(_ mapView: MKMapView, context: Context) {
            if self.displayedPins.count != mapView.annotations.count {
                mapView.removeAnnotations(mapView.annotations)
                mapView.addAnnotations(self.displayedPins)
            }
        }
    
        func centerLocation(mapView: MKMapView, locationCoordinate: CLLocationCoordinate2D?) {
            if locationCoordinate != nil {
                let kilometerRadius = 1.5;
                let scalingFactor = abs((cos(2 * Double.pi * locationCoordinate!.latitude / 360.0)));
                let span = MKCoordinateSpan(latitudeDelta: kilometerRadius/111, longitudeDelta: kilometerRadius/(scalingFactor * 111))
                let region = MKCoordinateRegion(center: locationCoordinate!, span: span)
                mapView.setRegion(region, animated: true)
            }
        }
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView
    
        init(_ parent: MapView) {
            self.parent = parent
        }
    
        func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
            guard let pin = view.annotation as? MapPin else {
                return
            }
            mapView.setCenter(pin.coordinate, animated: true)
        
            DispatchQueue.main.async {
               self.parent.selectedPin = pin
               self.parent.isBottomSheetOpen = true
            }
        }
    
    
        func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
            guard (view.annotation as? MapPin) != nil else {
                return
            }
        
            DispatchQueue.main.async {
               self.parent.selectedPin = nil
               self.parent.isBottomSheetOpen = false
            }
        }
    }
    
    import Foundation
    import SwiftUI
    
    struct BottomSheetView<Content: View>: View {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
        @Binding var isOpen: Bool
    
        let maxHeight: CGFloat
        let minHeight: CGFloat
        let content: Content
    
        @GestureState private var translation: CGFloat = 0
    
        private var offset: CGFloat {
            isOpen ? 0 : maxHeight - minHeight
        }
    
        private var indicator: some View {
            RoundedRectangle(cornerRadius: Constants.RADIUS)
                .fill(Color.black)
                .frame(
                    width: Constants.INDICATOR_WIDTH,
                    height: Constants.INDICATOR_HEIGHT
            ).onTapGesture {
                self.isOpen.toggle()
            }
        }
    
        init(isOpen: Binding<Bool>, maxHeight: CGFloat, @ViewBuilder content: () -> Content) {
            self.minHeight = maxHeight * Constants.MIN_HEIGHT_RATIO
            self.maxHeight = maxHeight
            self.content = content()
            self._isOpen = isOpen
        }
    
        var body: some View {
            GeometryReader { geometry in
                VStack(spacing: 0) {
                    self.indicator.padding()
                    self.content
                }
                .frame(width: geometry.size.width, height: self.maxHeight, alignment: .top)
                .background(Color.white)
                .cornerRadius(Constants.RADIUS)
                .frame(height: geometry.size.height, alignment: .bottom)
                .offset(y: max(self.offset + self.translation, 0))
                .animation(.interactiveSpring())
                .gesture(
                    DragGesture().updating(self.$translation) { value, state, _ in
                        state = value.translation.height
                    }.onEnded { value in
                        let snapDistance = self.maxHeight * Constants.SNAP_RATIO
                        guard abs(value.translation.height) > snapDistance else {
                            return
                        }
                        self.isOpen = value.translation.height < 0
                    }
                )
            }   
        } 
    }
    
    enum Constants {
        static let RADIUS: CGFloat = 16
        static let INDICATOR_HEIGHT: CGFloat = 6
        static let INDICATOR_WIDTH: CGFloat = 60
        static let SNAP_RATIO: CGFloat = 0.25
        static let MIN_HEIGHT_RATIO: CGFloat = 0
    }
    
    MapMainView.swift

    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            MapMainView()
        }
    }
    
    import Foundation
    import SwiftUI
    import MapKit
    
    struct MapMainView: View {
        let showCurrentLocation = false
        let locationFetcher = LocationFetcher()
        @State var selectedPin: MapPin? = nil
        @State var isBottomSheetOpen: Bool = false
        @State var examplePins = [MapPin]()
    
        var body: some View {
            GeometryReader { geometry in
                ZStack() {
                    VStack() {
                        Spacer()
                        BottomSheetView(isOpen: self.$isBottomSheetOpen, maxHeight: geometry.size.height * 0.3) {
                            Text(String(self.selectedPin?.title ?? "no title")).foregroundColor(Color.black)
                        }
                    }
                    .edgesIgnoringSafeArea(.all)
                    .zIndex(1)
                
                    MapView(locationFetcher: self.locationFetcher, showCurrentLocation: self.showCurrentLocation, displayedPins: self.$examplePins, selectedPin: self.$selectedPin, isBottomSheetOpen: self.$isBottomSheetOpen)
                        .edgesIgnoringSafeArea(.all)
                        .onAppear{
                            var currentLat: Double
                            var currentLng: Double
                        
                            if self.showCurrentLocation {
                                currentLat = self.locationFetcher.getCurrentCoordinates()?.latitude ?? 46.9457590197085
                                currentLng = self.locationFetcher.getCurrentCoordinates()?.longitude ?? 8.007923669708498
                            } else {
                                currentLat = 46.9457590197085
                                currentLng = 8.007923669708498
                            }
                        
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.004, longitude: currentLng - 0.002), title: "First Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat + 0.002, longitude: currentLng + 0.002), title: "Second Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.002, longitude: currentLng + 0.004), title: "Third Pin"))
                    }
                }
            }
        }
    }
    
    class MapPin: NSObject, MKAnnotation {
        let coordinate: CLLocationCoordinate2D
        let title: String?
    
        init(coordinate: CLLocationCoordinate2D, title: String? = nil) {
            self.coordinate = coordinate
            self.title = title
        }
    }
    
    import SwiftUI
    import MapKit
    
    struct MapView: UIViewRepresentable {
        let locationFetcher: LocationFetcher
        let showCurrentLocation: Bool
        @Binding var displayedPins: [MapPin]
        @Binding var selectedPin: MapPin?
        @Binding var isBottomSheetOpen: Bool
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    
        func makeUIView(context: Context) -> MKMapView {
            let mapView = MKMapView()
            mapView.delegate = context.coordinator
        
            if showCurrentLocation {
                mapView.showsUserLocation = true
                self.locationFetcher.attemptLocationAccess()
                centerLocation(mapView: mapView, locationCoordinate: locationFetcher.getCurrentCoordinates())
            } else {
                centerLocation(mapView: mapView, locationCoordinate: CLLocationCoordinate2D(latitude: 46.9457590197085, longitude: 8.007923669708498))
            }
        
            return mapView
        }
    
        func updateUIView(_ mapView: MKMapView, context: Context) {
            if self.displayedPins.count != mapView.annotations.count {
                mapView.removeAnnotations(mapView.annotations)
                mapView.addAnnotations(self.displayedPins)
            }
        }
    
        func centerLocation(mapView: MKMapView, locationCoordinate: CLLocationCoordinate2D?) {
            if locationCoordinate != nil {
                let kilometerRadius = 1.5;
                let scalingFactor = abs((cos(2 * Double.pi * locationCoordinate!.latitude / 360.0)));
                let span = MKCoordinateSpan(latitudeDelta: kilometerRadius/111, longitudeDelta: kilometerRadius/(scalingFactor * 111))
                let region = MKCoordinateRegion(center: locationCoordinate!, span: span)
                mapView.setRegion(region, animated: true)
            }
        }
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView
    
        init(_ parent: MapView) {
            self.parent = parent
        }
    
        func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
            guard let pin = view.annotation as? MapPin else {
                return
            }
            mapView.setCenter(pin.coordinate, animated: true)
        
            DispatchQueue.main.async {
               self.parent.selectedPin = pin
               self.parent.isBottomSheetOpen = true
            }
        }
    
    
        func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
            guard (view.annotation as? MapPin) != nil else {
                return
            }
        
            DispatchQueue.main.async {
               self.parent.selectedPin = nil
               self.parent.isBottomSheetOpen = false
            }
        }
    }
    
    import Foundation
    import SwiftUI
    
    struct BottomSheetView<Content: View>: View {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
        @Binding var isOpen: Bool
    
        let maxHeight: CGFloat
        let minHeight: CGFloat
        let content: Content
    
        @GestureState private var translation: CGFloat = 0
    
        private var offset: CGFloat {
            isOpen ? 0 : maxHeight - minHeight
        }
    
        private var indicator: some View {
            RoundedRectangle(cornerRadius: Constants.RADIUS)
                .fill(Color.black)
                .frame(
                    width: Constants.INDICATOR_WIDTH,
                    height: Constants.INDICATOR_HEIGHT
            ).onTapGesture {
                self.isOpen.toggle()
            }
        }
    
        init(isOpen: Binding<Bool>, maxHeight: CGFloat, @ViewBuilder content: () -> Content) {
            self.minHeight = maxHeight * Constants.MIN_HEIGHT_RATIO
            self.maxHeight = maxHeight
            self.content = content()
            self._isOpen = isOpen
        }
    
        var body: some View {
            GeometryReader { geometry in
                VStack(spacing: 0) {
                    self.indicator.padding()
                    self.content
                }
                .frame(width: geometry.size.width, height: self.maxHeight, alignment: .top)
                .background(Color.white)
                .cornerRadius(Constants.RADIUS)
                .frame(height: geometry.size.height, alignment: .bottom)
                .offset(y: max(self.offset + self.translation, 0))
                .animation(.interactiveSpring())
                .gesture(
                    DragGesture().updating(self.$translation) { value, state, _ in
                        state = value.translation.height
                    }.onEnded { value in
                        let snapDistance = self.maxHeight * Constants.SNAP_RATIO
                        guard abs(value.translation.height) > snapDistance else {
                            return
                        }
                        self.isOpen = value.translation.height < 0
                    }
                )
            }   
        } 
    }
    
    enum Constants {
        static let RADIUS: CGFloat = 16
        static let INDICATOR_HEIGHT: CGFloat = 6
        static let INDICATOR_WIDTH: CGFloat = 60
        static let SNAP_RATIO: CGFloat = 0.25
        static let MIN_HEIGHT_RATIO: CGFloat = 0
    }
    
    斯威夫特地图

    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            MapMainView()
        }
    }
    
    import Foundation
    import SwiftUI
    import MapKit
    
    struct MapMainView: View {
        let showCurrentLocation = false
        let locationFetcher = LocationFetcher()
        @State var selectedPin: MapPin? = nil
        @State var isBottomSheetOpen: Bool = false
        @State var examplePins = [MapPin]()
    
        var body: some View {
            GeometryReader { geometry in
                ZStack() {
                    VStack() {
                        Spacer()
                        BottomSheetView(isOpen: self.$isBottomSheetOpen, maxHeight: geometry.size.height * 0.3) {
                            Text(String(self.selectedPin?.title ?? "no title")).foregroundColor(Color.black)
                        }
                    }
                    .edgesIgnoringSafeArea(.all)
                    .zIndex(1)
                
                    MapView(locationFetcher: self.locationFetcher, showCurrentLocation: self.showCurrentLocation, displayedPins: self.$examplePins, selectedPin: self.$selectedPin, isBottomSheetOpen: self.$isBottomSheetOpen)
                        .edgesIgnoringSafeArea(.all)
                        .onAppear{
                            var currentLat: Double
                            var currentLng: Double
                        
                            if self.showCurrentLocation {
                                currentLat = self.locationFetcher.getCurrentCoordinates()?.latitude ?? 46.9457590197085
                                currentLng = self.locationFetcher.getCurrentCoordinates()?.longitude ?? 8.007923669708498
                            } else {
                                currentLat = 46.9457590197085
                                currentLng = 8.007923669708498
                            }
                        
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.004, longitude: currentLng - 0.002), title: "First Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat + 0.002, longitude: currentLng + 0.002), title: "Second Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.002, longitude: currentLng + 0.004), title: "Third Pin"))
                    }
                }
            }
        }
    }
    
    class MapPin: NSObject, MKAnnotation {
        let coordinate: CLLocationCoordinate2D
        let title: String?
    
        init(coordinate: CLLocationCoordinate2D, title: String? = nil) {
            self.coordinate = coordinate
            self.title = title
        }
    }
    
    import SwiftUI
    import MapKit
    
    struct MapView: UIViewRepresentable {
        let locationFetcher: LocationFetcher
        let showCurrentLocation: Bool
        @Binding var displayedPins: [MapPin]
        @Binding var selectedPin: MapPin?
        @Binding var isBottomSheetOpen: Bool
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    
        func makeUIView(context: Context) -> MKMapView {
            let mapView = MKMapView()
            mapView.delegate = context.coordinator
        
            if showCurrentLocation {
                mapView.showsUserLocation = true
                self.locationFetcher.attemptLocationAccess()
                centerLocation(mapView: mapView, locationCoordinate: locationFetcher.getCurrentCoordinates())
            } else {
                centerLocation(mapView: mapView, locationCoordinate: CLLocationCoordinate2D(latitude: 46.9457590197085, longitude: 8.007923669708498))
            }
        
            return mapView
        }
    
        func updateUIView(_ mapView: MKMapView, context: Context) {
            if self.displayedPins.count != mapView.annotations.count {
                mapView.removeAnnotations(mapView.annotations)
                mapView.addAnnotations(self.displayedPins)
            }
        }
    
        func centerLocation(mapView: MKMapView, locationCoordinate: CLLocationCoordinate2D?) {
            if locationCoordinate != nil {
                let kilometerRadius = 1.5;
                let scalingFactor = abs((cos(2 * Double.pi * locationCoordinate!.latitude / 360.0)));
                let span = MKCoordinateSpan(latitudeDelta: kilometerRadius/111, longitudeDelta: kilometerRadius/(scalingFactor * 111))
                let region = MKCoordinateRegion(center: locationCoordinate!, span: span)
                mapView.setRegion(region, animated: true)
            }
        }
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView
    
        init(_ parent: MapView) {
            self.parent = parent
        }
    
        func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
            guard let pin = view.annotation as? MapPin else {
                return
            }
            mapView.setCenter(pin.coordinate, animated: true)
        
            DispatchQueue.main.async {
               self.parent.selectedPin = pin
               self.parent.isBottomSheetOpen = true
            }
        }
    
    
        func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
            guard (view.annotation as? MapPin) != nil else {
                return
            }
        
            DispatchQueue.main.async {
               self.parent.selectedPin = nil
               self.parent.isBottomSheetOpen = false
            }
        }
    }
    
    import Foundation
    import SwiftUI
    
    struct BottomSheetView<Content: View>: View {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
        @Binding var isOpen: Bool
    
        let maxHeight: CGFloat
        let minHeight: CGFloat
        let content: Content
    
        @GestureState private var translation: CGFloat = 0
    
        private var offset: CGFloat {
            isOpen ? 0 : maxHeight - minHeight
        }
    
        private var indicator: some View {
            RoundedRectangle(cornerRadius: Constants.RADIUS)
                .fill(Color.black)
                .frame(
                    width: Constants.INDICATOR_WIDTH,
                    height: Constants.INDICATOR_HEIGHT
            ).onTapGesture {
                self.isOpen.toggle()
            }
        }
    
        init(isOpen: Binding<Bool>, maxHeight: CGFloat, @ViewBuilder content: () -> Content) {
            self.minHeight = maxHeight * Constants.MIN_HEIGHT_RATIO
            self.maxHeight = maxHeight
            self.content = content()
            self._isOpen = isOpen
        }
    
        var body: some View {
            GeometryReader { geometry in
                VStack(spacing: 0) {
                    self.indicator.padding()
                    self.content
                }
                .frame(width: geometry.size.width, height: self.maxHeight, alignment: .top)
                .background(Color.white)
                .cornerRadius(Constants.RADIUS)
                .frame(height: geometry.size.height, alignment: .bottom)
                .offset(y: max(self.offset + self.translation, 0))
                .animation(.interactiveSpring())
                .gesture(
                    DragGesture().updating(self.$translation) { value, state, _ in
                        state = value.translation.height
                    }.onEnded { value in
                        let snapDistance = self.maxHeight * Constants.SNAP_RATIO
                        guard abs(value.translation.height) > snapDistance else {
                            return
                        }
                        self.isOpen = value.translation.height < 0
                    }
                )
            }   
        } 
    }
    
    enum Constants {
        static let RADIUS: CGFloat = 16
        static let INDICATOR_HEIGHT: CGFloat = 6
        static let INDICATOR_WIDTH: CGFloat = 60
        static let SNAP_RATIO: CGFloat = 0.25
        static let MIN_HEIGHT_RATIO: CGFloat = 0
    }
    
    斯威夫特

    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            MapMainView()
        }
    }
    
    import Foundation
    import SwiftUI
    import MapKit
    
    struct MapMainView: View {
        let showCurrentLocation = false
        let locationFetcher = LocationFetcher()
        @State var selectedPin: MapPin? = nil
        @State var isBottomSheetOpen: Bool = false
        @State var examplePins = [MapPin]()
    
        var body: some View {
            GeometryReader { geometry in
                ZStack() {
                    VStack() {
                        Spacer()
                        BottomSheetView(isOpen: self.$isBottomSheetOpen, maxHeight: geometry.size.height * 0.3) {
                            Text(String(self.selectedPin?.title ?? "no title")).foregroundColor(Color.black)
                        }
                    }
                    .edgesIgnoringSafeArea(.all)
                    .zIndex(1)
                
                    MapView(locationFetcher: self.locationFetcher, showCurrentLocation: self.showCurrentLocation, displayedPins: self.$examplePins, selectedPin: self.$selectedPin, isBottomSheetOpen: self.$isBottomSheetOpen)
                        .edgesIgnoringSafeArea(.all)
                        .onAppear{
                            var currentLat: Double
                            var currentLng: Double
                        
                            if self.showCurrentLocation {
                                currentLat = self.locationFetcher.getCurrentCoordinates()?.latitude ?? 46.9457590197085
                                currentLng = self.locationFetcher.getCurrentCoordinates()?.longitude ?? 8.007923669708498
                            } else {
                                currentLat = 46.9457590197085
                                currentLng = 8.007923669708498
                            }
                        
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.004, longitude: currentLng - 0.002), title: "First Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat + 0.002, longitude: currentLng + 0.002), title: "Second Pin"))
                            self.examplePins.append(MapPin(coordinate: CLLocationCoordinate2D(latitude: currentLat - 0.002, longitude: currentLng + 0.004), title: "Third Pin"))
                    }
                }
            }
        }
    }
    
    class MapPin: NSObject, MKAnnotation {
        let coordinate: CLLocationCoordinate2D
        let title: String?
    
        init(coordinate: CLLocationCoordinate2D, title: String? = nil) {
            self.coordinate = coordinate
            self.title = title
        }
    }
    
    import SwiftUI
    import MapKit
    
    struct MapView: UIViewRepresentable {
        let locationFetcher: LocationFetcher
        let showCurrentLocation: Bool
        @Binding var displayedPins: [MapPin]
        @Binding var selectedPin: MapPin?
        @Binding var isBottomSheetOpen: Bool
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    
        func makeUIView(context: Context) -> MKMapView {
            let mapView = MKMapView()
            mapView.delegate = context.coordinator
        
            if showCurrentLocation {
                mapView.showsUserLocation = true
                self.locationFetcher.attemptLocationAccess()
                centerLocation(mapView: mapView, locationCoordinate: locationFetcher.getCurrentCoordinates())
            } else {
                centerLocation(mapView: mapView, locationCoordinate: CLLocationCoordinate2D(latitude: 46.9457590197085, longitude: 8.007923669708498))
            }
        
            return mapView
        }
    
        func updateUIView(_ mapView: MKMapView, context: Context) {
            if self.displayedPins.count != mapView.annotations.count {
                mapView.removeAnnotations(mapView.annotations)
                mapView.addAnnotations(self.displayedPins)
            }
        }
    
        func centerLocation(mapView: MKMapView, locationCoordinate: CLLocationCoordinate2D?) {
            if locationCoordinate != nil {
                let kilometerRadius = 1.5;
                let scalingFactor = abs((cos(2 * Double.pi * locationCoordinate!.latitude / 360.0)));
                let span = MKCoordinateSpan(latitudeDelta: kilometerRadius/111, longitudeDelta: kilometerRadius/(scalingFactor * 111))
                let region = MKCoordinateRegion(center: locationCoordinate!, span: span)
                mapView.setRegion(region, animated: true)
            }
        }
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView
    
        init(_ parent: MapView) {
            self.parent = parent
        }
    
        func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
            guard let pin = view.annotation as? MapPin else {
                return
            }
            mapView.setCenter(pin.coordinate, animated: true)
        
            DispatchQueue.main.async {
               self.parent.selectedPin = pin
               self.parent.isBottomSheetOpen = true
            }
        }
    
    
        func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
            guard (view.annotation as? MapPin) != nil else {
                return
            }
        
            DispatchQueue.main.async {
               self.parent.selectedPin = nil
               self.parent.isBottomSheetOpen = false
            }
        }
    }
    
    import Foundation
    import SwiftUI
    
    struct BottomSheetView<Content: View>: View {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
        @Binding var isOpen: Bool
    
        let maxHeight: CGFloat
        let minHeight: CGFloat
        let content: Content
    
        @GestureState private var translation: CGFloat = 0
    
        private var offset: CGFloat {
            isOpen ? 0 : maxHeight - minHeight
        }
    
        private var indicator: some View {
            RoundedRectangle(cornerRadius: Constants.RADIUS)
                .fill(Color.black)
                .frame(
                    width: Constants.INDICATOR_WIDTH,
                    height: Constants.INDICATOR_HEIGHT
            ).onTapGesture {
                self.isOpen.toggle()
            }
        }
    
        init(isOpen: Binding<Bool>, maxHeight: CGFloat, @ViewBuilder content: () -> Content) {
            self.minHeight = maxHeight * Constants.MIN_HEIGHT_RATIO
            self.maxHeight = maxHeight
            self.content = content()
            self._isOpen = isOpen
        }
    
        var body: some View {
            GeometryReader { geometry in
                VStack(spacing: 0) {
                    self.indicator.padding()
                    self.content
                }
                .frame(width: geometry.size.width, height: self.maxHeight, alignment: .top)
                .background(Color.white)
                .cornerRadius(Constants.RADIUS)
                .frame(height: geometry.size.height, alignment: .bottom)
                .offset(y: max(self.offset + self.translation, 0))
                .animation(.interactiveSpring())
                .gesture(
                    DragGesture().updating(self.$translation) { value, state, _ in
                        state = value.translation.height
                    }.onEnded { value in
                        let snapDistance = self.maxHeight * Constants.SNAP_RATIO
                        guard abs(value.translation.height) > snapDistance else {
                            return
                        }
                        self.isOpen = value.translation.height < 0
                    }
                )
            }   
        } 
    }
    
    enum Constants {
        static let RADIUS: CGFloat = 16
        static let INDICATOR_HEIGHT: CGFloat = 6
        static let INDICATOR_WIDTH: CGFloat = 60
        static let SNAP_RATIO: CGFloat = 0.25
        static let MIN_HEIGHT_RATIO: CGFloat = 0
    }
    

    或者你可以在这里下载所有文件

    我自己发现了问题。不仅我的MapPins,蓝色的位置圆也算作mapView注释。因此,如果启用了位置服务,my UpdateUI()将删除并添加每个didSelect上的所有注释,因为self.displayedPins.count!=mapView.annotations.count始终为false,这会导致底部图纸突然消失

    在过滤注释后,它最终起作用:

    func updateUIView(_ mapView: MKMapView, context: Context) {
        let displayedMapPins = mapView.annotations.filter { annotation in
            return annotation is MapPin
        }
        
        if self.mapPinsToDisplay.count != displayedMapPins.count {
            mapView.removeAnnotations(displayedMapPins)
            mapView.addAnnotations(self.mapPinsToDisplay)
        }
    }