Skip to content

Commit

Permalink
Add support concurrency
Browse files Browse the repository at this point in the history
  • Loading branch information
vospennikov committed Oct 28, 2023
1 parent e5de4f6 commit d861f02
Show file tree
Hide file tree
Showing 22 changed files with 598 additions and 401 deletions.
12 changes: 9 additions & 3 deletions Example/Example-AppKit/App/Map/MapViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,16 @@ private extension MapViewController {
}

func removeActionHandler(_ sender: NSButton) {
clusterManager.removeAll()
Task { await reloadMap() }
Task {
await clusterManager.removeAll()
await reloadMap()
}
}
}

extension MapViewController {
func addAnnotations(_ coordinates: [CLLocationCoordinate2D]) async {
clusterManager.add(coordinates.map {
await clusterManager.add(coordinates.map {
let point = PointAnnotation()
point.coordinate = $0
return point
Expand All @@ -130,6 +132,8 @@ extension MapViewController {
annotations.remove(at: result.offset)
mapView.removeAnnotation(result.element)
}
@unknown default:
fatalError()
}
}
for annotationType in difference.insertions {
Expand All @@ -144,6 +148,8 @@ extension MapViewController {
cluster.memberAnnotations = clusterAnnotation.memberAnnotations
annotations.append(cluster)
mapView.addAnnotation(cluster)
@unknown default:
fatalError()
}
}
}
Expand Down
40 changes: 40 additions & 0 deletions Example/Example-SwiftUI/App/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// ContentView.swift
// Example-SwiftUI
//
// Created by Mikhail Vospennikov on 21.10.2023.
//

import SwiftUI

struct ContentView: View {
var body: some View {
NavigationView(content: {
Form(content: {
Section {
NavigationLink(
destination: { LazyView(LegacyMap()) },
label: { Text("Map before iOS 17") }
)
}

if #available(iOS 17.0, *) {
Section {
NavigationLink(
destination: { LazyView(ModernMap()) },
label: { Text("Map since iOS 17") }
)
NavigationLink(
destination: { LazyView(MapKitIntegration()) },
label: { Text("Map with MKLocalSearchCompleter") }
)
}
}
})
})
}
}

#Preview {
ContentView()
}
2 changes: 1 addition & 1 deletion Example/Example-SwiftUI/App/ExampleApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import SwiftUI
struct ExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView(dataSource: ContentView.DataSource())
ContentView()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//
// ContentView+DataSource.swift
// LegacyMap+DataSource.swift
// Example-SwiftUI
//
// Created by Mikhail Vospennikov on 01.08.2023.
// Created by Mikhail Vospennikov on 21.10.2023.
//

import ClusterMap
Expand All @@ -12,8 +12,8 @@ import Foundation
import MapKit
import SwiftUI

extension ContentView.DataSource {
struct MapAnnotation: Identifiable, CoordinateIdentifiable, Hashable {
extension LegacyMap {
struct Annotation: Identifiable, CoordinateIdentifiable, Hashable {
enum Style: Hashable {
case single
case cluster(count: Int)
Expand All @@ -23,31 +23,25 @@ extension ContentView.DataSource {
var coordinate: CLLocationCoordinate2D
var style: Style = .single
}
}

extension ContentView {
final class DataSource: ObservableObject {
private let coordinateRandomizer = CoordinateRandomizer()
private let clusterManager = ClusterManager<MapAnnotation>()
private let clusterManager = ClusterManager<Annotation>()
private var cancellables = Set<AnyCancellable>()
private var _region: MKCoordinateRegion

@Published var annotations: [MapAnnotation] = []
@Published var annotations: [Annotation] = []

var mapSize: CGSize = .zero
let initialPosition: MKCoordinateRegion = .sanFrancisco
var regionSubject = PassthroughSubject<MKCoordinateRegion, Never>()

private var _region: MKCoordinateRegion = .sanFrancisco
var region: Binding<MKCoordinateRegion> {
Binding(
get: { self._region },
set: { newValue in self.regionSubject.send(newValue) }
)
}

init() {
_region = initialPosition
}

func bind() {
regionSubject
.debounce(for: .seconds(0.3), scheduler: DispatchQueue.main)
Expand All @@ -60,14 +54,14 @@ extension ContentView {

func addAnnotations() async {
let points = coordinateRandomizer.generateRandomCoordinates(count: 10000, within: _region)
let newAnnotations = points.map { MapAnnotation(coordinate: $0) }
let newAnnotations = points.map { Annotation(coordinate: $0) }

clusterManager.add(newAnnotations)
await clusterManager.add(newAnnotations)
await reloadAnnotations()
}

func removeAnnotations() async {
clusterManager.removeAll()
await clusterManager.removeAll()
await reloadAnnotations()
}

Expand All @@ -77,13 +71,15 @@ extension ContentView {
}

@MainActor
private func applyChanges(_ difference: ClusterManager<MapAnnotation>.Difference) {
private func applyChanges(_ difference: ClusterManager<Annotation>.Difference) {
for removal in difference.removals {
switch removal {
case .annotation(let annotation):
annotations.removeAll { $0 == annotation }
case .cluster(let clusterAnnotation):
annotations.removeAll { $0.id == clusterAnnotation.id }
@unknown default:
fatalError()
}
}

Expand All @@ -92,11 +88,13 @@ extension ContentView {
case .annotation(let newItem):
annotations.append(newItem)
case .cluster(let newItem):
annotations.append(MapAnnotation(
annotations.append(Annotation(
id: newItem.id,
coordinate: newItem.coordinate,
style: .cluster(count: newItem.memberAnnotations.count)
))
@unknown default:
fatalError()
}
}
}
Expand Down
81 changes: 81 additions & 0 deletions Example/Example-SwiftUI/App/LegacyMap/LegacyMap.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// LegacyMap.swift
// Example-SwiftUI
//
// Created by Mikhail Vospennikov on 21.10.2023.
//

import ClusterMap
import ClusterMapSwiftUI
import MapKit
import SwiftUI

struct LegacyMap: View {
@StateObject private var dataSource = DataSource()

var body: some View {
Map(
coordinateRegion: dataSource.region,
interactionModes: .all,
annotationItems: dataSource.annotations,
annotationContent: mapItem(for:)
)
.ignoresSafeArea()
.readSize(onChange: { newValue in
dataSource.mapSize = newValue
})
.overlay(alignment: .bottom) {
HStack {
AsyncButton("Add annotations") {
await dataSource.addAnnotations()
}
Spacer()
AsyncButton("Remove annotations") {
await dataSource.removeAnnotations()
}
}
.padding()
.buttonStyle(RoundedButton(fillColor: .accentColor, padding: 8))
}
.onAppear {
dataSource.bind()
}
}

private func mapItem(for annotation: Annotation) -> some MapAnnotationProtocol {
switch annotation.style {
case .single:
AnyMapAnnotationProtocol(
MapPin(coordinate: annotation.coordinate)
)
case .cluster(let count):
AnyMapAnnotationProtocol(MapAnnotation(coordinate: annotation.coordinate) {
VStack(spacing: 0) {
Image(systemName: "mappin.circle.fill")
.font(.title)
.foregroundColor(.red)

Image(systemName: "arrowtriangle.down.fill")
.font(.caption)
.foregroundColor(.red)
.offset(x: 0, y: -5)

Text("\(count)")
.font(.footnote)
.foregroundColor(.black)
.padding(4)
.background {
RoundedRectangle(cornerRadius: 4.0, style: .continuous)
.foregroundColor(.white)
}
}
})
}
}
}

struct LegacyMap_Previews: PreviewProvider {
static var previews: some View {
LegacyMap()
}
}

This file was deleted.

Loading

0 comments on commit d861f02

Please sign in to comment.