Make update delay reusable and include call to zoomInOnAll

This commit is contained in:
Milan Stute
2021-03-16 09:38:07 +01:00
parent c7696b6687
commit 0e126e7882
2 changed files with 31 additions and 24 deletions

View File

@@ -17,6 +17,7 @@ struct AccessoryMapView: NSViewControllerRepresentable {
@Binding var focusedAccessory: Accessory?
@Binding var showHistory: Bool
@Binding var showPastHistory: TimeInterval
var delayer = UpdateDelayer()
func makeNSViewController(context: Context) -> MapViewController {
return MapViewController(nibName: NSNib.Name("MapViewController"), bundle: nil)
@@ -27,8 +28,10 @@ struct AccessoryMapView: NSViewControllerRepresentable {
nsViewController.focusedAccessory = focusedAccessory
if showHistory {
nsViewController.addAllLocations(from: focusedAccessory!, past: showPastHistory)
nsViewController.zoomInOnAll()
delayer.delayUpdate {
nsViewController.addAllLocations(from: focusedAccessory!, past: showPastHistory)
nsViewController.zoomInOnAll()
}
} else {
nsViewController.addLastLocations(from: accessories)
nsViewController.zoomInOnSelection()
@@ -36,3 +39,17 @@ struct AccessoryMapView: NSViewControllerRepresentable {
nsViewController.changeMapType(mapType)
}
}
class UpdateDelayer {
/// Some view updates need to be delayed to mitigate UI glitches.
var delayedWorkItem: DispatchWorkItem?
func delayUpdate(delay: Double = 0.3, closure: @escaping () -> Void) {
self.delayedWorkItem?.cancel()
let workItem = DispatchWorkItem {
closure()
}
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem)
self.delayedWorkItem = workItem
}
}

View File

@@ -14,8 +14,6 @@ final class MapViewController: NSViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
var pinsShown = false
var focusedAccessory: Accessory?
/// Some view updates need to be delayed to mitigate ui glitches
var delayedWorkItem: DispatchWorkItem?
override func viewDidLoad() {
super.viewDidLoad()
@@ -64,28 +62,20 @@ final class MapViewController: NSViewController, MKMapViewDelegate {
}
func addAllLocations(from accessory: Accessory, past: TimeInterval) {
//We delay the updates here to make sure that we do not get any race conditions with SwiftUI and our map update cycle that could end up showing the wrong data
self.delayedWorkItem?.cancel()
let workItem = DispatchWorkItem {
let now = Date()
let pastLocations = accessory.locations?.filter { location in
guard let timestamp = location.timestamp else {
return false
}
return timestamp + past >= now
}
self.mapView.removeAnnotations(self.mapView.annotations)
for location in pastLocations ?? [] {
let coordinate = CLLocationCoordinate2DMake(location.latitude, location.longitude)
let annotation = AccessoryHistoryAnnotation(coordinate: coordinate)
self.mapView.addAnnotation(annotation)
let now = Date()
let pastLocations = accessory.locations?.filter { location in
guard let timestamp = location.timestamp else {
return false
}
return timestamp + past >= now
}
self.mapView.removeAnnotations(self.mapView.annotations)
for location in pastLocations ?? [] {
let coordinate = CLLocationCoordinate2DMake(location.latitude, location.longitude)
let annotation = AccessoryHistoryAnnotation(coordinate: coordinate)
self.mapView.addAnnotation(annotation)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: workItem)
self.delayedWorkItem = workItem
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {