如何在SwiftUI中改变用户触摸GoogleMaps标记时的UI状态?

问题描述 投票:0回答:1

这个问题是关于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个回答
0
投票

过了一段时间,我找到了一个解决的方法。

其关键词是 "协调员 "和 "绑定"。

当然,我不知道这是否是正确的方法,或者说是最好的方法,但至少它是有效的。


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

        }

    }
}

© www.soinside.com 2019 - 2024. All rights reserved.