SwiftUI集成Google Maps SDK时GMSMapView无法加载问题求助
Google Maps SDK 桥接SwiftUI加载失败修复
问题现象
通过纯UIKit方式直接初始化GMSMapView赋值给控制器根视图可以正常运行,改用UIViewControllerRepresentable桥接到SwiftUI后,地图无法正常加载渲染。
原问题代码:
//Modules import GoogleMaps import SwiftUI import UIKit import GoogleMapsUtils class MapViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate { var mapView: GMSMapView! let locationManager = CLLocationManager() override func loadView() { super.loadView() //LoadMap - Default locationManager.delegate = self locationManager.requestAlwaysAuthorization() guard let myLoc = locationManager.location?.coordinate else{return} if CLLocationManager.locationServicesEnabled() { locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.startUpdatingLocation() } //Camera Focus let camera = GMSCameraPosition.camera(withLatitude: myLoc.latitude, longitude: myLoc.longitude, zoom: 15.0) mapView = GMSMapView.map(withFrame: self.view.bounds, camera: camera) mapView.isMyLocationEnabled = true mapView.delegate = self self.view = mapView } }
原桥接代码:
import GoogleMaps import SwiftUI struct MapViewControllerBridge: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> MapViewController { let uiViewController = MapViewController() return uiViewController } func updateUIViewController(_ uiViewController: MapViewController, context: Context) { } }
核心错误点
loadView逻辑错误:该方法的作用是直接设置控制器的根视图,不需要先调用super.loadView()生成默认视图再覆盖;更严重的是你在这个方法里同步获取定位坐标,此时定位权限刚发起请求、定位服务还未返回结果,guard判断会直接触发return,后续地图初始化代码完全不执行,最终控制器只加载了super.loadView()生成的空白视图。- 视图尺寸错误:
loadView执行阶段控制器视图还没完成布局,self.view.bounds值为.zero,就算执行到地图初始化逻辑,生成的GMSMapView尺寸也是0,无法正常渲染。 - 定位逻辑缺失:没有实现CLLocationManager的定位更新、权限变更回调,拿到定位结果后不会更新地图相机位置;也没有设置默认兜底相机,定位失败时地图没有有效渲染参数。
修复后代码
MapViewController 部分
//Modules import GoogleMaps import SwiftUI import UIKit import GoogleMapsUtils class MapViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate { var mapView: GMSMapView! let locationManager = CLLocationManager() // 设置默认兜底相机,避免定位未完成时地图无渲染目标 let defaultCamera = GMSCameraPosition.camera(withLatitude: 39.9042, longitude: 116.4074, zoom: 15.0) override func loadView() { // 直接初始化GMSMapView作为根视图,不需要调用super.loadView() mapView = GMSMapView.map(withFrame: .zero, camera: defaultCamera) mapView.isMyLocationEnabled = true mapView.delegate = self self.view = mapView } override func viewDidLoad() { super.viewDidLoad() // 定位相关逻辑移到viewDidLoad执行 locationManager.delegate = self locationManager.requestAlwaysAuthorization() if CLLocationManager.locationServicesEnabled() { locationManager.desiredAccuracy = kCLLocationAccuracyBest } // 设置自动布局掩码,保证地图尺寸跟随控制器视图自适应 mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight] } // 权限变更回调,拿到定位权限后再启动定位 func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { let status = manager.authorizationStatus guard status == .authorizedWhenInUse || status == .authorizedAlways else { return } locationManager.startUpdatingLocation() } // 定位更新回调,拿到位置后移动地图相机 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let currentLoc = locations.last else { return } let camera = GMSCameraPosition.camera( withLatitude: currentLoc.coordinate.latitude, longitude: currentLoc.coordinate.longitude, zoom: 15.0 ) mapView.animate(to: camera) // 拿到一次定位结果后可停止更新,节省电量 locationManager.stopUpdatingLocation() } }
SwiftUI桥接部分
原有桥接逻辑无核心错误,可直接使用:
import GoogleMaps import SwiftUI struct MapViewControllerBridge: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> MapViewController { MapViewController() } func updateUIViewController(_ uiViewController: MapViewController, context: Context) {} }
排查校验点
如果修复后仍有空白问题,逐项检查:
- 确认已在App启动入口(SwiftUI App的
init方法、或AppDelegate的didFinishLaunchingWithOptions方法)调用GMSServices.provideAPIKey("你的有效API Key") - 确认Info.plist已添加定位权限描述字段:
NSLocationWhenInUseUsageDescription、NSLocationAlwaysAndWhenInUseUsageDescription - 确认API Key已在Google Cloud控制台开启Maps SDK for iOS服务,且绑定了当前项目的Bundle ID
- 确认测试设备网络可正常访问Google服务
内容的提问来源于stack exchange,提问作者Skyrifter
相关产品推荐
相关产品推荐

