From 68e00bf2e067f65059e7e053d12a4fb78bb99272 Mon Sep 17 00:00:00 2001 From: BucekJiri Date: Mon, 4 Jul 2022 14:56:39 +0200 Subject: [PATCH 1/4] Region updates immprovements --- .../_CustomAnnotatedMapContent.swift | 59 +++++++++++-------- .../_CustomAnnotatedMapCoordinator.swift | 29 ++++----- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift index e9dcd8a..6783415 100644 --- a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift +++ b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift @@ -108,17 +108,8 @@ where updateAnnotationsIfNeeded(on: mapView, with: context.coordinator) - if mapView.showsUserLocation != self.showsUserLocation { - mapView.showsUserLocation = self.showsUserLocation - } - - if let userTrackingMode = MKUserTrackingMode(rawValue: self.userTrackingMode.rawValue), - mapView.userTrackingMode != userTrackingMode - { - performWithoutLocationUpdates(on: context.coordinator) { - mapView.setUserTrackingMode(userTrackingMode, animated: true) - } - } + updateUserTrackingMode(on: mapView, + with: context.coordinator) // Update the map region either using the coordinateRegion or MapRect if let coordinateRegion = self.coordinateRegion { @@ -134,6 +125,24 @@ where } } + /// Updates the user tracking mode when it is different than the currently set mode + /// - Parameters: + /// - mapView: The MKMapView associated with this UIViewRepresentable + /// - coordinator: The associated coordinator object + private func updateUserTrackingMode(on mapView: MKMapView, with coordinator: Coordinator) { + DispatchQueue.main.async { + if mapView.showsUserLocation != self.showsUserLocation { + mapView.showsUserLocation = self.showsUserLocation + } + + if let userTrackingMode = MKUserTrackingMode(rawValue: self.userTrackingMode.rawValue), + mapView.userTrackingMode != userTrackingMode + { + mapView.setUserTrackingMode(userTrackingMode, animated: true) + } + } + } + /// Checks if the current annotations reflect the annotations displayed in the map and updates accordingly /// - Parameters: @@ -163,25 +172,27 @@ where private func updateRegion(_ coordinateRegion: CoordinateRegion, on mapView: UIViewType, with coordinator: Coordinator) { // Prevents repetitive calls to MKMapView.setRegion when other parts of the view are updated that are not // related to the map region - guard !coordinateRegion.mapRect.isSame(as: coordinator.lastMapRect) else { + DispatchQueue.main.async { + guard !coordinateRegion.mapRect.isSame(as: coordinator.lastMapRect), + !coordinator.regionIsChanging + else { return } - - performWithoutLocationUpdates(on: coordinator) { - mapView.setRegion(coordinateRegion.rawValue, animated: true) - } + + mapView.setRegion(coordinateRegion.rawValue, animated: true) + } } /// Pauses the location updates on the coordinator while performing a task /// - Parameters: /// - coordinator: The associated Coordinator object /// - task: The task to be performed - private func performWithoutLocationUpdates(on coordinator: _CustomAnnotatedMapCoordinator, task: () -> Void) { - defer { - coordinator.listenToLocationChanges = true - } - - coordinator.listenToLocationChanges = false - task() - } +// private func performWithoutLocationUpdates(on coordinator: _CustomAnnotatedMapCoordinator, task: () -> Void) { +// defer { +// coordinator.listenToLocationChanges = true +// } +// +// coordinator.listenToLocationChanges = false +// task() +// } } diff --git a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift index c911889..9f4d134 100644 --- a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift +++ b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift @@ -6,8 +6,8 @@ extension _CustomAnnotatedMapContent { public class _CustomAnnotatedMapCoordinator: NSObject, MKMapViewDelegate { private var mapContent: _CustomAnnotatedMapContent - /// Determines if changes in map region are updated to the mapContent view - var listenToLocationChanges = false + /// Determines if the map region is currently being changed with animation (the map is sliding to a new region) + var regionIsChanging = false /// The latest map region that got updated to the mapContent view var lastMapRect: MapRect? @@ -19,22 +19,23 @@ extension _CustomAnnotatedMapContent { self.mapContent = mapContent super.init() } - - public func mapView( - _ mapView: MKMapView, - regionDidChangeAnimated animated: Bool - ) { - /* - Only update the map region changes to the mapContent if allowed. - This prevents updates during the manual changes to the map region and user tracking mode - which are animated and would be interrupted. - */ - guard listenToLocationChanges else { return } - + + /// This delegate method gets called multiple times during the animation of the region change + public func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) { self.mapContent.coordinateRegion = CoordinateRegion(rawValue: mapView.region) self.mapContent.mapRect = MapRect.init(rawValue: mapView.visibleMapRect) self.lastMapRect = MapRect.init(rawValue: mapView.visibleMapRect) } + + /// The map view is about to change the visible map region + public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) { + regionIsChanging = true + } + + /// The map view finished changing the visible map region + public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { + regionIsChanging = false + } public func mapView( _ mapView: MKMapView, From 6e24fb418c86b27cb08ca0f86f70a32b745b492d Mon Sep 17 00:00:00 2001 From: BucekJiri Date: Thu, 28 Jul 2022 11:19:47 +0200 Subject: [PATCH 2/4] Comment remove --- .../_CustomAnnotatedMapContent.swift | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift index 6783415..35a1bbe 100644 --- a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift +++ b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift @@ -182,17 +182,4 @@ where mapView.setRegion(coordinateRegion.rawValue, animated: true) } } - - /// Pauses the location updates on the coordinator while performing a task - /// - Parameters: - /// - coordinator: The associated Coordinator object - /// - task: The task to be performed -// private func performWithoutLocationUpdates(on coordinator: _CustomAnnotatedMapCoordinator, task: () -> Void) { -// defer { -// coordinator.listenToLocationChanges = true -// } -// -// coordinator.listenToLocationChanges = false -// task() -// } } From d3073ab830eb514bc8843e913ce8264c372b3838 Mon Sep 17 00:00:00 2001 From: BucekJiri Date: Thu, 28 Jul 2022 13:24:04 +0200 Subject: [PATCH 3/4] Region transition improvements --- .../CustomAnnotatedMap/Helpers/MapKit.swift | 24 +++++++++++++++++++ .../_CustomAnnotatedMapContent.swift | 9 ++++--- .../_CustomAnnotatedMapCoordinator.swift | 6 +---- 3 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 Sources/CustomAnnotatedMap/Helpers/MapKit.swift diff --git a/Sources/CustomAnnotatedMap/Helpers/MapKit.swift b/Sources/CustomAnnotatedMap/Helpers/MapKit.swift new file mode 100644 index 0000000..eb84c16 --- /dev/null +++ b/Sources/CustomAnnotatedMap/Helpers/MapKit.swift @@ -0,0 +1,24 @@ +// +// File.swift +// +// +// Created by Jiří Buček on 28.07.2022. +// + +import Foundation +import MapKit + +extension MKCoordinateRegion { + func equals(to other: MKCoordinateRegion) -> Bool { + center.equals(to: other.center) + && span.equals(to: other.span) + } +} + +extension CLLocationCoordinate2D { + func equals(to other: CLLocationCoordinate2D) -> Bool { + latitude == other.latitude + && longitude == other.longitude + } +} + diff --git a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift index 35a1bbe..f09c1fd 100644 --- a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift +++ b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapContent.swift @@ -169,16 +169,15 @@ where /// - coordinateRegion: The region the map will be moved to /// - mapView: The MKMapView associated with this UIViewRepresentable /// - coordinator: The associated coordinator object - private func updateRegion(_ coordinateRegion: CoordinateRegion, on mapView: UIViewType, with coordinator: Coordinator) { - // Prevents repetitive calls to MKMapView.setRegion when other parts of the view are updated that are not - // related to the map region + private func updateRegion(_ coordinateRegion: CoordinateRegion, + on mapView: UIViewType, + with coordinator: Coordinator) { DispatchQueue.main.async { - guard !coordinateRegion.mapRect.isSame(as: coordinator.lastMapRect), + guard !coordinateRegion.rawValue.equals(to: mapView.region), !coordinator.regionIsChanging else { return } - mapView.setRegion(coordinateRegion.rawValue, animated: true) } } diff --git a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift index 9f4d134..8193b66 100644 --- a/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift +++ b/Sources/CustomAnnotatedMap/_CustomAnnotatedMapCoordinator.swift @@ -9,9 +9,6 @@ extension _CustomAnnotatedMapContent { /// Determines if the map region is currently being changed with animation (the map is sliding to a new region) var regionIsChanging = false - /// The latest map region that got updated to the mapContent view - var lastMapRect: MapRect? - /// The IDs of the annotations currently displayed in the mapContent view var displayedAnnotationsIDs: Set = [] @@ -20,11 +17,10 @@ extension _CustomAnnotatedMapContent { super.init() } - /// This delegate method gets called multiple times during the animation of the region change + /// Called multiple times when the map region change animation is taking place public func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) { self.mapContent.coordinateRegion = CoordinateRegion(rawValue: mapView.region) self.mapContent.mapRect = MapRect.init(rawValue: mapView.visibleMapRect) - self.lastMapRect = MapRect.init(rawValue: mapView.visibleMapRect) } /// The map view is about to change the visible map region From e83a4e7c5c027625d73b095975f2b92e51052612 Mon Sep 17 00:00:00 2001 From: BucekJiri Date: Thu, 28 Jul 2022 13:59:42 +0200 Subject: [PATCH 4/4] Helpers --- .../CustomAnnotatedMap/Helpers/MapKit.swift | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Sources/CustomAnnotatedMap/Helpers/MapKit.swift b/Sources/CustomAnnotatedMap/Helpers/MapKit.swift index eb84c16..f785b95 100644 --- a/Sources/CustomAnnotatedMap/Helpers/MapKit.swift +++ b/Sources/CustomAnnotatedMap/Helpers/MapKit.swift @@ -1,6 +1,6 @@ // -// File.swift -// +// MapKit.swift +// // // Created by Jiří Buček on 28.07.2022. // @@ -8,17 +8,29 @@ import Foundation import MapKit +extension CLLocationCoordinate2D { + + func equals(to other: CLLocationCoordinate2D) -> Bool { + latitude == other.latitude + && longitude == other.longitude + } + +} + extension MKCoordinateRegion { + func equals(to other: MKCoordinateRegion) -> Bool { center.equals(to: other.center) && span.equals(to: other.span) } + } -extension CLLocationCoordinate2D { - func equals(to other: CLLocationCoordinate2D) -> Bool { - latitude == other.latitude - && longitude == other.longitude +extension MKCoordinateSpan { + + func equals(to other: MKCoordinateSpan) -> Bool { + latitudeDelta == other.latitudeDelta + && longitudeDelta == other.longitudeDelta } -} +}