vospennikov / ClusterMap

High performance map annotation clustering
MIT License
70 stars 12 forks source link

Clustering working only on preview mode #10

Open thomascailhol opened 3 months ago

thomascailhol commented 3 months ago

Hello there,

I'm trying to clusterize a bunch of annotations to display marine buoys on a map. Everything seems to work fine on the preview canvas but when running on a device or simulator it looks like the differences arrays are empty.

Hope you can help, I'll try to share a max of code but do not hesitate if you need more info.

Here is my integration:

struct BuoyAnnotationItem: CoordinateIdentifiable, Identifiable, Hashable {
    let id: Int
    var coordinate: CLLocationCoordinate2D
    var name: String
    var height: Double
}

struct BuoyClusterAnnotation: Identifiable {
    var id = UUID()
    var coordinate: CLLocationCoordinate2D
    var count: Int
}
let clusterManager = ClusterManager<BuoyAnnotationItem>()
@State private var mapSize: CGSize = .zero
@State private var annotations: [BuoyAnnotationItem] = []
@State private var clusters: [BuoyClusterAnnotation] = []
@State private var region = MKCoordinateRegion(
    center: CLLocationCoordinate2D(latitude: 46.2276, longitude: 2.2137),
    span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10)
)
    private var buoyAnnotations: [BuoyAnnotationItem] {
        viewModel.buoys.map {
            BuoyAnnotationItem(
                id: $0.id,
                coordinate: CLLocationCoordinate2D(
                    latitude: Double($0.lat) ?? 0.0, // Convert here
                    longitude: Double($0.lng) ?? 0.0 // Convert here
                ),
                name: $0.name,
                height: $0.lastReading.significantHeight
            )
        }
    }
    private func applyChanges(_ difference: ClusterManager<BuoyAnnotationItem>.Difference) {
        print("APPLYING CHANGES")
        for removal in difference.removals {
            print("REMOVAL")
            switch removal {
            case .annotation(let annotation):
                annotations.removeAll { $0 == annotation }
            case .cluster(let clusterAnnotation):
                clusters.removeAll { $0.id == clusterAnnotation.id }
            }
        }
        for insertion in difference.insertions {
            switch insertion {
            case .annotation(let newItem):
                print("INSERT ANNOTATION")
                annotations.append(newItem)
            case .cluster(let newItem):
                print("INSERT CLUSTER")
                clusters.append(BuoyClusterAnnotation(
                    id: newItem.id,
                    coordinate: newItem.coordinate,
                    count: newItem.memberAnnotations.count
                ))
            }
        }
    }

    func reloadAnnotations() async {
        print("Reloading annotations with region: \(region) and mapSize: \(mapSize)")
        let difference = await clusterManager.reload(mapViewSize: mapSize, coordinateRegion: region)
        print("Difference: \(difference)")
        applyChanges(difference)
    }
if #available(iOS 17.0, *) {
    Map(
        initialPosition: .region(region),
        interactionModes: .all
    ) {
        // Annotations
        ForEach(annotations) { item in
            Marker(
                "\(item.name)",
                systemImage: "mappin",
                coordinate: item.coordinate
            )
        }
        // Clusters
        ForEach(clusters) { cluster in
            Marker(
                "\(cluster.count)",
                systemImage: "square.3.layers.3d",
                coordinate: cluster.coordinate
            )
        }
    }
    .readSize(onChange: { newValue in
        mapSize = newValue
    })
    .onMapCameraChange { context in
        region = context.region
    }
    .onMapCameraChange(frequency: .onEnd) { context in
        Task {
            await reloadAnnotations()
        }
    }
    .edgesIgnoringSafeArea(.all)
    .colorScheme(.dark)
  }
thomascailhol commented 3 months ago

I managed to improve some stuff but now on the device the first time I launch the map I see annotations/clusters but when moving nothing happens but when I press back and come back to the map everything works fine šŸ¤”

Here are some print statements:

First load:

fetchData: Data fetch complete
BUOYS COUNT: 81
Annotations onAppear: 81
Camera change update region to:  43.36285018920898, -1.8889000415802
Annotations onMapCameraChange: 0
Camera change update region to:  43.362850189208984, -1.8889000415801414
Annotations onMapCameraChange: 0
Camera change update region to:  43.362850189208984, -1.8889000415801414
Annotations onMapCameraChange: 0
Camera change update region to:  43.362850189208984, -1.8889000415801414
Annotations onMapCameraChange: 12
Camera change update region to:  43.46831427255401, -1.864360783462244
Annotations onMapCameraChange: 12

Second load:

fetchData: Data fetch complete
BUOYS COUNT: 81
Annotations onAppear: 81
Camera change update region to:  43.36285018920898, -1.8889000415802
Annotations onMapCameraChange: 0
Camera change update region to:  43.362850189208984, -1.8889000415801414
Annotations onMapCameraChange: 0
Camera change update region to:  43.362850189208984, -1.8889000415801414
Annotations onMapCameraChange: 0
Camera change update region to:  43.362850189208984, -1.8889000415801414
Annotations onMapCameraChange: 12
Camera change update region to:  43.44456374750019, -1.864360783462244
Annotations onMapCameraChange: 3

See how Annotations onMapCameraChange: x stays at 12 on first load (which reflect on the map not updating)