场景
- UIViewController 将
self.view
设置为viewDidLload
中的GMSMapView
- 一个方法将创建标记并将它们存储在
self.markers
中,并将marker.map
设置为self.view as! GMSMapView
到目前为止,该应用程序运行良好
- 稍后,另一种方法在执行某些操作后(希望切换这些标记)将所有
self.markers.map
设置为nil
到这里一切顺利,标记从 map 上消失了
- 同样,另一种方法想要返回这些标记,将所有
self.markers.map = self.view 设置为! GMSMapView
这里 cpu 卡在 100%(在 8 核机器的模拟器上)
如果 self.markers.map
再次重置为 nil
,则 cpu 回到 ~0% 并且一切正常。
问题
这是对 cpu 或 GoogleMaps SDK 的限制吗?有没有办法避免这个问题?
重现步骤
在提取相关代码位之后,我还添加了类似的条件,其中标签被创建为另一个标记的图标。
经过一些测试,它似乎只与要处理的标记数量有关。查看 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]
,在我从服务器获取一组对象后,我遍历该数组,删除那些不在新的中数据并添加那些,这是新的
关于ios - 适用于 iOS 的 GoogleMaps SDK - SWIFT 3 : When hiding a marker and then adding the map view back, CPU 卡在 100%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43910085/