我创建了一个使用MKMapView的MapView,地图显示OK,所有注释图钉都显示OK,我可以点击图钉以获取其他信息,然后在我点击其他信息时将其推送到另一个SwiftUI视图。我看不到如何从UIViewRepresentable内部推送SwiftUi视图。 MapView的代码如下,即使我调用MapView时,navigationController始终为nil,它位于NavigationView中。
import SwiftUI
import MapKit
class MapAnnotationItem: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
var item: Any?
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
}
}
struct MapViewRepresentable : UIViewRepresentable {
@Binding var coordinateRegion: MKCoordinateRegion
@Binding var annotationItems: [MapAnnotationItem]
@State var mapView = MKMapView()
@State var showReport = false
var viewController: UIHostingController<MapView>
func makeUIView(context: UIViewRepresentableContext<MapViewRepresentable>) -> MKMapView {
mapView.delegate = context.coordinator
mapView.showsUserLocation = false
mapView.region = coordinateRegion
mapView.addAnnotations(annotationItems)
return mapView
}
func updateUIView(_ uiView: MKMapView, context: UIViewRepresentableContext<MapViewRepresentable>) {
uiView.region = coordinateRegion
let allAnnotations = uiView.annotations
uiView.removeAnnotations(allAnnotations)
uiView.addAnnotations(annotationItems)
}
func makeCoordinator() -> Coordinator {
Coordinator(viewController: viewController)
}
class Coordinator: NSObject, MKMapViewDelegate {
var tappedItem: Any?
var viewController: UIHostingController<MapView>
init(viewController: UIHostingController<MapView>) {
self.viewController = viewController
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView: MKPinAnnotationView?
if (annotation is MKUserLocation) == true {
annotationView = nil
} else {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "MapAnnotation")
tappedItem = (annotation as? MapAnnotationItem)?.item
if (tappedItem is Report) {
annotationView?.pinTintColor = MKPinAnnotationView.redPinColor()
} else if (tappedItem is User) {
annotationView?.image = UIImage(named: "MapPinIcon\(AppSettings.shared.appNameNoSpaces)")
}
annotationView?.animatesDrop = false
annotationView?.canShowCallout = true
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
return annotationView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
tappedItem = (view.annotation as? MapAnnotationItem)?.item
if (tappedItem is Report) {
let viewControllerReport = UIHostingController(rootView: ReportView(report: tappedItem as! Report))
print(viewController.navigationController) // This is nil
viewController.navigationController?.pushViewController(viewControllerReport, animated: true)
} else if (tappedItem is User) {
// FIXME: Push to user
}
}
}
}
struct MapView: View {
@Binding var coordinateRegion: MKCoordinateRegion
@Binding var annotationItems: [MapAnnotationItem]
var navigationTitle: String
@State private var displayAnnotationText = false
var body: some View {
Print(annotationItems.count)
MapViewRepresentable(coordinateRegion: $coordinateRegion, annotationItems: $annotationItems, viewController: UIHostingController(rootView: self))
.navigationTitle(navigationTitle)
}
}
答案 0 :(得分:0)
不确定这是最好的解决方案,但是我设法通过替换来使其起作用:
viewController.navigationController?.pushViewController(viewControllerReport, animated: true)
具有:
mapView.parentViewController?.navigationController?.pushViewController(viewControllerReport, animated: true)
并添加:
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder?.next
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}