efremidze / cluster Goto Github PK
View Code? Open in Web Editor NEWEasy Map Annotation Clustering ๐
License: MIT License
Easy Map Annotation Clustering ๐
License: MIT License
I guess there is no way to add images to annotations. I think its gonna be awesome feature for this project.
When I run my project I get this runtime issue: UIView.bounds must be used from main thread only
This is in Cluster.swift
line 118
Thanks
Hello again!
It would be great to be able to disable clustering from a certain zoom level. For instance it can be a property or a method e.g. :
clusterManager.zoomLevel = 10
Where:
clusterManager
is an instance of Cluster
classzoomLevel
is a property that takes a numeric parameterThe inspiration was taken from Google Maps API
.
Thank you for doing an amazing job!
Can you parametrize border and text color, adding paramters to set the colors instead of white?
label.textColor = customColor // label.textColor = .white
layer.borderColor = customColor // UIColor.white.cgColor
Our background for example is white and I modified in my clash but if you allow to set them as we wish in the library it's better.
I want to add that the way to change the color of text:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if view == nil {
view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: type)
(view as! ClusterAnnotationView).countLabel.textColor = UIColor.black
(view as! ClusterAnnotationView).layer.borderColor = UIColor.black.cgColor
} else {
view?.annotation = annotation
}
return view
}
removing the line below in Annotation the layer.borderColor can be set from outside
layer.borderColor = UIColor.white.cgColorlayer.borderColor = UIColor.white.cgColor
Thanks
Hey! I have tested the project using 2 pins only. If you zoom out a little, it shows cluster count 4 if it has to be one. If something at all
Hi!
What a great repo!
I strumbled on something that may be a bug.
When moving the mapView very slightly, the ClusterManager removes some ClusterAnnotation and re-add them right away. In does not seems to happen with Annotations.
Example of logs:
Deleting <Cluster.ClusterAnnotation: 0x171884dd0>
Deleting <Cluster.ClusterAnnotation: 0x171887940>
Deleting <Cluster.ClusterAnnotation: 0x175c90770>
Deleting <Cluster.ClusterAnnotation: 0x171892ca0>
Adding <Cluster.ClusterAnnotation: 0x171884dd0>
Adding <Cluster.ClusterAnnotation: 0x171887940>
Adding <Cluster.ClusterAnnotation: 0x175c90770>
Adding <Cluster.ClusterAnnotation: 0x171892ca0>
It's not very bad but if you have some processing done in the "viewFor" method of the mapView this is annoying.
I tried to play with the Set but could not figure out what was wrong. It seems that for some reason some ClusterAnnotations in before and after are considered unequal, whereas they are equal.
Any idea ?
Any help will be greatly appreciated.
Hello,
Kudos for the great work on the library so far :)
I faced an issue when I tried to group pins based on a given type that I have.
It would be really convenient if I could configure multiple Cluster Manager instances. I've seen that feature in some older libs.
Do you think that would be possible to achieve in your library?
Thank you,
Granit
Hello,
Thanks for this useful library. I get an error implement it in my project just like your example. Example project is working properly but When I add library to my project and use it I got this error.
Getter for 'borderColor' with Objective-C selector 'borderColor' conflicts with getter for 'borderColor' from superclass 'UIView' with the same Objective-C selector
in here:
class BorderedClusterAnnotationView: ClusterAnnotationView {
let borderColor: UIColor //I got error on this line
What is the problem? I can't solve it.
Thanks
iOS 11, Cluster v. 2.1.3
We are using png image for cluster pin. This png image is scaled depending on the size of the clusters.
So the more places clustered in the cluster, the bigger the scaling factor is. In ios 10 it works well, but in iOS 11 there is a strange expand/ shrinking animation.
Any idea where this animation is coming from and how can we get rid of it?
Below is the code that we are using to scale the image and the gif.
class RetailerClusterAnnotationView: ClusterAnnotationView {
var pinTextColor: UIColor = .white
required init(annotation: MKAnnotation?, reuseIdentifier: String?, style: ClusterAnnotationStyle, pinTextColor: UIColor) {
self.pinTextColor = pinTextColor
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier, style: style)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func configure(with type: ClusterAnnotationStyle) {
// super.configure(with:type)
guard let annotation = annotation as? ClusterAnnotation else { return }
switch type {
case let .image(image):
backgroundColor = .clear
let count = annotation.annotations.count
let scale = self.scale(for: count)
countLabel.text = "\(count)"
countLabel.textColor = pinTextColor
self.image = image?.imageResize(sizeChange: CGSize(width: 50*scale, height: 50*scale))
case let .color(color, radius):
let count = annotation.annotations.count
backgroundColor = color
var diameter = radius * 2
switch count {
case _ where count < 8: diameter *= 0.6
case _ where count < 16: diameter *= 0.8
default: break
}
frame = CGRect(origin: frame.origin, size: CGSize(width: diameter, height: diameter))
countLabel.text = "\(count)"
}
}
override func prepareForReuse() {
super.prepareForReuse()
countLabel.text = nil
image = nil
}
func updateFor(annotation: ClusterAnnotation, with type: ClusterAnnotationStyle){
self.annotation = annotation
configure(with: type)
}
private func scale(for annotationsCount: Int) -> CGFloat {
switch annotationsCount {
case _ where annotationsCount < 25: return 0.75
case _ where annotationsCount < 50: return 1
case _ where annotationsCount < 100: return 1.25
case _ where annotationsCount >= 100: return 1.5
default: return 1
}
}
}
Hey guys and very nice work! Congrats to all of you ๐
Although I have one question.
I'm running one app about Events.
And some Venues have multiple Events in the exact same location (lat, lon) in the map.
Do we have a workaround about it?
Cause if i zoom in this location spot, the cluster doesn't break. And this is normal.
Thanks a lot !
for node in tree.annotations(in: mapRect) {
totalLatitude += node.coordinate.latitude
totalLongitude += node.coordinate.longitude
annotations.append(node)
hash[node.coordinate, default: MKAnnotation] += [node] //On This Line
}
Ambiguous use of 'subscript(_:default:)'
How to fix it?
Hello,
How do I change the picture of the single pin?
Currently I can only change the color. I would like to put a custom image on the pin-
thank you.
Hello,
The example project does not build. The clusterView call is not defined.
Thanks
I try to select an annotation right after adding it to the cluster manager. To make it appear on the map I have to call clusterManager.reload. However this method is async. In my case I try to select the annoation in code right after calling reload. However the annoation is not available yet.
clusterManager.add(annotation)
clusterManager.reload(mapView, visibleMapRect: mapView.visibleMapRect)
mapView.selectAnnotation(annotation, animated: true) // can not find annotation
Is there any way I can know when reload has finished? Can you add a callback?
Hey!
Sometimes pins are clustered into more than one cluster, and these clusters are overlapping each other. That is really confusing, sometimes two overlapping cluster pins are exactly on the same place on the map, which looks like a mistake in calculation.
Is that normal, expected behaviour of the framework?
I'm working with a map which has both: annotations managed by a ClusterManager
and other annotations which are not clustered at all.
I've found that when one of those non-clustered annotations is visible and I call clusterManager.reload(_:, visibleMapRect:)
the non-clustered annotation gets removed.
Checking source code of release 1.0.7 I've found this:
https://github.com/efremidze/Cluster/blob/1.0.7/Sources/Cluster.swift#L168
let before = NSMutableSet(array: mapView.annotations)
before.remove(mapView.userLocation)
This takes all annotations in the map (regardless they are managed by this cluster or not) and removes them according to what the manager decides to show or not.
Changing this by:
let annotationsInCluster = NSSet(array: self.annotations)
let before = NSSet(
array: mapView.annotations.filter {
$0 is ClusterAnnotation || annotationsInCluster.contains($0)
}
)
Seems to solve my problem.
I would normally open a pull request but I don't have any test for this use case and I'm not quite sure why that line was like it was before so until I have some feedback I won't open a pull request.
PS: Nice library!
Add an animation for the grouping and ungrouping of annotations.
hi,
having another issue as below.
When i drag the map i the cluster pin changes it's location. I did print toAdd and toRemove array of annotations with coordinates and the log is attached below. When i drag the map "regionDidChangeAnimated" method called and here we added below line :
clusterManager.reload(MapView, visibleMapRect: MapView.visibleMapRect)
and in the reload method i did add below things.
open func reload(_ mapView: MKMapView, visibleMapRect: MKMapRect) {
let zoomScale = ZoomScale(mapView.bounds.width) / visibleMapRect.size.width
let (toAdd, toRemove) = clusteredAnnotations(mapView, zoomScale: zoomScale, visibleMapRect: visibleMapRect)
for annoadd in toAdd {
print("Location of toAdd Annotations : \(annoadd.coordinate)")
}
for annorem in toRemove {
print("Location of toRemove Annotations : \(annorem.coordinate)")
}
mapView.removeAnnotations(toRemove)
mapView.addAnnotations(toAdd)
visibleAnnotations.subtract(toRemove)
visibleAnnotations.add(toAdd)
}
The issue is when i drag or scroll the map the pin changes its Coordinate. please look into GIF.
Log :
NOTE : We are showing annotations not pin on the map.
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.07258800000001, longitude: -81.508352789999989)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.073535866666674, longitude: -81.506221999999994)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.072601486018961, longitude: -81.508352789999989)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.073549352685632, longitude: -81.506221999999994)Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.07258800000001, longitude: -81.508352789999989)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.073535866666674, longitude: -81.506221999999994)Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.072614972037925, longitude: -81.508352789999989)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.073562838704596, longitude: -81.506221999999994)Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.072601486018961, longitude: -81.508352789999989)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.073549352685632, longitude: -81.506221999999994)Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.072628458056883, longitude: -81.508352789999989)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.073576324723554, longitude: -81.506221999999994)Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.072614972037925, longitude: -81.508352789999989)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.073562838704596, longitude: -81.506221999999994)Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.072641944075848, longitude: -81.508352789999989)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.073589810742519, longitude: -81.506221999999994)Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.072628458056883, longitude: -81.508352789999989)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.073576324723554, longitude: -81.506221999999994)After region change
after adding all pins (cluster pins) on the map and scroll the map
UIView.animate
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.072655430094805, longitude: -81.508352789999989)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.073603296761476, longitude: -81.506221999999994)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.072641944075848, longitude: -81.508352789999989)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.073589810742519, longitude: -81.506221999999994)after adding all pins (cluster pins) on the map and scroll the map
UIView.animate
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.072668916113777, longitude: -81.508352789999989)
Location of toAdd Annotations : CLLocationCoordinate2D(latitude: 41.073616782780441, longitude: -81.506221999999994)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.072655430094805, longitude: -81.508352789999989)
Location of toRemove Annotations : CLLocationCoordinate2D(latitude: 41.073603296761476, longitude: -81.506221999999994)
Kindly help me Please.
Thank you.
Use ===
instead of ==
Same issue in the FB library as well. As I slowly zoom out, my pins pop in and out of a single cluster. I can be entirely zoomed out and have two pins overlapping. I learned that this does not happen on particular zoom levels (2-20), but particular fractions of a zoom level.. if that makes any sense.
I can't see why it would be returning the wrong annotation type.
Code seems to run fine in the example however I ran a pod install and noticed two differences in the Annotation.swift and Cluster.swift files that are causing errors with the example code and instructional code.
https://stackoverflow.com/questions/44262514/clustering-with-mapkit-in-ios
Hello,
I've faced an issue where I have a map with about 25
pins. Half of them is located in Asia
and the other half in US
. When I zoom out the map and look at the Asian
cluster everything works great. But when I swipe the map to the US
cluster, it simply does not display at the same zoom level. When zoom it in a little bit, then it appears. US
cluster is a little bit smaller e.g. Asian 14 pins vs 11 pins in US.
As I understand that behaviour has something with spatial division of pins in clusters. The Asian cluster is a 'parent' one for US, that is why they both cannot be displayed at the same zoom level.
The question is: How to display the US
cluster when map is zoomed out at max distance?
(1) Cluster views change their location constantly when zooming (even very slightly) on low zoom, (2) they move far from the actual pins locations,
(3) occasionally on very low zoom pins pop up.
All this somehow linked to this method manager.shouldCenterAlignClusters = true
Add option to cluster like iOS 11
https://developer.apple.com/documentation/mapkit/mkmapviewdelegate/2867923-mapview
extension MapKitViewController: ClusterDelegate {
func mapView(_ mapView: MKMapView, clusterAnnotationForMemberAnnotations memberAnnotations: [MKAnnotation]) -> ClusterAnnotation {
let annotation = ClusterAnnotation(memberAnnotations: memberAnnotations)
annotation.title = "Emojis"
return annotation
}
}
I'm having a problem with my program crashing while using clustering manager. I'm trying to build an app that will display the status of houses using coloured icons.
It gives me an index out of range error when the map reloads, however the error only occurs occasionally. I can't tell from the stack trace where the error is occuring, since it takes me to a line Cluster.swift. Does anyone have any idea on what sort of thing could be causing the error? I have no idea what array could be out of range to cause this error.
I'm thought the error is coming from the function below (as it sets the MKAnnotationView) but I swapped it for the function in the example project and it still crashes.
//Display annotations and pins for the map
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var reuseId = ""
let orangeColor = UIColor(red: 255/255, green: 149/255, blue: 0/255, alpha: 1)
let redColor = UIColor(red: 255/255, green: 0/255, blue: 0/255, alpha: 1)
let greenColor = UIColor(red: 6/255, green: 152/255, blue: 6/255, alpha: 1)
if let annotation = annotation as? ClusterAnnotation {
let identifier = "Cluster"
var view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if view == nil {
if let annotation = annotation.annotations.first as? Annotation, let type = annotation.type {
view = BorderedClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: type, borderColor: .white)
} else {
let allAnnos = annotation.annotations
if (!allAnnos.isEmpty && !addressStatus.isEmpty){
for anno in allAnnos {
if (addressStatus[anno.title!!] == "Offline") {
view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(redColor, radius: 25))
return view
} else if (addressStatus[anno.title!!] == "Error"){
view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(orangeColor, radius: 25))
return view
}
}
}
view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(greenColor, radius: 25))
}
} else {
let allAnnos = annotation.annotations
if (!allAnnos.isEmpty && !addressStatus.isEmpty) {
for anno in allAnnos {
if (addressStatus[anno.title!!] == "Offline") {
view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(redColor, radius: 25))
return view
} else if (addressStatus[anno.title!!] == "Error"){
view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(orangeColor, radius: 25))
return view
}
}
view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(greenColor, radius: 25))
}
}
return view
} else {
reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
let address = annotation.title
if (addressStatus[address!!] == "OK") {
pinView?.image = UIImage(named:"House Icon Green.png")!
} else if (addressStatus[address!!] == nil) {
pinView?.image = UIImage(named:"House Icon Black.png")!
} else if (addressStatus[address!!] == "Error") {
pinView?.image = UIImage(named:"House Icon Orange.png")!
} else if (addressStatus[address!!] == "Offline") {
pinView?.image = UIImage(named:"House Icon Red.png")!
}
pinView?.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
return pinView
}
}
Any help would be greatly appreciated thank you!
Hi,
I really like your solution as other's I've been using were written in Objective-C and I've run into some bridging issues. But I've run into issue here as well.
Common pattern I want to use is that when user selects cluster, app zooms in to make all annotations in that cluster visible. So I've implemented delegate method to the example to try that.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let annotation = view.annotation else { return }
if let cluster = annotation as? ClusterAnnotation {
mapView.showAnnotations(cluster.annotations, animated: true)
}
}
The behavior I get doesn't look nice. When the cluster is tapped, pins are added to map and when mapView(regionDidChangeAnimated:)
is called, tapped cluster is removed and if some of the newly added pins are clusters they are transformed to reflect that. Would it be possible to do that in a better way?
Thanks
Hello,
commit "710c605aa47f92da52f7f7f5618650ca2a28e64a" changed protection attribute of type property.
OLD
public var type: ClusterAnnotationType? {
didSet {
configure()
}
}
NEW
let type: ClusterAnnotationType
What was the reasoning behind this move? Could you please change it back to public?
Thanks a lot.
Hi!
I have a custom annotation class named MyAnnotations, i made an array:
var newArray:[MyAnnotation] = []
then i add annotations to that array:
self.newArray.append(annotation)
and then self.manager.add(self.newArray)
now i can see annotations and clusters on map but i can't access properties of MyAnnotation class, if i make: let MyAnnotations = view.annotation as! MyAnnotations i get:
Could not cast value of type 'Cluster.ClusterAnnotation' (0x7feca9419090) to 'app.MyAnnotations'
I really need to access all properties of that class, can you help me?
He
Hello!
Hope all is well, I have a really quick question. I've looked through the previously posted issues and don't seem to see anyone else asking. How do you perform an action whenever a rightCalloutAccessoryView button is clicked or whenever an individual annotation is clicked. I'm attempting to use this function to test my button being fired but no luck
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
print("pressed")
}
Hi,
It's great lib and i would like to thank you for making it easier.
Here i am facing one issue regarding the selecting annotation.
When i select annotation the map is changed it's region. you can see in the below gif.
There are two issues
as you can see thay the zoom level of the map is so that both end (left and right) pin is cut. i tried a lot but when ever i reload the cluster it always gives me this result. You can see it in the GIF after stopped progressview.
when i tap on diff diff annotations i select the annotation and reload cluster method is called from regionDidChangeAnimated as we need to show that annotation. but this time the map is getting don and down the annotations are changing positions on map and the map moves :(.
Please help me.
First off, thanks for getting this project started! Loving the simplicity and Swifty-ness and the simplicity so far, a fresh change of pace compared to CCH and other clustering libraries out there.
A quick question: I'm finding myself needing to wrap all my ClusterManager.add calls in a helper function that detects duplicates. Right now, it's possible to add the same instance to the ClusterManager multiple times (frustrating as it creates a permanent 'cluster' at that location).
Was there a reason for that? It's a little frustrating from a user's perspective, but curious to hear your thoughts.
(Happy to submit a PR for this, pending the response)
Hi, this might have been raised before but not too sure.
I have a manager which has annotations, obviously some are clustered.
I want to select an annotation programmatically but if it is in a cluster, the view of the annotation is nil and therefore cannot be selected.
How would I select an annotation (i.e. move to the cluster, open the cluster and select the annotation that was inside it)?
I've tried moving to the location where the cluster should be without animation, but it can't be selected somehow.
Any ideas?
Hello There,
After install the Cluster pod on my project and without make any further changes. The application got 3 erros.
These 2 :
visibleAnnotations.subtract(Set(toRemove as! [NSObject]))
visibleAnnotations.formUnion(Set(toAdd as! [NSObject]))
With : Type 'NSObject' does not conform to protocol 'MKAnnotation'
And these 1:
let after = Set(clusteredAnnotations as! [NSObject])
With : Type 'NSObject' does not conform to protocol 'MKAnnotation'
It's normal by default the pop to have this erros?
Hello again!
As I am adding a lot of pins on my map, I am facing an issue with grouping. The grouping algorithm seems not to be predictive. If I zoom/unzoom a little bit, sometime a pin will be part of group 1, and sometime on group 2. This can lead to weird things (see attached video).
Is it easy to fix or not? :)
iOS 10/11
Any device
Roughly on 3000+ locations while scrolling the map (w/o zooming) cluster recalculation freezes the map for a couple of seconds (fully unresponsive). The older the processor the longer the freeze.
Even slight scrolling causes this freeze.
It's worth also to note that for the same map, with the same number of locations there is no such a freeze when zooming out/in, although recalculation should be similar.
When single annotation tapped, how do I get the index of the backing array of data
I have an array of objects, e.g. Shop
object, and for each I have created an Annotation object and added them to the ClusterManager
When user taps on a single annotationView and mapView: didSelect:
is called, how do I get the correct index of the Shop
array? This should be the Shop at the coordinates that the user has tapped on
Hello again!
I had a (random) crash today saying:
'NSInvalidArgumentException', reason: '*** -[__NSSetM addObject:]: object cannot be nil'
Here is the entire stack trace:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSSetM addObject:]: object cannot be nil'
*** First throw call stack:
(
0 CoreFoundation 0x0000000105ed4b0b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x0000000105939141 objc_exception_throw + 48
2 CoreFoundation 0x0000000105e29e3f -[__NSSetM addObject:] + 783
3 MapKit 0x000000010514b08b __30-[MKQuadTrie _itemsInMapRect:]_block_invoke + 634
4 MapKit 0x000000010514a89e _Z17__depthFirstApplyP14MKQuadTrieNodeU13block_pointerF28MKQuadTrieTraversalDirectiveS0_E + 94
5 MapKit 0x000000010514999c -[MKQuadTrie _itemsInMapRect:] + 343
6 MapKit 0x0000000105149b0c -[MKQuadTrie itemsInMapRect:] + 304
7 MapKit 0x0000000105149f7d -[MKQuadTrie allItems] + 104
8 MapKit 0x0000000105132300 -[MKAnnotationManager annotations] + 73
9 MapKit 0x000000010506b6c7 -[MKMapView annotations] + 39
10 Cluster 0x0000000104e3b6cf _TFC7Cluster14ClusterManager20clusteredAnnotationsfTCSo9MKMapView14visibleMapRectVSC9MKMapRect9operationCSo9Operation_T5toAddGSaPSo12MKAnnotation__8toRemoveGSaPS4____ + 8079
11 Cluster 0x0000000104e391d4 _TFFC7Cluster14ClusterManager6reloadFTCSo9MKMapView14visibleMapRectVSC9MKMapRect_T_U_FT_T_ + 420
12 Cluster 0x0000000104e39588 _TPA__TFFC7Cluster14ClusterManager6reloadFTCSo9MKMapView14visibleMapRectVSC9MKMapRect_T_U_FT_T_ + 136
13 Cluster 0x0000000104e396e7 _TTRXFo___XFdCb___ + 39
14 Foundation 0x0000000105443237 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
15 Foundation 0x0000000105442f3b -[NSBlockOperation main] + 101
16 Foundation 0x00000001054416f7 -[__NSOperationInternal _start:] + 627
17 Foundation 0x000000010543d47c __NSOQSchedule_f + 198
18 libdispatch.dylib 0x000000010a29e05c _dispatch_client_callout + 8
19 libdispatch.dylib 0x000000010a27c94f _dispatch_queue_serial_drain + 221
20 libdispatch.dylib 0x000000010a27d669 _dispatch_queue_invoke + 1084
21 libdispatch.dylib 0x000000010a27fec4 _dispatch_root_queue_drain + 634
22 libdispatch.dylib 0x000000010a27fbef _dispatch_worker_thread3 + 123
23 libsystem_pthread.dylib 0x000000010a630616 _pthread_wqthread + 1299
24 libsystem_pthread.dylib 0x000000010a6300f1 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Here is the source file:
//
// MapController.swift
//
import Foundation
import UIKit
import MapKit
import Cluster
// MARK: - MapController class
class MapController: UIViewController {
// MARK: Properties
fileprivate let clusterManager = ClusterManager()
// MARK: Outlets
@IBOutlet weak var mapView: MKMapView!
// MARK: Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
// Initial region
self.mapView.setRegion(/* random things */, animated: false)
}
}
// MARK: - Partners displayable
extension MapController: PartnersDisplayable {
func update(partners: [Partner]) {
// Remove partners without locations
let filteredPartners = partners.filter { $0.location != nil }
// Create annotations
let annotations = filteredPartners.map {
return PartnerAnnotation(partner: $0)
}
// Add annotations to the cluster manager
self.clusterManager.removeAll()
self.clusterManager.add(annotations)
self.clusterManager.reload(self.mapView, visibleMapRect: self.mapView.visibleMapRect)
}
}
// MARK: - Map view delegate
extension MapController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Show a cluster pin or a normal pin
if let annotation = annotation as? ClusterAnnotation {
let reuseIdentifier = "PartnerClusterAnnotationView"
let view = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
?? ClusterAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier, type: .color(.mainTintNormal, radius: 30))
view.annotation = annotation
return view
} else if let annotation = annotation as? PartnerAnnotation {
let view = UINib.partnerAnnotationView.instantiate(withOwner: self, options: nil).first as! PartnerAnnotationView
view.annotation = annotation
view.configure(with: annotation.partner)
return view
} else {
return nil
}
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
/* random things */
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
/* random things */
}
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
self.clusterManager.reload(self.mapView, visibleMapRect: self.mapView.visibleMapRect)
}
}
// MARK: - Navigation
extension MapController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
/* random things */
}
}
Do you have any idea on what happens?
Thanks you very much!
Thomas
When I choose ClusterAnnotationType.color clusterview shows annotation count but When I choose ClusterAnnotationType.image annotatation count is not shows.
There is a way show count without change library codes?
Thanks
I try latest release 2.0.1 and the cluster goes crazy. When I zoom on the map, it does not stop changing its position.
Help, please.
It would be very useful to have an additional API
method for removing a single annotation
. Right now there is a single method called removeAll()
, but I suggest to add a new method with the following signature: remove(_ annotation: MKAnnotation)
.
It would complement the existing API
similar to the one used in MKMapView
(mapView.remove(annotation)
).
Thank you!
I am loading Mapview with geojson data. It contains 7000 data in that geojson file. Even I loaded that data into Mapview. Its loaded fine, but, the problem is mapview getting freezing/stucking for few seconds while zoomin/zoomou So, its getting very bad user experience.
Even, I loaded the data in background thread, still mapview getting freeze.
After I read few forums, we can load clusters to avoid this kind freeze UI issue for mapview, but, I did not found for geojson data loading with clusters and for MKpolylines. I am showing in my mapview Polylines and Annoations by loading 2 geojson files to MKMapview.
Anyone can suggest me, how to show clusters for MKPolylines and Annotations by loading with geojson files.
Threading should be handled by the user instead of this library. It would remove the need for completion blocks. Could add an option for asynchronous operation.
annotation.canShowCallout = true
annotation.rightCalloutAccessoryView = UIButton
Doesn't seem to work.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.