Я попытаюсь объяснить мою проблему и то, что я сделал до сих пор.
Введение
Я использую библиотеку iOS Utils от Google Maps для отображения около 300 маркеров на карте.
Алгоритм, используемый для кластеризации: GMUNonHierarchicalDistanceBasedAlgorithm
.
По сути, наши пользователи могут отправлять нам погоду, которую они наблюдают , через свое окно , чтобы мы могли отображать погоду в реальном времени по всему миру.
Это позволяет нам улучшать и / или корректировать прогнозы погоды.
Но мой опыт прокрутки / масштабирования совсем не гладкий. Кстати, я тестирую его с iPhone X ...
Давайте рассмотрим суть вопроса:
Вот как я настраиваю ClusterManager
private func configureCluster(array: [Observation]) -> Void {
let iconGenerator = GMUDefaultClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: mapView,
clusterIconGenerator: iconGenerator)
renderer.delegate = self
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm,
renderer: renderer)
clusterManager.add(array)
clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
}
Вот мой Observation
класс, я постарался сделать его простым:
class Observation : NSObject, GMUClusterItem {
static var ICON_SIZE = 30
let timestamp: Double
let idObs: String
let position: CLLocationCoordinate2D
let idPicto: [Int]
let token: String
let comment: String
let altitude: Double
init(timestamp: Double, idObs: String, coordinate: CLLocationCoordinate2D, idPicto: [Int], token: String, comment: String, altitude: Double) {
self.timestamp = timestamp
self.idObs = idObs
self.position = coordinate
self.idPicto = idPicto
self.token = token
self.comment = comment
self.altitude = altitude
}
}
И, наконец, метод делегата для рендеринга:
func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
if let cluster = marker.userData as? GMUCluster {
if let listObs = cluster.items as? [Observation] {
if listObs.count > 1 {
let sortedObs = listObs.sorted(by: { $0.timestamp > $1.timestamp })
if let mostRecentObs = sortedObs.first {
DispatchQueue.main.async {
self.setIconViewForMarker(marker: marker, obs: mostRecentObs)
}
}
} else {
if let obs = listObs.last {
DispatchQueue.main.async {
self.setIconViewForMarker(marker: marker, obs: obs)
}
}
}
}
}
}
Пользователи могут отправлять только одно наблюдение, но это наблюдение может быть составлено из различных погодных явлений (таких как Облака + Дождь + Ветер) или только Дождя, если они хотят.
Чтобы дифференцировать их, если это всего лишь 1 феномен, свойство marker.iconView
будет установлено напрямую.
С другой стороны, если это наблюдение с несколькими феноменами, я создам вид, содержащий все изображения, представляющие феномен.
func setIconViewForMarker(marker: GMSMarker, obs: Observation) -> Void {
let isYourObs = Observation.isOwnObservation(id: obs.idObs) ? true : false
if isYourObs {
marker.iconView = Observation.viewForPhenomenomArray(ids: obs.idPicto, isYourObs: isYourObs)
} else {
// Observation with more than 1 phenomenom
if obs.idPicto.count > 1 {
marker.iconView = Observation.viewForPhenomenomArray(ids: obs.idPicto, isYourObs: isYourObs)
// Observation with only 1 phenomenom
} else if obs.idPicto.count == 1 {
if let id = obs.idPicto.last {
marker.iconView = Observation.setImageForPhenomenom(id: id)
}
}
}
}
И последний кусок кода, чтобы показать вам, как я создаю это пользовательское представление (я думаю, что моя проблема, вероятно, здесь)
class func viewForPhenomenomArray(ids: [Int], isYourObs: Bool) -> UIView {
let popupView = UIView()
popupView.frame = CGRect.init(x: 0, y: 0, width: (ICON_SIZE * ids.count) + ((ids.count + 1) * 5) , height: ICON_SIZE)
if (isYourObs) {
popupView.backgroundColor = UIColor(red:0.25, green:0.61, blue:0.20, alpha:1)
} else {
popupView.backgroundColor = UIColor(red:0.00, green:0.31, blue:0.57, alpha:1)
}
popupView.layer.cornerRadius = 12
for (index, element) in ids.enumerated() {
let imageView = UIImageView(image: Observation.getPictoFromID(id: element))
imageView.frame = CGRect(x: ((index + 1) * 5) + index * ICON_SIZE, y: 0, width: ICON_SIZE, height: ICON_SIZE)
popupView.addSubview(imageView)
}
return popupView
}
Я также попытался с очень маленьким изображением, чтобы понять, возникает ли проблема при рендеринге большого количества PNG на карте, но, если серьезно, это iPhone X, он должен быть в состоянии отобразить на карте простой значок погоды.
Как вы думаете, я делаю что-то не так? Или это известная проблема в SDK Google Maps? (Я читал, что он установлен на 30 кадров в секунду)
Как вы думаете, рендеринг большого количества изображений (как marker.image) на карте занимает столько графического процессора? До точки, где опыт вообще не приемлем?
Если у вас есть какие-либо советы, я приму их все.