如何在Mapbox点标注中为两个不同标注设置不同的自定义图片
问题原因
你当前实现失效的核心问题如下:
- 不同样式标注共用了同一个复用ID,首次创建标注图片后,后续标注会直接复用已生成的实例,不会重新执行图片匹配逻辑
- 仅通过纬度判断标注归属不严谨,存在不同标注纬度相同的误判风险
- 未排除地图默认的用户位置标注,可能引发逻辑异常
- 图片资源强制解包存在崩溃风险
快速修复方案
首先确保你已经给mapView设置了代理:mapView.delegate = self,且当前控制器遵守MGLMapViewDelegate协议,直接修改代理方法如下:
func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? { // 过滤非自定义的点标注 guard annotation is MGLPointAnnotation else { return nil } var reuseId: String var targetImage: UIImage? // 同时匹配经纬度确认标注类型,分配不同的复用ID if annotation.coordinate.latitude == fromLat && annotation.coordinate.longitude == fromLon { reuseId = "fromPoint" targetImage = UIImage(named: "location") } else if annotation.coordinate.latitude == toLat && annotation.coordinate.longitude == toLon { reuseId = "toPoint" targetImage = UIImage(named: "map7") } else { return nil } // 校验图片资源存在 guard let validImage = targetImage else { return nil } // 对应复用ID出队,不存在则新建 var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: reuseId) if annotationImage == nil { let adjustedImage = validImage.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: 0, bottom: validImage.size.height/2, right: 0)) annotationImage = MGLAnnotationImage(image: adjustedImage, reuseIdentifier: reuseId) } return annotationImage }
更稳定的自定义标注方案
如果后续标注数量多、类型复杂,建议用自定义标注类避免坐标匹配的误判问题:
- 新增自定义标注类
class CustomMapAnnotation: MGLPointAnnotation { enum AnnotationType { case startPoint case endPoint } var type: AnnotationType = .startPoint }
- 修改标注添加逻辑
func showFromAnnotation(){ let startAnnotation = CustomMapAnnotation() startAnnotation.coordinate = CLLocationCoordinate2D(latitude: fromLat, longitude: fromLon) startAnnotation.title = fromHouseName startAnnotation.type = .startPoint mapView.addAnnotation(startAnnotation) let endAnnotation = CustomMapAnnotation() endAnnotation.coordinate = CLLocationCoordinate2D(latitude: toLat, longitude: toLon) endAnnotation.title = toHouseName endAnnotation.type = .endPoint mapView.addAnnotation(endAnnotation) }
- 代理方法根据标注类型匹配样式
func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? { guard let customAnno = annotation as? CustomMapAnnotation else { return nil } let reuseId: String var targetImage: UIImage? switch customAnno.type { case .startPoint: reuseId = "startPointId" targetImage = UIImage(named: "location") case .endPoint: reuseId = "endPointId" targetImage = UIImage(named: "map7") } guard let validImage = targetImage else { return nil } var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: reuseId) if annotationImage == nil { let adjustedImage = validImage.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: 0, bottom: validImage.size.height/2, right: 0)) annotationImage = MGLAnnotationImage(image: adjustedImage, reuseIdentifier: reuseId) } return annotationImage }
内容的提问来源于stack exchange,提问作者biyush shrestha
相关产品推荐
相关产品推荐

