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

Swift中Yandex Map多标记点击事件失效问题求助

解决Yandex地图多标记点击仅最后一个生效的问题

问题原因

  • 你用单个变量yandexMapObjectTapListener存储监听器,循环中每次赋值都会覆盖之前的实例,导致只有最后一个监听器能保留强引用,其余的被ARC自动销毁
  • 若用局部变量存储监听器,循环结束后局部变量生命周期终止,监听器也会被释放,自然无法触发点击事件

解决方案

  1. 添加数组存储所有监听器
    在控制器类中声明一个数组属性,用来保存每个标记对应的监听器实例:
private var mapTapListeners: [YandexMapObjectTapListener] = []
  1. 循环中创建并保存监听器
    替换原来的单个变量赋值逻辑,把每个新创建的监听器加入数组,确保强引用不丢失:
func showMarkers() {
    let mapObjects = yandexMapView.mapWindow.map.mapObjects
    mapObjects.clear()
    // 清理旧监听器,避免内存泄漏
    mapTapListeners.removeAll()
    
    for pickupPoint in masterVC?.aryPickupPoints ?? [] {
        if pickupPoint.latitude != 0 && pickupPoint.longitude != 0 {
            let point = YMKPoint(latitude: pickupPoint.latitude!, longitude: pickupPoint.longitude!)
            
            let placemark = mapObjects.addPlacemark(with: point)
            placemark.userData = pickupPoint
            
            switch pickupPoint.pickupType {
            case 3:
                if let image = UIImage(named: "lockerPin") {
                    placemark.setIconWith(self.imageWithImage(image: image, scaledToSize: CGSize(width: 30, height: 40)))
                }
            default:
                if let image = UIImage(named: "otherPin") {
                    placemark.setIconWith(self.imageWithImage(image: image, scaledToSize: CGSize(width: 30, height: 40)))
                }
            }
            dLog("------------- \(point)----------------")
            
            // 创建监听器并加入数组保存
            let listener = YandexMapObjectTapListener(controller: self)
            mapTapListeners.append(listener)
            placemark.addTapListener(with: listener)
        }
    }
}
  1. 监听器类保持原有实现
    你的YandexMapObjectTapListener类对控制器使用了弱引用,不会造成循环引用,无需修改:
//MARK: - YandexMapObjectTapListener
private class YandexMapObjectTapListener: NSObject, YMKMapObjectTapListener {
    private weak var controller: UIViewController?
    var selectedPickupPoint: PickupPoint?

    init(controller: UIViewController) {
        self.controller = controller
    }

    func onMapObjectTap(with mapObject: YMKMapObject, point: YMKPoint) -> Bool {
        guard let marker = mapObject as? YMKPlacemarkMapObject else { return false }
        let pickupPoint = marker.userData as? PickupPoint
        let data = ["pickupPoint": pickupPoint as Any,
                    "marker": marker] as [String : Any]
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: NotificationObserver.ShowBottomSheet), object: nil, userInfo: data)
        return true
    }
}

原理说明

数组会对每个监听器保持强引用,确保它们不会在循环结束后被销毁,每个标记的点击监听器都能正常存活并响应事件。同时在清理地图标记时清空数组,避免无用监听器占用内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:27:44