vospennikov / ClusterMap

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

Update fails sometimes after map swipe #5

Open LaborEtArs opened 9 months ago

LaborEtArs commented 9 months ago

When swiping the map and lifting the finger while the map moves on (in order to move a large distance), the update process often fails and no more annotations are visible in the newly shown area of the map.

I am using a nearly 1:1 copy of your 'Example-SwiftUI' code and while debugging the problem I found, that when adding 'print()' commands in the 'func reloadAnnotations()' code, the problem disappears.

As 'print()' would not be a good solution in productive code, I replaced it by an empty call to the main thread: func reloadAnnotations() async { await MainActor.run{} // WORKAROUND: Show annotations after long swipe async let changes = clusterManager.reload(mapViewSize: mapSize, coordinateRegion: currentRegion) await applyChanges(changes) }

I am not sure, if the reason, this helps, is the call to the main thread, or if it it is just some sore of timing problem.

hthao commented 5 months ago

When swiping the map and lifting the finger while the map moves on (in order to move a large distance), the update process often fails and no more annotations are visible in the newly shown area of the map.

I am using a nearly 1:1 copy of your 'Example-SwiftUI' code and while debugging the problem I found, that when adding 'print()' commands in the 'func reloadAnnotations()' code, the problem disappears.

As 'print()' would not be a good solution in productive code, I replaced it by an empty call to the main thread:

`func reloadAnnotations() async {

      await MainActor.run{}   // WORKAROUND: Show annotations after long swipe

      async let changes = clusterManager.reload(mapViewSize: mapSize, coordinateRegion: currentRegion)

      await applyChanges(changes)

  }`

I am not sure, if the reason, this helps, is the call to the main thread, or if it it is just some sore of timing problem.

I met the same problem. the workaround helps, but sometimes the cluster is not updated too when zooming out.

hthao commented 5 months ago

in the example Example-SwiftUI, the problem can be fixed by making datasource reload annotations for both mapSize & Camera changes.

Map(
            initialPosition: .region(dataSource.currentRegion),
            interactionModes: .all
        ) {
            ForEach(dataSource.annotations) { item in
                Marker(
                    "\(item.coordinate.latitude) \(item.coordinate.longitude)",
                    systemImage: "mappin",
                    coordinate: item.coordinate
                )
                .annotationTitles(.hidden)
            }
            ForEach(dataSource.clusters) { item in
                Marker(
                    "\(item.count)",
                    systemImage: "square.3.layers.3d",
                    coordinate: item.coordinate
                )
            }
        }
        .readSize(onChange: { newValue in
            dataSource.mapSize = newValue
            Task.detached { await dataSource.reloadAnnotations() } // reload here.
        })
        .onMapCameraChange { context in
            dataSource.currentRegion = context.region
            Task.detached { await dataSource.reloadAnnotations() } // reload here.
        }
        .onMapCameraChange(frequency: .onEnd) { context in
            Task.detached { await dataSource.reloadAnnotations() }
        }
        .overlay(alignment: .bottom, content: {
            HStack {
                AsyncButton("Add annotations") {
                    await dataSource.addAnnotations()
                }
                Spacer()
                AsyncButton("Remove annotations") {
                    await dataSource.removeAnnotations()
                }
            }
            .padding()
            .buttonStyle(RoundedButton(fillColor: .accentColor, padding: 8))
        })