I am currently working on adding cluster annotations to my map view. Everything is working fine with the exception of a couple of things. First of all, I need to refresh the annotations on the map when the user leaves and returns to the view. At the moment this sort of works... The problem is that rather than removing the annotations and adding the new ones, the new ones are just being added in addition of the old ones so there are multiplying each time.
The next issue is that each annotation displays the distance the user is from that annotation, however the annotations are set up before the user's location is found. I assume I will just have to remove and replace the annotations once the location is found, but then I run into the issue of the annotations duplicating again.
This is my code:
override func viewDidAppear(animated: Bool) {
println(rideArray.count)
setUpMapView()
}
func setUpMapView() {
rideArray = ((DataManager.sharedInstance.rideArray) as NSArray) as! [Ride]
myLocation = mapView.userLocation.coordinate as CLLocationCoordinate2D
zoomRegion = MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2D(latitude: parkPassed.latitude!, longitude: parkPassed.longitude!), 1000, 1000)
mapView.setRegion(zoomRegion, animated: true)
mapView.delegate = self
for ride in rideArray {
println("Location: \(mapView.userLocation.coordinate.latitude)")
var subtitle = ""
if mapView.userLocation.location == nil {
subtitle = "Distance unavailable"
} else {
let userLocation = CLLocation(latitude: mapView.userLocation.coordinate.latitude, longitude: mapView.userLocation.coordinate.longitude)
let annotationLocation = CLLocation(latitude: ride.latitude!, longitude: ride.longitude!)
var distance = Int(CLLocationDistance(annotationLocation.distanceFromLocation(userLocation)))
if distance > 1000 {
distance = distance / 1000
subtitle = "\(distance) kilometers"
} else {
subtitle = "\(distance) meters"
}
}
let annotation = RideAnnotation(coordinate: CLLocationCoordinate2DMake(ride.latitude!, ride.longitude!), title: ride.name!, subtitle: subtitle)
self.qTree.insertObject(annotation)
}
var leftSwipe = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
var rightSwipe = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
leftSwipe.direction = .Left
rightSwipe.direction = .Right
view.addGestureRecognizer(leftSwipe)
view.addGestureRecognizer(rightSwipe)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation.isKindOfClass(QCluster.classForCoder()) {
let PinIdentifier = "PinIdentifier"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(ClusterAnnotationView.reuseId()) as? ClusterAnnotationView
if annotationView == nil {
annotationView = ClusterAnnotationView(cluster: annotation)
}
annotationView!.cluster = annotation
return annotationView
} else if annotation.isKindOfClass(RideAnnotation.classForCoder()) {
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("RideAnnotation")
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "RideAnnotation")
pinView?.canShowCallout = true
pinView?.rightCalloutAccessoryView = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as! UIButton
pinView?.rightCalloutAccessoryView.tintColor = UIColorFromRGB(0x424242)
let rideTimeView = UIView()
rideTimeView.frame = CGRectMake(5, 5, 50, 50)
rideTimeView.layer.cornerRadius = 25
let waitTimeLabel = UILabel()
waitTimeLabel.frame = CGRectMake(0, 0, 50, 50)
if DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime! == "Closed" {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)"
rideTimeView.backgroundColor = getColorFromNumber(80)
waitTimeLabel.font = UIFont(name: "Avenir", size: 15)
} else {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)m"
rideTimeView.backgroundColor = getColorFromNumber(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!.toInt()!)
waitTimeLabel.font = UIFont(name: "Avenir", size: 20)
}
waitTimeLabel.textAlignment = NSTextAlignment.Center
waitTimeLabel.textColor = UIColor.whiteColor()
waitTimeLabel.adjustsFontSizeToFitWidth = true
waitTimeLabel.numberOfLines = 1
rideTimeView.addSubview(waitTimeLabel)
pinView.leftCalloutAccessoryView = rideTimeView
pinView?.image = UIImage(named: "rideMapAnnotation")
} else {
pinView?.annotation = annotation
let rideTimeView = UIView()
rideTimeView.frame = CGRectMake(5, 5, 50, 50)
rideTimeView.layer.cornerRadius = 25
let waitTimeLabel = UILabel()
waitTimeLabel.frame = CGRectMake(0, 0, 50, 50)
if DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime! == "Closed" {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)"
rideTimeView.backgroundColor = getColorFromNumber(80)
waitTimeLabel.font = UIFont(name: "Avenir", size: 15)
} else {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)m"
rideTimeView.backgroundColor = getColorFromNumber(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!.toInt()!)
waitTimeLabel.font = UIFont(name: "Avenir", size: 20)
}
waitTimeLabel.textAlignment = NSTextAlignment.Center
waitTimeLabel.textColor = UIColor.whiteColor()
waitTimeLabel.adjustsFontSizeToFitWidth = true
waitTimeLabel.numberOfLines = 1
rideTimeView.addSubview(waitTimeLabel)
pinView.leftCalloutAccessoryView = rideTimeView
}
return pinView
}
return nil
}
func reloadAnnotations(){
if self.isViewLoaded() == false {
return
}
self.cacheArray.removeAll(keepCapacity: false)
let mapRegion = self.mapView.region
let minNonClusteredSpan = min(mapRegion.span.latitudeDelta, mapRegion.span.longitudeDelta) / 5
let objects = self.qTree.getObjectsInRegion(mapRegion, minNonClusteredSpan: minNonClusteredSpan) as NSArray
for object in objects {
if object.isKindOfClass(QCluster){
let c = object as? QCluster
let neighbours = self.qTree.neighboursForLocation((c?.coordinate)!, limitCount: NSInteger((c?.objectsCount)!)) as NSArray
for neighbour in neighbours {
let tmp = self.rideArray.filter({
return $0.name == (neighbour.title)!!
})
if find(self.cacheArray, tmp[0]) == nil {
self.cacheArray.insert(tmp[0], atIndex: self.cacheArray.count)
}
}
} else {
let tmp = self.rideArray.filter({
return $0.name == (object.title)!!
})
if find(self.cacheArray, tmp[0]) == nil {
self.cacheArray.insert(tmp[0], atIndex: self.cacheArray.count)
}
}
}
let annotationsToRemove = (self.mapView.annotations as NSArray).mutableCopy() as! NSMutableArray
annotationsToRemove.removeObject(self.mapView.userLocation)
annotationsToRemove.removeObjectsInArray(objects as [AnyObject])
self.mapView.removeAnnotations(annotationsToRemove as [AnyObject])
let annotationsToAdd = objects.mutableCopy() as! NSMutableArray
annotationsToAdd.removeObjectsInArray(self.mapView.annotations)
self.mapView.addAnnotations(annotationsToAdd as [AnyObject])
}
func mapView(mapView: MKMapView!, regionDidChangeAnimated animated: Bool) {
viewChanged = true
self.reloadAnnotations()
}
I apologise for the extensive amount of code, but it all had to be included.
Anyone have any suggestions as to how I can remove the annotations and re-add them once the view appears?
Thanks!
EDIT:
The second issue is now resolved. Here is a bit more detail in regards to the situation and issue:
Basically each annotation represents a ride in a theme park and displays the ride name, current wait time and distance to that ride. At the moment since I am calling setUpMapView()
when the view appears, all of the ride annotations are being added to the qTree each time, but are not being removed. This is the issue that I am trying to resolve, but I can't find a way to remove them from the qTree.
MKMapView has the method removeAnnotation:
, which will remove a single annotation, and removeAnnotations:
which will remove an array of annotations. It also has an annotations
property which lets you the current array of annotations. You should be able to select and remove the annotations that you want to remove and then add new ones to replace them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With