I am currently working on adding cluster annotations to my map view. Everything works fine except for a few things. First of all, I need to update the annotations on the map when the user leaves and returns to the view. At the moment, such works ... The problem is that instead of removing annotations and adding new ones, new ones are added in addition to the old ones, so they are multiplied every time.
The next problem is that each annotation shows the distance the user is from this annotation, however the annotations are configured before the user's location is found. I assume that I just need to remove and replace annotations after locating the location, but then again I ran into the problem of duplicate comments.
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 apologize for the large amount of code, but all this should have been included.
Does anyone have any suggestions on how I can remove annotations and re-add them after the view appears?
Thanks!
EDIT:
The second problem is now resolved. The following is more detailed information about the situation and problems:
Basically, each annotation is a trip to a theme park and displays the name of the trip, the current waiting time, and the distance to this trip. Currently, when I find setUpMapView() when the view appears, all ride annotations are added to qTree every time, but not deleted. This is a problem that I am trying to solve, but I cannot find a way to remove them from qTree.