【问题标题】:Push SwiftUI View from inside UIViewRepresentable从 UIViewRepresentable 内部推送 SwiftUI 视图
【发布时间】:2020-08-24 20:04:32
【问题描述】:

我创建了一个使用 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)
    }
}

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    不确定这是最好的解决方案,但我设法通过替换:

    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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 2021-02-16
      • 2018-12-30
      相关资源
      最近更新 更多