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

如何在Swift中通过Firebase发送位置消息并实现Google Map动态取点

功能需求与当前实现问题

预期功能逻辑

  • 用户点击按钮后弹出弹窗,提供音频、视频、位置三类消息发送选项
  • 用户选择位置选项后跳转至locationViewController
  • 最终将选中的位置存储到Firebase

当前已完成功能

  • 静态坐标的Google Map加载与标记点渲染
  • 在chatViewController中定义了InputActionSheet方法,用户点击选择按钮后触发该方法,调用位置消息相关逻辑

待解决问题

  • 如何在用户点击Google Map任意位置时动态获取对应坐标
  • 如何在用户点击位置时同步显示标记点

解决方案

修改逻辑说明

  1. 给位置选择页添加GMSMapViewDelegate代理,通过代理方法获取用户点击的坐标
  2. 新增全局存储选中标记的属性,每次点击后替换旧标记,避免页面出现多个选中标记
  3. 新增回调闭包,等用户确认选中位置后再将坐标传回聊天页触发Firebase发送逻辑,修正原代码未等用户选择就提前发消息的问题

修改后完整代码

位置选择页面代码(原ViewController建议重命名为LocationPickerViewController避免重名)

class LocationPickerViewController: UIViewController {
    @IBOutlet weak var mapView: GMSMapView!
    let manager = CLLocationManager()
    // 存储当前选中的标记,方便后续替换
    private var selectedMarker: GMSMarker?
    // 回调闭包:用户选完位置后把坐标传回聊天页
    var didSelectLocation: ((CLLocationCoordinate2D) -> Void)?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置mapView代理
        mapView.delegate = self
        manager.delegate = self
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
        self.mapView.mapStyle(name:"darkTheme", type:"json")
        // 右上角添加确认发送按钮
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "发送", style: .done, target: self, action: #selector(sendSelectedLocation))
    }
    
    func setupMap(title:String,subtitle:String,_ coordinate:CLLocationCoordinate2D){
        let camera = GMSCameraPosition.camera(withLatitude: coordinate.latitude, longitude:  coordinate.longitude, zoom: 6.0)
        mapView.camera = camera
        self.addMarker(title: title, subtitle: subtitle, coordinate:coordinate)
    }
    
    func addMarker(title:String,subtitle:String,coordinate:CLLocationCoordinate2D){
        let marker = GMSMarker()
        marker.icon = #imageLiteral(resourceName: "DiceFive")
        marker.position = coordinate
        marker.title = title
        marker.snippet = subtitle
        marker.map = mapView
    }
    
    // 确认发送选中位置
    @objc private func sendSelectedLocation() {
        guard let coordinate = selectedMarker?.position else {
            // 可自行添加提示要求用户先选择位置
            return
        }
        didSelectLocation?(coordinate)
        navigationController?.popViewController(animated: true)
    }
}

// 实现GMSMapViewDelegate处理地图点击事件
extension LocationPickerViewController: GMSMapViewDelegate {
    func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
        // 移除上一次的选中标记
        selectedMarker?.map = nil
        // 新建选中标记
        let newMarker = GMSMarker()
        newMarker.icon = #imageLiteral(resourceName: "DiceFive") // 可替换为自定义选中态图标
        newMarker.position = coordinate
        newMarker.title = "选中位置"
        newMarker.map = mapView
        // 存储当前选中标记
        selectedMarker = newMarker
        // 可选:将选中位置移到地图中心
        mapView.animate(to: GMSCameraPosition.camera(withTarget: coordinate, zoom: mapView.camera.zoom))
    }
}

extension LocationPickerViewController : CLLocationManagerDelegate {
    public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.first else{
            return
        }
        // 可选:默认将地图定位到用户当前位置
        mapView.animate(to: GMSCameraPosition.camera(withTarget: location.coordinate, zoom: 15.0))
        // 拿到位置后停止更新节省电量
        manager.stopUpdatingLocation()
    }
}

聊天页presentLocationPicker方法修改后代码

private func presentLocationPicker() {
    let vc = LocationPickerViewController()
    vc.title = "选择位置"
    vc.navigationItem.largeTitleDisplayMode = .never
    // 监听位置选择回调
    vc.didSelectLocation = { [weak self] selectedCoordinate in
        guard let strongSelf = self else { return }
        let location = Location(location: CLLocation(latitude: selectedCoordinate.latitude, longitude: selectedCoordinate.longitude),
                                 size: .zero)
        let messageId = UUID().uuidString // 自行生成唯一消息ID
        let message = Message(sender: strongSelf.selfSender,messageId: messageId,sentDate: Date(),kind: .location(location))
        DatabaseManager.shared.sendMessage(to: strongSelf.conversationId, otherUserEmail: strongSelf.otherUserEmail, name: strongSelf.name, newMessage: message, completion: { success in
            if success {
                print("位置消息发送成功")
            }
            else {
                print("位置消息发送失败")
            }
        })
    }
    navigationController?.pushViewController(vc, animated: true)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:15:04