You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS SwiftUI中Google Maps代理方法未触发问题求助

问题描述

通过SPM集成Google Maps后,地图可正常加载并显示多个标记,但mapViewDidFinishTileRendering(_:)和mapViewSnapshotReady(_:)等代理方法从未被调用,无法监听地图加载完成、地图移动等事件。

相关实现代码如下:

MapViewController 代码

import UIKit
import GoogleMaps

class MapViewController: UIViewController {
    var options = GMSMapViewOptions()
    var map = GMSMapView()
    var isAnimating: Bool = false

    override func loadView() {
      super.loadView()
      options.camera = GMSCameraPosition.camera(withLatitude: 18.659553, longitude: 78.105868, zoom: 17.0)
      options.frame = self.view.bounds
      map = GMSMapView(options: options)
      self.view = map
    }
}

MapViewControllerBridge 代码

import Foundation
import SwiftUI
import GoogleMaps

struct MapViewControllerBridge: UIViewControllerRepresentable {
    
    @Binding var markers: [GMSMarker]
    @Binding var selectedMarker: GMSMarker?
    var onAnimationEnded: () -> ()
    var mapViewWillMove: (Bool) -> ()

    func makeUIViewController(context: Context) -> MapViewController {
        let uiViewController = MapViewController()
        uiViewController.map.delegate = context.coordinator
        return uiViewController
    }

    func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
        markers.forEach { $0.map = uiViewController.map }
        selectedMarker?.map = uiViewController.map
        animateToSelectedMarker(viewController: uiViewController)
    }
    
    func makeCoordinator() -> MapViewCoordinator {
      return MapViewCoordinator(self)
    }
    
    private func animateToSelectedMarker(viewController: MapViewController) {
      guard let selectedMarker = selectedMarker else {
        return
      }

      let map = viewController.map
      if map.selectedMarker != selectedMarker {
        map.selectedMarker = selectedMarker
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
          map.animate(toZoom: kGMSMinZoomLevel)
          DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            map.animate(with: GMSCameraUpdate.setTarget(selectedMarker.position))
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
              map.animate(toZoom: 12)
              DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
                onAnimationEnded()
              })
            })
          }
        }
      }
    }
    
    final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
        var mapViewControllerBridge: MapViewControllerBridge
        
        init(_ mapViewControllerBridge: MapViewControllerBridge) {
            self.mapViewControllerBridge = mapViewControllerBridge
        }
        
        func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
            self.mapViewControllerBridge.mapViewWillMove(gesture)
        }
        
        func mapViewDidFinishTileRendering(_ mapView: GMSMapView) {
            print("Map Finished Rendering..")
        }
        
        func mapViewSnapshotReady(_ mapView: GMSMapView) {
            print("Map View Snapshot Ready..")
        }
    }
}

ContentView 调用代码

MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker, onAnimationEnded: {
                  self.zoomInCenter = true
                }, mapViewWillMove: { (isGesture) in
                  guard isGesture else { return }
                  self.zoomInCenter = false
                })
                .ignoresSafeArea()
解决方案

1. 替换已废弃的代理方法

mapViewDidFinishTileRendering(_:)和mapViewSnapshotReady(_:)已被Google Maps SDK标记为废弃,需使用最新替代方法:

  • 监听地图渲染完成:使用mapView(_:didFinishRenderingMap:fullyRendered:),该方法会在地图完成渲染时触发,fullyRendered参数可判断是否所有瓦片都加载完成。
  • 监听快照就绪:使用GMSMapView的snapshot(with:completionHandler:)方法,在回调中处理快照就绪逻辑。

修改后的MapViewCoordinator代码:

final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
    var mapViewControllerBridge: MapViewControllerBridge
    
    init(_ mapViewControllerBridge: MapViewControllerBridge) {
        self.mapViewControllerBridge = mapViewControllerBridge
    }
    
    func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
        self.mapViewControllerBridge.mapViewWillMove(gesture)
    }
    
    func mapView(_ mapView: GMSMapView, didFinishRenderingMap fullyRendered: Bool) {
        if fullyRendered {
            print("Map fully rendered..")
            // 处理地图完全加载完成的逻辑
        } else {
            print("Map partially rendered..")
        }
    }
    
    // 按需调用快照方法
    func takeMapSnapshot(mapView: GMSMapView) {
        mapView.snapshot(with: nil) { image in
            guard let image = image else { return }
            print("Map snapshot ready..")
            // 处理快照图片
        }
    }
}

2. 确认代理设置逻辑

当前代码在makeUIViewController中设置代理的逻辑正确,需确保updateUIViewController中没有重置map.delegate的操作。现有代码仅添加标记,未修改代理,无需调整。

3. 排查地图移动事件

若mapView(_:willMove:)也未触发,可尝试延迟设置代理(用于排查,非最优解):

func makeUIViewController(context: Context) -> MapViewController {
    let uiViewController = MapViewController()
    DispatchQueue.main.async {
        uiViewController.map.delegate = context.coordinator
    }
    return uiViewController
}

内容的提问来源于stack exchange,提问作者vishwa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:40:39