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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:42:16