适用于 iOS 的 GoogleMaps SDK - SWIFT 3:隐藏标记然后重新添加地图视图时,cpu 卡在 100% [英] GoogleMaps SDK for iOS - SWIFT 3: When hiding a marker and then adding the map view back, the cpu gets stuck at 100%

查看:12
本文介绍了适用于 iOS 的 GoogleMaps SDK - SWIFT 3:隐藏标记然后重新添加地图视图时,cpu 卡在 100%的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  • UIViewController 在 viewDidLload
  • 中将 self.view 设置为 GMSMapView
  • 一个方法将创建标记并将它们存储在 self.markers 中并将 marker.map 设置为 self.view as!GMSMapView
  • UIViewController sets self.view as GMSMapView in viewDidLload
  • A method will create markers and store them in self.markers and set marker.map to the self.view as! GMSMapView

到目前为止,该应用运行良好

So far the app behaves well

  • 稍后,在某些操作(寻找切换这些标记)之后的另一个方法将所有 self.markers.map 设置为 nil

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

Up to here all goes well and the markers are gone from the map

  • 同样,另一种想要返回这些标记的方法,将所有 self.markers.map = self.view 设置为!GMSMapView

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

Here the cpu gets stuck at 100% (on a simulator in an 8 core machine)

如果 self.markers.map 再次被重置为 nil,cpu 会回到 ~0% 并且一切正常.

If the self.markers.map gets reset to nil again, the cpu goes back to ~0% and all is good.

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

Is this a limitation on cpu or GoogleMaps SDK? Is there a way to avoid the problem?

在提取相关的代码位后,我还添加了类似的条件,其中一个标签被创建为另一个标记的图标.

After extracting the bits of code related, I added also similar conditions where a Label is being created as an icon for another marker.

经过一些测试,它似乎只与要处理的标记数量有关.请参阅 LabelCount 并设置为不同的值,在我的 cpu 中,问题出现在 200 而不是 100 个标记(即:400 个标记,因为标签有一个额外的标记)

After some tests it seems it is related on the amount of markers to process only. See LabelCount and set to different values, in my cpu the problem appeared with 200 but not with 100 markers (ie: 400 markers as there is an extra marker for the label)

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()
        }
    }
}

为了获得区域内的别针,我在客户端上执行此操作

to get pins in area I do this on client

// 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 传递给服务器,服务器获取对象的 pin 数据,其坐标在此边界内.我们正在使用 node.js,不确定它在那里是如何工作的.

then this data as JSON is passed to the server and the server gets pins' data for objects, coordinates of which are inside this bounding. We are using node.js, not sure how it works there.

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

Then I have an array of currently displayed pins like var pins = [GMSMarker], after I get an array of objects from server I go through this array, remove those, which are not in new data and add those, which are new

这篇关于适用于 iOS 的 GoogleMaps SDK - SWIFT 3:隐藏标记然后重新添加地图视图时,cpu 卡在 100%的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆