SwiftUI MapKit UIViewRepresentable Can't present Alert
我有一个 SwiftUI 应用程序,其中有几个视图是使用 MapKit 制作的地图
UIView 可表示的。我有兴趣点和使用的自定义注释
右侧和左侧的标注按钮,用于进一步操作。在右边我只是想要
显示有关航点的信息。在左边我想发出警报
进一步操作的选择 - 例如,插入一个新的注释点。前
SwiftUI 我刚刚提出了一个警报,并做了上述两个。但据我所知,
UIViewRepresentable 版本上没有 self.present。因此我没有
能够显示警报。
只是为了一个实验 - 我将 SwiftUI 警报代码附加到 SwiftUI 视图中
调用 MapView。使用 Observable 布尔值,我确实可以同时发出这两个警报。
这对我来说似乎很奇怪,但也许是绑定到全局属性的警报代码
可以在任何地方。
我的第一次尝试:(结构是 DetailMapView)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { if control == view.leftCalloutAccessoryView { guard let tappedLocationCoord = view.annotation?.coordinate else {return} let tappedLocation = CLLocation(latitude: tappedLocationCoord.latitude, longitude: tappedLocationCoord.longitude) let ac = UIAlertController(title: nil, message: nil, preferredStyle: .alert) let deleteAction = UIAlertAction(title:"Delete Waypoint", style: .destructive) { (action) in //some stuff } let insertAction = UIAlertAction(title:"Insert Waypoint After This", style: .default) { (action) in //some stuff } let cancelAction = UIAlertAction(title:"Cancel", style: .default) { (action) in //some stuff }//cancelAction ac.addAction(deleteAction) ac.addAction(insertAction) ac.addAction(cancelAction) //tried adding self, referencing parent - always error saying //the object does not have a .present mapView.present(ac, animated: true) } else if control == view.rightCalloutAccessoryView { //more of the same } }//annotationView |
然后我删除了警报代码并添加了:
1 | parent.userDefaultsManager.shouldShowAnnotationEditMenu.toggle() |
然后我将呼叫屏幕更改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | @ObservedObject var userDefaultsManager: UserDefaultsManager var aTrip: Trip? var body: some View { VStack { Text(aTrip?.name ??"Unknown Map Name") .padding(.top, -50) .padding(.bottom, -20) DetailMapView(aTrip: aTrip, userDefaultsManager: userDefaultsManager) .padding(.top, -20) .alert(isPresented: $userDefaultsManager.shouldShowAddress) { //Alert(title: Text("\\(aTrip?.name ??"No") Address"), Alert(title: Text(self.userDefaultsManager.approximateAddress), message: Text("This is the approximate street address."), dismissButton: .default(Text("Got it!"))) }//.alert shouldShowAddress Text("This is the view where the trip information will be displayed.") .multilineTextAlignment(.center) .alert(isPresented: $userDefaultsManager.shouldShowAnnotationEditMenu) { Alert(title: Text("Edit Annotations"), message: Text("Choose this to insert an Annotation."), dismissButton: .default(Text("Got it!"))) }//.alert shouldShowAddress } } |
我想如果这是安全的,我可以让它工作 - 但它似乎更复杂
应该是。
这就是想法:
任何指导将不胜感激:Xcode 版本 11.3.1 (11C504)
我为此花了一个小时,我是 SwiftUI 的新手,我跳进去只是为了回答一些简单的问题。
一种方法是使用
你还需要有一个
的地方
像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | struct MainView: View { @State var text ="" @State var showingAlert: Bool var body: some View { VStack { MapView(showingAlert: self.$showingAlert) .alert(isPresented: $showingAlert) { () -> Alert in print("SHOWING ALERT BODY: --> \\($showingAlert.wrappedValue)") return Alert(title: Text("Important message"), message: Text("Go out and have a girlfriend!"), dismissButton: .default(Text("Got it!"))) } } } } |
然后你的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | struct MapView: UIViewRepresentable { let landmarks = LandmarkAnnotation.requestMockData() @Binding var showingAlert: Bool func makeCoordinator() -> MapViewCoordinator { MapViewCoordinator(mapView: self, showingAlert: self.$showingAlert) } /** - Description - Replace the body with a make UIView(context:) method that creates and return an empty MKMapView */ func makeUIView(context: Context) -> MKMapView { MKMapView(frame: .zero) } func updateUIView(_ view: MKMapView, context: Context){ //If you changing the Map Annotation then you have to remove old Annotations //mapView.removeAnnotations(mapView.annotations) view.delegate = context.coordinator view.addAnnotations(landmarks) } } struct MapView_Previews: PreviewProvider { static var previews: some View { MapView(showingAlert: Binding<Bool>.constant(true)) } } |
最后,在你的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /* Coordinator for using UIKit inside SwiftUI. */ class MapViewCoordinator: NSObject, MKMapViewDelegate { var mapViewController: MapView! @Binding var showAlert: Bool init(mapView: MapView, showingAlert: Binding<Bool>) { self.mapViewController = mapView self._showAlert = showingAlert super.init() } func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{ //Custom View for Annotation let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier:"customView") annotationView.canShowCallout = true //Your custom image icon annotationView.image = UIImage(named:"locationPin") return annotationView } func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { print("calloutAccessoryControlTapped") } func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { print("didSelect") self.showAlert = true } } |
如您所见,我只是使用了 Bool 标志。尤其是
是的,格伦。
这实际上是我的做法。我用过
另外,我不想有条件地显示地图 - 只想显示注释连接。
由于某种原因,我无法对您的答案添加评论,所以在这里回复。