适用于iOS的GoogleMaps SDK – SWIFT 3:当隐藏标记,然后添加地图视图时,cpu陷入100%

脚本

  • UIViewController在viewDidLload中将GMSMapView设置为GMSMapView
  • 一个方法将创build标记并将其存储在self.markers ,并将marker.map设置为marker.map self.view as! GMSMapView self.view as! GMSMapView

到目前为止,该应用程序performance良好

  • 稍后,另一种方法(查看切换这些标记)将所有self.markers.map设置nil

到这里一切顺利,标记从地图上消失

  • 再一次,希望这些标记返回的另一种方法,将所有self.markers.map = self.view as! GMSMapView设置self.markers.map = self.view as! GMSMapView self.markers.map = self.view as! GMSMapView

这里的CPU卡在100%(在8核心机器模拟器上)

如果self.markers.map被重置nil ,则CPU会回到self.markers.map %,并且都是好的。

这是对cpu或GoogleMaps SDK的限制吗? 有没有办法避免这个问题?

重现步骤

在提取相关的代码之后,我也添加了类似的条件,其中标签被创build为另一个标记的图标。

经过一些testing后,似乎只与处理标记的数量有关。 看到LabelCount并设置为不同的值,在我的CPU中,问题出现在200,但没有100标记(即:400标记,因为有一个额外的标记标记)

示例代码

 import UIKit import GoogleMaps class ViewController: UIViewController { // The problem is noticed when markers have a UIImage // Set below to false to see normal cpu behaviour static let LabelsMakeProblem = true static let LabelCountFine = 100 static let LabelCountProblems = 200 static let LabelCount = ViewController.LabelCountProblems static let labelWidth = 200 static let labelHeight = 20 var coords = [CLLocationCoordinate2D]() static let initLat = Double(-33) static let initLong = Double(-70) static let zoomThreshold = Float(13) var oldZoom : Float! var markers = [Int: [GMSMarker]]() var labels = [Int: [GMSMarker]]() override func viewDidLoad() { super.viewDidLoad() // Generate some random points let initCoord = CLLocationCoordinate2D(latitude: ViewController.initLat, longitude: ViewController.initLong) let deltaCoord = 0.001 for i in 0...200 { let multiplier = Double(i) self.coords.append(CLLocationCoordinate2D( latitude: initCoord.latitude + multiplier * deltaCoord, longitude: initCoord.longitude + multiplier * deltaCoord)) } // Create a map let camera = GMSCameraPosition.camera(withLatitude: ViewController.initLat, longitude: ViewController.initLong, zoom: ViewController.zoomThreshold * 1.3) let mapView = GMSMapView.map(withFrame: .zero, camera: camera) mapView.delegate = self self.view = mapView self.oldZoom = mapView.camera.zoom // Add markers let label = self.createLabel() for (idx, coord) in self.coords.enumerated() { // Init marker arrays if self.markers[idx] == nil { self.markers[idx] = [GMSMarker]() } if self.labels[idx] == nil { self.labels[idx] = [GMSMarker]() } let marker = GMSMarker(position: coord) marker.map = mapView self.markers[idx]?.append(marker) if ViewController.LabelsMakeProblem { label.text = coord.latitude.description let contextSize = CGSize(width: ViewController.labelWidth, height: ViewController.labelHeight) let opaque = false UIGraphicsBeginImageContextWithOptions(contextSize, opaque, UIScreen.main.scale) if let currentContext = UIGraphicsGetCurrentContext(){ let labelBox = CGRect(x: 2, y: 2, width: ViewController.labelWidth, height: ViewController.labelHeight) label.frame = labelBox label.layer.render(in: currentContext) let labelImage = UIGraphicsGetImageFromCurrentImageContext() let labelMarker = GMSMarker(position: coord) labelMarker.icon = labelImage labelMarker.map = mapView self.labels[idx]?.append(labelMarker) } UIGraphicsEndImageContext() } } } private func createLabel() -> UILabel{ let label = UILabel() label.backgroundColor = UIColor.clear label.shadowColor = UIColor.white label.shadowOffset = CGSize(width: 5, height: 2) label.textColor = UIColor.black label.adjustsFontSizeToFitWidth = true label.textAlignment = .center return label } func hideMarkers() { for markers in self.markers.values.makeIterator() { for marker in markers { marker.map = nil } } print("Markers hidden") } func showMarkers() { let mapView = self.view as! GMSMapView var bounds = GMSCoordinateBounds() for markers in self.markers.values.makeIterator() { for marker in markers { marker.map = mapView bounds = bounds.includingCoordinate(marker.position) } } print("Show markers at zoom:\(mapView.camera.zoom)") // Ensure we see the markers let cameraUpdate = GMSCameraUpdate.fit(bounds) mapView.animate(with: cameraUpdate) } func hideLabels() { for markers in self.labels.values.makeIterator() { for marker in markers { marker.map = nil } } print("Labels hidden") } func showLabels() { let mapView = self.view as! GMSMapView for markers in self.labels.values.makeIterator() { for marker in markers { marker.map = mapView } } print("Show labels at zoom:\(mapView.camera.zoom)") } } extension ViewController : GMSMapViewDelegate { /// Hide labels when zooming out and show them when zooming in func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) { print("Zoom update: \(position.zoom)") if position.zoom < self.oldZoom && position.zoom < ViewController.zoomThreshold { self.hideLabels() } else if position.zoom > self.oldZoom && position.zoom > ViewController.zoomThreshold { self.showLabels() } // Track changes self.oldZoom = position.zoom } } 

这是我正在使用的集群方法

 //method to detect when user scrolls map @objc(mapView:didChangeCameraPosition:) func mapView(_: GMSMapView, didChange _: GMSCameraPosition) { self.counter = self.counter + 1 self.requestForMap(counter: self.counter) } //if user did nothing for 0.2 seconds request data from server fileprivate func requestForMap(counter: Int) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in guard let `self` = self else { return } if counter == self.counter { self.sessionManager.session.invalidateAndCancel() self.requestData() } } } 

为了得到地区的引脚我在客户端做这个

 // get coordinates of visible area extension GMSMapView { func boundings() -> [String: Any] { let screenBounds = UIScreen.main.bounds let topPoint = CGPoint(x: 15, y: 60) let bottomPoint = CGPoint(x: screenBounds.width - 15, y: screenBounds.height) let shoudBeFull = self.camera.zoom > 15 //if user is zoomed in a lot request all data in area let bouding = [ "top": [ "lat": self.projection.coordinate(for: topPoint).latitude, "lon": self.projection.coordinate(for: topPoint).longitude, ], "bottom": [ "lat": self.projection.coordinate(for: bottomPoint).latitude, "lon": self.projection.coordinate(for: bottomPoint).longitude, ], "full": shoudBeFull, ] as [String: Any] return bouding } } 

那么这个数据作为JSON被传递到服务器,服务器获取对象的引脚数据,其坐标在这个边界内。 我们使用node.js,不知道它是如何工作的。

然后我有一个当前显示的引脚数组,例如var pins = [GMSMarker] ,当我从服务器获取一个对象数组后,通过这个数组,删除那些不在新数据中的并添加新的数据