【问题标题】:How to change UI state when user touch GoogleMaps' Marker in SwiftUI?当用户在 SwiftUI 中触摸 GoogleMaps 的标记时如何更改 UI 状态?
【发布时间】:2020-09-03 07:24:30
【问题描述】:

这个问题是关于 SwiftUI 的。

我正在尝试显示地图并允许用户触摸任何可用的标记。发生这种情况时,我希望更改视图上的文本,以反映该用户的操作。

经过大量搜索,我认为解决方案可能接近 Observable 协议,但我就是想不出正确的方法。这是我的代码:


struct Home: View {

    // Here's the attribute I want to be changed when user touches the marker
    var selectedMarker: GMSMarker?

    var body: some View {

            VStack(spacing: 0) {

                // Condition to be applied when user touches the marker                                
                if (selectedMarker == nil){
                    Text("No marker selected").padding()
                }else{
                    Text("Now, there's a marker selected").padding()
                }

                GoogleMapsHome()

        }
        .navigationBarBackButtonHidden(true)
        .navigationBarTitle(Text("Marker question"), displayMode: .inline)

    }

}

struct Home_Previews: PreviewProvider {
    static var previews: some View {
        Home()
    }
}

这是 GoogleMaps 的定义:

struct GoogleMapsHome: UIViewRepresentable {

    private let zoom: Float = 18

    // Just for didactic purposes. Later, I'm going to use LocationManager
    let lat: Double = -15.6692660716233
    let lng: Double = -47.83980712156295

    func makeUIView(context: Self.Context) -> GMSMapView {

        let camera = GMSCameraPosition.camera(
            withLatitude: lat,
            longitude: lng,
            zoom: zoom)

        let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)

        mapView.mapType = .hybrid

        mapView.delegate = context.coordinator

        return mapView

    }

    func updateUIView(_ mapView: GMSMapView, context: Context) {

        mapView.animate(toLocation: CLLocationCoordinate2D(latitude: lat, longitude: lng))

        let position = CLLocationCoordinate2D(latitude: lat, longitude: lng)
        let marker = GMSMarker(position: position)

        marker.title = "You"

        marker.map = mapView

    }

    func makeCoordinator() -> Coordinator {
       Coordinator(owner: self)
    }

    class Coordinator: NSObject, GMSMapViewDelegate, ObservableObject {

        let owner: GoogleMapsHome       // access to owner view members,

        init(owner: GoogleMapsHome) {
         self.owner = owner
        }

        @Published var selectedMarker: GMSMarker? {
            willSet { objectWillChange.send() }
        }

        func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

            print("A marker has been touched by the user")

            self.selectedMarker = marker

            return true

        }

    }
}

我希望有人可以帮助我,以后,这个问题对任何有同样需要的人都有用。

最好的问候!

【问题讨论】:

    标签: delegates swiftui google-maps-markers google-maps-sdk-ios


    【解决方案1】:

    过了一会儿,我找到了解决它的方法。

    其中的关键字是“协调器”和“绑定”。

    当然,我不确定这是正确的方法还是最好的方法,但至少它奏效了。

    
    import Foundation
    import SwiftUI
    import GoogleMaps
    
    struct Home: View {
    
        @State var selectedMarker: GMSMarker?
    
        var body: some View {
    
                VStack(spacing: 0) {
    
                    if (selectedMarker == nil){
                        Text("No marker selected").padding()
                    }else{
                        Text("There's a marker selected").padding()
                    }
    
                    GoogleMapsHome(selectedMarker: self.$selectedMarker)
    
            }
            .navigationBarBackButtonHidden(true)
            .navigationBarTitle(Text("Map Test"), displayMode: .inline)
    
        }
    
    }
    
    struct Home_Previews: PreviewProvider {
        static var previews: some View {
            Home()
        }
    }
    
    struct GoogleMapsHome: UIViewRepresentable {
    
        private let zoom: Float = 18
    
        let lat: Double = -15.6692660716233
        let lng: Double = -47.83980712156295
    
        @Binding var selectedMarker: GMSMarker?
    
        func makeCoordinator() -> Coordinator {
            return Coordinator(
                owner: self,
                selectedMarker: $selectedMarker)
        }
    
        func makeUIView(context: Self.Context) -> GMSMapView {
    
            let camera = GMSCameraPosition.camera(
                withLatitude: lat,
                longitude: lng,
                zoom: zoom)
    
            let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
    
            mapView.mapType = .hybrid
    
            mapView.delegate = context.coordinator
    
            return mapView
    
        }
    
        func updateUIView(_ mapView: GMSMapView, context: Context) {
    
            mapView.animate(toLocation: CLLocationCoordinate2D(latitude: lat, longitude: lng))
    
            let position = CLLocationCoordinate2D(latitude: lat, longitude: lng)
            let marker = GMSMarker(position: position)
    
            marker.title = "You"
    
            marker.map = mapView
    
        }
    
    
        class Coordinator: NSObject, GMSMapViewDelegate, ObservableObject {
    
            let owner: GoogleMapsHome       // access to owner view members,
    
            @Binding var selectedMarker: GMSMarker?
    
            init(
                owner: GoogleMapsHome,
                selectedMarker: Binding<GMSMarker?>
            ) {
    
                self.owner = owner
    
                _selectedMarker = selectedMarker
    
            }
    
            func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
    
                print("A marker has been touched")
    
                self.selectedMarker = marker
    
                return true
    
            }
    
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-15
      • 1970-01-01
      • 2016-06-05
      • 2020-09-29
      • 1970-01-01
      • 2020-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多