Reputation: 3697
I have done a bit of research but couldn't find anything of value so I thought I would ask here.
I have a mapview with custom annotations. In the callouts I would like to display a count down timer. The initial countdown from time is retrieved from an api. I would like to show the countdown timer when a user taps the map annotation in the callout.
What would be the best way to manage the countdown timers consider each annotation could have a different time?
I realise there would be a performance hit having multiple timers running but at what point is too many timers on a single view controller?
Any guidance is appreciated.
Thanks
Upvotes: 2
Views: 79
Reputation: 93191
You don't need to create multiple NSTimer
. Just needs one running in the background to remind all annotation views to update the remaining time.
First the data model:
class MyAnnotation: NSObject, MKAnnotation {
@objc var coordinate: CLLocationCoordinate2D
@objc var title: String?
@objc var subtitle: String?
@objc var expirationDate: NSDate?
init(coordinate: CLLocationCoordinate2D, title: String?, subtitle: String?, expirationDate: NSDate?) {
self.coordinate = coordinate
self.title = title
self.subtitle = subtitle
self.expirationDate = expirationDate
}
}
And the custom Annotation View & the View Controller :
class MyAnnotationView: MKPinAnnotationView {
static let formatter = { Void -> NSDateComponentsFormatter in
let tmp = NSDateComponentsFormatter()
tmp.allowedUnits = [.Minute, .Second]
return tmp
}()
func updateCountDown() {
guard let annotation = self.annotation as? MyAnnotation,
let expirationDate = annotation.expirationDate else {
return
}
annotation.subtitle = MyAnnotationView.formatter.stringFromDate(NSDate(), toDate: expirationDate)
self.annotation = annotation
}
}
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
var timer: NSTimer!
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
addAnnotations()
self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(ViewController.updateRemainingTime), userInfo: nil, repeats: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func addAnnotations() {
let coordinate1 = CLLocationCoordinate2D(latitude: 37.3316936, longitude: -122.03021910000001)
let coordinate2 = CLLocationCoordinate2D(latitude: 37.4224187, longitude: -122.0843491)
let appleHQ = MyAnnotation(coordinate: coordinate1, title: "Apple HQ", subtitle: "hohoho", expirationDate: NSDate(timeIntervalSinceNow: 240) )
let googleHQ = MyAnnotation(coordinate: coordinate2, title: "Googleplex", subtitle: nil, expirationDate: NSDate(timeIntervalSinceNow: 180))
self.mapView.addAnnotation(appleHQ)
self.mapView.addAnnotation(googleHQ)
self.mapView.centerCoordinate = coordinate1
self.mapView.region.span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
}
func updateRemainingTime() {
for annotation in self.mapView.annotations {
if let view = self.mapView.viewForAnnotation(annotation) as? MyAnnotationView {
view.updateCountDown()
}
}
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier("annotationView")
if annotationView != nil {
annotationView!.annotation = annotation
} else {
annotationView = MyAnnotationView(annotation: annotation, reuseIdentifier: "annotationView")
annotationView!.canShowCallout = true
}
return annotationView
}
}
Upvotes: 2