如何高效绘制动态更新的MKPolyline?解决内存占用过高问题
问题根源
你当前代码的核心问题是重复添加MKPolyline Overlay:每次收到新坐标时,都基于完整的路径数组创建新的MKPolyline,并调用addOverlay添加到地图。30分钟后,地图上会叠加约1800条完全重合的Polyline,每条都需要独立渲染,直接导致CPU占用飙升、内存溢出和卡顿。
解决方案:维护单条Polyline并高效更新
只保留一条MKPolyline实例,每次新增坐标后,通过replaceOverlay方法替换旧的Polyline,而非重复添加新的Overlay。这样地图始终只渲染一条路径,彻底解决资源占用问题。
修改后的ViewController代码
var polyline: MKPolyline? override func viewDidLoad() { super.viewDidLoad() setupBindings() mapView.delegate = self mapView.addAnnotation(viewModel.aircraftLocation) } func setupBindings() { viewModel.$simulationData.sink { [weak self] simData in guard let simData, let self else { return } DispatchQueue.main.async { // 更新经纬度显示标签 self.LatitudeLbl.text = String(format: "Lat: %.5f", simData.latitude) self.longitudeLbl.text = String(format: "Long: %.5f", simData.longitude) // 基于最新路径数组创建新的Polyline let newPolyline = MKPolyline(coordinates: &self.viewModel.aircraftPath, count: self.viewModel.aircraftPath.count) if let oldPolyline = self.polyline { // 替换旧Overlay,避免重复叠加 self.mapView.replaceOverlay(oldPolyline, with: newPolyline) } else { // 首次添加路径Overlay self.mapView.addOverlay(newPolyline) } self.polyline = newPolyline } }.store(in: &viewModel.subscriptions) } func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { guard let polylineOverlay = overlay as? MKPolyline else { return MKOverlayRenderer() } let renderer = MKPolylineRenderer(polyline: polylineOverlay) renderer.strokeColor = .purple renderer.lineWidth = 2 return renderer }
ViewModel代码(无需核心修改)
@Published public var simulationData: SimulationData? func didReceiveSimulationUpdate(simulation: SimulationData) { // 将新坐标追加到路径数组 aircraftPath.append(simulation.aircraft.location) DispatchQueue.main.async { UIView.animate(withDuration: 0.3) { self.simulationData = simulation self.aircraftLocation.coordinate = simulation.aircraft.location } } }
额外优化建议
- 坐标去重:如果连续收到的坐标距离极近(比如小于1米),可以跳过添加,减少路径数组长度和Polyline更新次数。
- 批量更新:若每秒一次更新过于频繁,可改为每2-3秒合并一次坐标再刷新路径,降低地图渲染压力。
- 路径截断:如果不需要保留完整历史路径,可限制路径数组长度(比如只保留最近1000个点),避免数组无限增长导致的内存占用。
内容的提问来源于stack exchange,提问作者Fred Novack
相关产品推荐
相关产品推荐

