maps
maps copied to clipboard
(iOS) v10 - ShapeSource.getClusterExpansionZoom throws error
Describe the bug
The ShapeSource.getClusterExpansionZoom
method throws an error when provided with a Feature
argument:
`JSON value '{...JSON object}' of type NSString cannot be converted to NSNumber
To Reproduce
- Clone the minimal reproduction repo
- Add your Download token to the
app.config.js
file - Add your Access token to the
App.tsx
file - run
expo run:ios
to spin up the application (may need to install Expo if your don't already have it) - Tap on a cluster
Example:
export default function App() {
const sourceRef = useRef<MapboxGL.ShapeSource>(null);
const mapRef = useRef<MapboxGL.MapView>(null);
const cameraRef = useRef<MapboxGL.Camera>(null);
const onPress = async (event: OnPressEvent) => {
const [cluster] = event.features as Feature<Point>[];
if (cluster.properties?.cluster === true && sourceRef.current) {
// Error here. Works fine on Android
const expansionZoom = await sourceRef.current.getClusterExpansionZoom(
cluster
);
const centerCoordinate = cluster.geometry.coordinates;
const zoomLevel = expansionZoom * 1.15;
cameraRef.current?.setCamera({
centerCoordinate,
zoomLevel,
animationMode: "easeTo",
animationDuration: 1500
});
}
};
return (
<View style={styles.container}>
<MapboxGL.MapView
ref={mapRef}
style={StyleSheet.absoluteFillObject}
styleURL={MapboxGL.StyleURL.Dark}
scaleBarEnabled={false}
pitchEnabled={false}
>
<MapboxGL.Camera
ref={cameraRef}
centerCoordinate={[0, 0]}
zoomLevel={0}
/>
<MapboxGL.ShapeSource
ref={sourceRef}
id="earthquakes"
onPress={onPress}
cluster
clusterRadius={50}
clusterMaxZoom={14}
url="https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson"
>
<MapboxGL.SymbolLayer
id="pointCount"
style={layerStyles.clusterCount}
/>
<MapboxGL.CircleLayer
id="clusteredPoints"
belowLayerID="pointCount"
filter={["has", "point_count"]}
style={layerStyles.clusteredPoints}
/>
<MapboxGL.CircleLayer
id="singlePoint"
filter={["!", ["has", "point_count"]]}
style={layerStyles.singlePoint}
/>
</MapboxGL.ShapeSource>
</MapboxGL.MapView>
</View>
);
}
Expected behavior
The method returns the zoom required to expand the cluster
Actual behavior
The method throws and error (as seen in the provided screenshot)
Screenshots
Versions (please complete the following information):
- Platform: iOS
- Platform OS: iOS 15
- Device: Phone6
- Emulator/ Simulator: mo
- Dev OS: macOS 12.12.1
- @rnmapbox/maps Version 10.0.0-beta.15
- Mapbox GL version 10
- React Native Version 0.68.2
- Expo Version 45
I've got same issue
Please help me Mapbox
developers
I can provide info into why this is happening, but I'm not sure I'll be able to submit a PR...
tldr: using clusterId for cluster-related functions is being deprecated, but the iOS v10 code hasn't been updated for the getClusterExpansionZoom
native func (in switft).
details:
javascript/components/ShapeSource.js
provides a means to overload the getClusterExpansionZoom
function to allow either a
- clusterId: number or
- feature: Feature<Geometry, Properties>
and calls the appropriate native func, either getClusterExpansionZoom
or getClusterExpansionZoomById
ios/RCTMGL-v10/RCTMGLShapeSource.swift
implements getClusterExpansionZoom
, but expecting a clusterId arg. There's no getClusterExpansionZoomById
Looks like just an oversight, since getClusterLeaves
and getClusterChildren
take the cluster feature as an arg.
Hello,
I am not an iOS developer but I was able to solve this problem with this patch
diff --git a/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSource.swift b/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSource.swift
index 3542821..09a09ee 100644
--- a/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSource.swift
+++ b/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSource.swift
@@ -191,24 +191,25 @@ extension RCTMGLShapeSource
extension RCTMGLShapeSource
{
- func getClusterExpansionZoom(
- _ clusterId: NSNumber,
- completion: @escaping (Result<Int, Error>) -> Void)
- {
- guard let mapView = map?.mapView else {
- completion(.failure(RCTMGLError.failed("getClusterExpansionZoom: no mapView")))
- return
- }
+ func getClusterExpansionZoom(
+ _ featureJSON: String,
+ completion: @escaping (Result<Int, Error>) -> Void
+ ) {
+ guard let mapView = map?.mapView else {
+ completion(.failure(RCTMGLError.failed("getClusterExpansionZoom: no mapView")))
+ return
+ }
- let options = SourceQueryOptions(sourceLayerIds: nil, filter: Exp(.eq) {
- Exp(.get) { "cluster_id" }
- clusterId.uintValue
- })
- mapView.mapboxMap.querySourceFeatures(for: id, options: options) { result in
- switch result {
- case .success(let features):
- let cluster = features[0]
- mapView.mapboxMap.queryFeatureExtension(for: self.id, feature: cluster.feature, extension: "supercluster", extensionField: "expansion-zoom") { result in
+ logged(
+ "RCTMGLShapeSource.getClusterExpansionZoom",
+ rejecter: { (_, _, error) in
+ completion(.failure(error!))
+ }
+ ) {
+ let cluster: Feature = try parse(featureJSON)
+ mapView.mapboxMap.queryFeatureExtension(
+ for: self.id, feature: cluster, extension: "supercluster", extensionField: "expansion-zoom"
+ ) { result in
switch result {
case .success(let features):
guard let value = features.value as? NSNumber else {
@@ -221,11 +222,8 @@ extension RCTMGLShapeSource
completion(.failure(error))
}
}
- case .failure(let error):
- completion(.failure(error))
}
}
- }
func getClusterLeaves(_ featureJSON: String,
number: uint,
diff --git a/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.m b/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.m
index 9449b79..124bc36 100644
--- a/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.m
+++ b/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.m
@@ -25,7 +25,7 @@
RCT_EXTERN_METHOD(getClusterExpansionZoom:(nonnull NSNumber*)reactTag
- clusterId:(nonnull NSNumber*)clusterId
+ featureJSON:(nonnull NSString*)featureJSON
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
diff --git a/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift b/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift
index 7cb642a..65e152e 100644
--- a/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift
+++ b/node_modules/@rnmapbox/maps/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift
@@ -38,12 +38,12 @@ extension RCTMGLShapeSourceManager {
extension RCTMGLShapeSourceManager {
@objc func getClusterExpansionZoom(
_ reactTag: NSNumber,
- clusterId: NSNumber,
+ featureJSON: String,
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) -> Void
{
self.withShapeSource(reactTag, name:"getClusterExpansionZoom", rejecter: rejecter) { shapeSource in
- shapeSource.getClusterExpansionZoom(clusterId) { result in
+ shapeSource.getClusterExpansionZoom(featureJSON) { result in
switch result {
case .success(let zoom):
resolver([
I don't know if it's the right thing to do 😄