Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions MAGE.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@
313FA0702E130399008DA52E /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 313FA06F2E130399008DA52E /* Date.swift */; };
314737AB2EC6323D002A8DD0 /* DisclaimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314737AA2EC63236002A8DD0 /* DisclaimerView.swift */; };
315336192EB5322300DAAC0C /* MainFilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315336182EB5322300DAAC0C /* MainFilterViewModel.swift */; };
31B73F352F630B3800FBEF35 /* ObservationImportProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B73F342F630B3800FBEF35 /* ObservationImportProgress.swift */; };
31B73F6D2F6C3E1300FBEF35 /* MapFeatureUpdateProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B73F6C2F6C3E1300FBEF35 /* MapFeatureUpdateProgress.swift */; };
31EA7F152F463ED3009C9FA7 /* ExpandingTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31EA7F142F463ED3009C9FA7 /* ExpandingTextEditor.swift */; };
4C390F4A197DB7B000AB3CCB /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C390F49197DB7B000AB3CCB /* MessageUI.framework */; };
4C546FEC195A27F4000CF230 /* LocationAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C546FEB195A27F4000CF230 /* LocationAnnotation.m */; };
Expand Down Expand Up @@ -1114,6 +1116,8 @@
313FA06F2E130399008DA52E /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
314737AA2EC63236002A8DD0 /* DisclaimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisclaimerView.swift; sourceTree = "<group>"; };
315336182EB5322300DAAC0C /* MainFilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFilterViewModel.swift; sourceTree = "<group>"; };
31B73F342F630B3800FBEF35 /* ObservationImportProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservationImportProgress.swift; sourceTree = "<group>"; };
31B73F6C2F6C3E1300FBEF35 /* MapFeatureUpdateProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapFeatureUpdateProgress.swift; sourceTree = "<group>"; };
31EA7F142F463ED3009C9FA7 /* ExpandingTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpandingTextEditor.swift; sourceTree = "<group>"; };
3B266AC5426B836F21B34375 /* Pods-MAGETests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MAGETests.release.xcconfig"; path = "Pods/Target Support Files/Pods-MAGETests/Pods-MAGETests.release.xcconfig"; sourceTree = "<group>"; };
4C390F49197DB7B000AB3CCB /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -2413,6 +2417,7 @@
F78D579927BDA951003594D3 /* SingleFeatureMapView.swift */,
F734C1E42BC845BE00B2E8C8 /* CoordinateDisplayType.swift */,
F744ACFC2BFE73A900A6E4CA /* DataSourceMapViewModel.swift */,
31B73F6C2F6C3E1300FBEF35 /* MapFeatureUpdateProgress.swift */,
);
name = Map;
sourceTree = "<group>";
Expand Down Expand Up @@ -2643,6 +2648,7 @@
F7A82D5C2051C2560080A4E3 /* ObservationTableHeaderView.m */,
311C6FB82F2A646C00298067 /* ObservationTableHeaderViewSwift.swift */,
F75DD30D1A97AABD0007FA3F /* View */,
31B73F342F630B3800FBEF35 /* ObservationImportProgress.swift */,
);
name = Observation;
sourceTree = "<group>";
Expand Down Expand Up @@ -4935,6 +4941,7 @@
2F9F43AB1CE5050400D99AAF /* UINavigationItem+Subtitle.m in Sources */,
F7DBBAF523D8B7050052D86C /* ObservationServicesSettingsTableViewController.m in Sources */,
F721B3661913E61B00F1CAB4 /* ValuePickerTableViewController.m in Sources */,
31B73F6D2F6C3E1300FBEF35 /* MapFeatureUpdateProgress.swift in Sources */,
D2A46FF92E0DD73700CE0D72 /* ObservationChangeRegions.swift in Sources */,
F7C097732C80C52C003FA115 /* AttachmentModel.swift in Sources */,
F781609E273EE1A50055B5D2 /* ObjC.m in Sources */,
Expand Down Expand Up @@ -5002,6 +5009,7 @@
F72D430A2694B60300F9AC3B /* Model8To15.xcmappingmodel in Sources */,
F7402C8A276D1A9B00531613 /* HasMapSettings.swift in Sources */,
8474FD9A26FB8B890041891A /* LinkGenerator.m in Sources */,
31B73F352F630B3800FBEF35 /* ObservationImportProgress.swift in Sources */,
F7CDD71D260138E800F3294C /* MockMKMapViewDelegate.swift in Sources */,
2F42586F2B51F05B00BF83B1 /* Settings.swift in Sources */,
F72D431F2694B60300F9AC3B /* Model14To16.xcmappingmodel in Sources */,
Expand Down
28 changes: 25 additions & 3 deletions Mage/CoreData/Observation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ enum ObservationState: Int, CustomStringConvertible {
}
}

func createObservationLocations(context: NSManagedObjectContext) {
func createObservationLocations(context: NSManagedObjectContext, formCache: ObservationFormCache? = nil) {
var order: Int64 = 0
var observationLocations: Set<ObservationLocation> = Set<ObservationLocation>()
// save the observations location
Expand All @@ -1055,7 +1055,7 @@ enum ObservationState: Int, CustomStringConvertible {
observationLocation.fieldName = Observation.PRIMARY_OBSERVATION_GEOMETRY
observationLocation.formId = (primaryObservationForm?[EventKey.formId.key] as? NSNumber)?.int64Value ?? -1

let eventForm = Form.mr_findFirst(
let eventForm = formCache?.form(for: observationLocation.formId, in: context) ?? Form.mr_findFirst(
byAttribute: "formId",
withValue: observationLocation.formId,
in: context
Expand Down Expand Up @@ -1113,7 +1113,7 @@ enum ObservationState: Int, CustomStringConvertible {
observationLocation.formId = eventFormId.int64Value
observationLocation.observationFormId = form[FormKey.id.key] as? String

let eventForm = Form.mr_findFirst(
let eventForm = formCache?.form(for: observationLocation.formId, in: context) ?? Form.mr_findFirst(
byAttribute: "formId",
withValue: observationLocation.formId,
in: context
Expand Down Expand Up @@ -1144,3 +1144,25 @@ enum ObservationState: Int, CustomStringConvertible {
self.locations = observationLocations
}
}

final class ObservationFormCache {
private var formsById: [Int64: Form] = [:]

func form(for formId: Int64, in context: NSManagedObjectContext) -> Form? {
if let cachedForm = formsById[formId] {
return cachedForm
}

guard let fetchedForm = Form.mr_findFirst(
byAttribute: "formId",
withValue: NSNumber(value: formId),
in: context
) else {
return nil
}

formsById[formId] = fetchedForm
return fetchedForm
}
}

53 changes: 31 additions & 22 deletions Mage/DataSourceMapViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class DataSourceMapViewModel {
@Published var annotations: [DataSourceAnnotation] = []
@Published var featureOverlays: [MKOverlay] = []

private var lastAnnotationKeys: Set<String> = []
private var lastOverlayKeys: Set<String> = []

let requerySubject = PassthroughSubject<Void, Never>()

init(
Expand All @@ -58,21 +61,21 @@ class DataSourceMapViewModel {
}
}
.store(in: &cancellable)

mapStateRepository.$zoom
.receive(on: DispatchQueue.main)
.sink { [weak self] zoom in
self?.requerySubject.send(())
}
.store(in: &cancellable)

mapStateRepository.$region
.receive(on: DispatchQueue.main)
.sink { [weak self] region in
self?.requerySubject.send(())
}
.store(in: &cancellable)

//
// mapStateRepository.$zoom
// .receive(on: DispatchQueue.main)
// .sink { [weak self] zoom in
// self?.requerySubject.send(())
// }
// .store(in: &cancellable)
//
// mapStateRepository.$region
// .receive(on: DispatchQueue.main)
// .sink { [weak self] region in
// self?.requerySubject.send(())
// }
// .store(in: &cancellable)
//
repository?.refreshPublisher?
.sink { [weak self] date in
self?.refresh()
Expand All @@ -90,20 +93,26 @@ class DataSourceMapViewModel {
if UserDefaults.standard.hideObservations {
annotations = []
featureOverlays = []
lastAnnotationKeys = []
lastOverlayKeys = []
return
}
let features = await mapFeatureRepository?.getAnnotationsAndOverlays(
zoom: zoom,
region: region.padded(percentage: 2.0)
)
annotations = (features?.annotations ?? []).sorted(by: { first, second in
first.id < second.id
})
let newAnnotations = features?.annotations ?? []
let newAnnotationKeys = Set(newAnnotations.map { $0.key() })
if newAnnotationKeys.count != lastAnnotationKeys.count || newAnnotationKeys != lastAnnotationKeys {
lastAnnotationKeys = newAnnotationKeys
annotations = newAnnotations.sorted(by: { first, second in
first.id < second.id
})
}
if let overlays = features?.overlays {
// Compare by stable identifiers
let newIds = overlays.compactMap { ($0 as? DataSourceIdentifiable)?.id }
let currentIds = featureOverlays.compactMap { ($0 as? DataSourceIdentifiable)?.id }
if newIds != currentIds {
let newOverlayKeys = Set(overlays.compactMap { ($0 as? DataSourceIdentifiable)?.key() })
if newOverlayKeys.count != lastOverlayKeys.count || newOverlayKeys != lastOverlayKeys {
lastOverlayKeys = newOverlayKeys
featureOverlays = overlays
}
}
Expand Down
Loading