SwiftUI封装Google地图时GMSMarker点击跳转及delegate设置问题
核心实现逻辑
- 不能直接将
GMSMapView.delegate设置为GoogleMapView本身:GoogleMapView是值类型结构体,不满足代理要求的类类型约束 - 必须使用
UIViewRepresentable配套的Coordinator协调器作为代理实现载体,这是SwiftUI桥接UIKit控件时处理代理事件的标准方案 - 你原有代码中
mapView.delegate = ViewController()的写法是无效的,临时创建的ViewController实例在方法执行完就会被释放,代理回调完全无法触发
完整实现代码
import SwiftUI import GoogleMaps struct GoogleMapView: UIViewRepresentable { // 点击Marker的回调闭包,用于向SwiftUI层传递事件 var onMarkerTapped: (GMSMarker) -> Void func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func updateUIView(_ uiView: GMSMapView, context: Context) { let marker = GMSMarker() marker.position = CLLocationCoordinate2D(latitude: 20, longitude: 50) marker.map = uiView } func makeUIView(context: Context) -> GMSMapView { let camera = GMSCameraPosition.camera(withLatitude: 20, longitude: 50, zoom: 10) let mapView = GMSMapView(frame: .zero, camera: camera) // 核心:将delegate设置为上下文中的协调器实例 mapView.delegate = context.coordinator return mapView } // 内部协调器类,实现GMSMapViewDelegate协议 class Coordinator: NSObject, GMSMapViewDelegate { var parent: GoogleMapView init(parent: GoogleMapView) { self.parent = parent } // 实现Marker点击的代理回调 func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { parent.onMarkerTapped(marker) // 返回true表示已自定义处理事件,不需要触发地图默认点击行为 return true } } }
SwiftUI层调用示例(实现跳转逻辑)
struct ContentView: View { @State private var isShowDetail = false @State private var tappedMarker: GMSMarker? var body: some View { NavigationStack { GoogleMapView { marker in // 收到Marker点击事件,触发跳转 tappedMarker = marker isShowDetail = true } .ignoresSafeArea() // 用sheet/push都可以实现跳转,这里以sheet为例 .sheet(isPresented: $isShowDetail) { MarkerDetailView(marker: $tappedMarker) } } } } // 示例跳转目标视图 struct MarkerDetailView: View { @Binding var marker: GMSMarker? var body: some View { VStack(spacing: 20) { Text("你点击了Marker") Text("坐标:\(marker?.position.latitude ?? 0), \(marker?.position.longitude ?? 0)") } .padding() } }
内容的提问来源于stack exchange,提问作者Santanu
相关产品推荐
相关产品推荐

