expo-gaode-map-navigation 2.0.14 → 2.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>expo-gaode-map-navigation</name>
4
+ <comment>Project example-navigation-android-expo-gaode-map-navigation created by Buildship.</comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>org.eclipse.jdt.core.javabuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ <buildCommand>
14
+ <name>org.eclipse.buildship.core.gradleprojectbuilder</name>
15
+ <arguments>
16
+ </arguments>
17
+ </buildCommand>
18
+ </buildSpec>
19
+ <natures>
20
+ <nature>org.eclipse.jdt.core.javanature</nature>
21
+ <nature>org.eclipse.buildship.core.gradleprojectnature</nature>
22
+ </natures>
23
+ <filteredResources>
24
+ <filter>
25
+ <id>1778483172220</id>
26
+ <name></name>
27
+ <type>30</type>
28
+ <matcher>
29
+ <id>org.eclipse.core.resources.regexFilterMatcher</id>
30
+ <arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
31
+ </matcher>
32
+ </filter>
33
+ </filteredResources>
34
+ </projectDescription>
@@ -27,6 +27,8 @@ class ExpoGaodeMapModule : Module() {
27
27
  /** 定位管理器实例 */
28
28
  private var locationManager: LocationManager? = null
29
29
 
30
+ private fun jsValue(value: Any?): Any? = value
31
+
30
32
  override fun definition() = ModuleDefinition {
31
33
  Name("ExpoGaodeMap")
32
34
 
@@ -93,7 +95,7 @@ class ExpoGaodeMapModule : Module() {
93
95
  }
94
96
 
95
97
  Function("getPrivacyStatus") {
96
- SDKInitializer.getPrivacyStatus()
98
+ jsValue(SDKInitializer.getPrivacyStatus())
97
99
  }
98
100
 
99
101
  /**
@@ -109,14 +111,14 @@ class ExpoGaodeMapModule : Module() {
109
111
  * @return SDK 版本号
110
112
  */
111
113
  Function("getVersion") {
112
- SDKInitializer.getVersion()
114
+ jsValue(SDKInitializer.getVersion())
113
115
  }
114
116
 
115
117
  /**
116
118
  * 检查原生 SDK 是否已配置 API Key
117
119
  */
118
120
  Function("isNativeSDKConfigured") {
119
- try {
121
+ jsValue(try {
120
122
  val context = appContext.reactContext!!
121
123
  val apiKey = context.packageManager
122
124
  .getApplicationInfo(context.packageName, android.content.pm.PackageManager.GET_META_DATA)
@@ -124,7 +126,7 @@ class ExpoGaodeMapModule : Module() {
124
126
  !apiKey.isNullOrEmpty()
125
127
  } catch (_: Exception) {
126
128
  false
127
- }
129
+ })
128
130
  }
129
131
 
130
132
 
@@ -187,11 +189,11 @@ class ExpoGaodeMapModule : Module() {
187
189
  Function("distanceBetweenCoordinates") { p1: Map<String, Any>?, p2: Map<String, Any>? ->
188
190
  val coord1 = LatLngParser.parseLatLng(p1)
189
191
  val coord2 = LatLngParser.parseLatLng(p2)
190
- if (coord1 != null && coord2 != null) {
192
+ jsValue(if (coord1 != null && coord2 != null) {
191
193
  GeometryUtils.calculateDistance(coord1, coord2)
192
194
  } else {
193
195
  0.0
194
- }
196
+ })
195
197
  }
196
198
 
197
199
  /**
@@ -213,16 +215,16 @@ class ExpoGaodeMapModule : Module() {
213
215
  val normalized = LatLngParser.parseLatLngList(points)
214
216
  val safeMinZoom = minZoom ?: 3
215
217
  val safeMaxZoom = maxZoom ?: 20
216
- if (normalized.isEmpty()) return@Function safeMinZoom.toDouble()
218
+ if (normalized.isEmpty()) return@Function jsValue(safeMinZoom.toDouble())
217
219
 
218
- GeometryUtils.calculateFitZoom(
220
+ jsValue(GeometryUtils.calculateFitZoom(
219
221
  normalized,
220
222
  viewportWidthPx ?: 390.0,
221
223
  viewportHeightPx ?: 844.0,
222
224
  paddingPx ?: 48.0,
223
225
  safeMinZoom,
224
226
  safeMaxZoom
225
- )
227
+ ))
226
228
  }
227
229
 
228
230
  /**
@@ -232,7 +234,7 @@ class ExpoGaodeMapModule : Module() {
232
234
  */
233
235
  Function("calculatePolygonArea") { points: List<Any>? ->
234
236
  val rings = LatLngParser.parseLatLngListList(points)
235
- if (rings.isEmpty()) return@Function 0.0
237
+ if (rings.isEmpty()) return@Function jsValue(0.0)
236
238
 
237
239
  // 第一项是外轮廓
238
240
  var totalArea = GeometryUtils.calculatePolygonArea(rings[0])
@@ -245,7 +247,7 @@ class ExpoGaodeMapModule : Module() {
245
247
  }
246
248
 
247
249
  // 确保面积不为负数
248
- max(0.0, totalArea)
250
+ jsValue(max(0.0, totalArea))
249
251
  }
250
252
 
251
253
  /**
@@ -255,24 +257,24 @@ class ExpoGaodeMapModule : Module() {
255
257
  * @return 是否在多边形内
256
258
  */
257
259
  Function("isPointInPolygon") { point: Map<String, Any>?, polygon: List<Any>? ->
258
- val pt = LatLngParser.parseLatLng(point) ?: return@Function false
260
+ val pt = LatLngParser.parseLatLng(point) ?: return@Function jsValue(false)
259
261
  val rings = LatLngParser.parseLatLngListList(polygon)
260
- if (rings.isEmpty()) return@Function false
262
+ if (rings.isEmpty()) return@Function jsValue(false)
261
263
 
262
264
  // 点必须在外轮廓内
263
265
  val inOuter = GeometryUtils.isPointInPolygon(pt, rings[0])
264
- if (!inOuter) return@Function false
266
+ if (!inOuter) return@Function jsValue(false)
265
267
 
266
268
  // 点不能在任何内孔内
267
269
  if (rings.size > 1) {
268
270
  for (i in 1 until rings.size) {
269
271
  if (GeometryUtils.isPointInPolygon(pt, rings[i])) {
270
- return@Function false
272
+ return@Function jsValue(false)
271
273
  }
272
274
  }
273
275
  }
274
276
 
275
- true
277
+ jsValue(true)
276
278
  }
277
279
 
278
280
  /**
@@ -285,11 +287,11 @@ class ExpoGaodeMapModule : Module() {
285
287
  Function("isPointInCircle") { point: Map<String, Any>?, center: Map<String, Any>?, radius: Double ->
286
288
  val pt = LatLngParser.parseLatLng(point)
287
289
  val cn = LatLngParser.parseLatLng(center)
288
- if (pt != null && cn != null) {
290
+ jsValue(if (pt != null && cn != null) {
289
291
  GeometryUtils.isPointInCircle(pt, cn, radius)
290
292
  } else {
291
293
  false
292
- }
294
+ })
293
295
  }
294
296
 
295
297
  /**
@@ -301,11 +303,11 @@ class ExpoGaodeMapModule : Module() {
301
303
  Function("calculateRectangleArea") { southWest: Map<String, Any>?, northEast: Map<String, Any>? ->
302
304
  val sw = LatLngParser.parseLatLng(southWest)
303
305
  val ne = LatLngParser.parseLatLng(northEast)
304
- if (sw != null && ne != null) {
306
+ jsValue(if (sw != null && ne != null) {
305
307
  GeometryUtils.calculateRectangleArea(sw, ne)
306
308
  } else {
307
309
  0.0
308
- }
310
+ })
309
311
  }
310
312
 
311
313
  /**
@@ -318,7 +320,7 @@ class ExpoGaodeMapModule : Module() {
318
320
  val pathPoints = LatLngParser.parseLatLngList(path)
319
321
  val targetPoint = LatLngParser.parseLatLng(target)
320
322
 
321
- if (targetPoint != null && pathPoints.isNotEmpty()) {
323
+ jsValue(if (targetPoint != null && pathPoints.isNotEmpty()) {
322
324
  val result = GeometryUtils.getNearestPointOnPath(pathPoints, targetPoint)
323
325
  if (result != null) {
324
326
  mapOf(
@@ -332,7 +334,7 @@ class ExpoGaodeMapModule : Module() {
332
334
  }
333
335
  } else {
334
336
  null
335
- }
337
+ })
336
338
  }
337
339
 
338
340
  /**
@@ -342,16 +344,16 @@ class ExpoGaodeMapModule : Module() {
342
344
  */
343
345
  Function("calculateCentroid") { polygon: List<Any>? ->
344
346
  val rings = LatLngParser.parseLatLngListList(polygon)
345
- if (rings.isEmpty()) return@Function null
347
+ if (rings.isEmpty()) return@Function jsValue(null)
346
348
 
347
349
  if (rings.size == 1) {
348
350
  val result = GeometryUtils.calculateCentroid(rings[0])
349
- return@Function result?.let {
351
+ return@Function jsValue(result?.let {
350
352
  mapOf(
351
353
  "latitude" to it.latitude,
352
354
  "longitude" to it.longitude
353
355
  )
354
- }
356
+ })
355
357
  }
356
358
 
357
359
  // 带孔多边形的质心计算: Σ(Area_i * Centroid_i) / Σ(Area_i)
@@ -376,14 +378,14 @@ class ExpoGaodeMapModule : Module() {
376
378
  }
377
379
  }
378
380
 
379
- if (abs(totalArea) > 1e-9) {
381
+ jsValue(if (abs(totalArea) > 1e-9) {
380
382
  mapOf(
381
383
  "latitude" to sumLat / totalArea,
382
384
  "longitude" to sumLon / totalArea
383
385
  )
384
386
  } else {
385
387
  null
386
- }
388
+ })
387
389
  }
388
390
 
389
391
  /**
@@ -393,10 +395,10 @@ class ExpoGaodeMapModule : Module() {
393
395
  */
394
396
  Function("calculatePathBounds") { pointsList: List<Any>? ->
395
397
  val points = LatLngParser.parseLatLngList(pointsList)
396
- if (points.isEmpty()) return@Function null
398
+ if (points.isEmpty()) return@Function jsValue(null)
397
399
 
398
400
  val result = GeometryUtils.calculatePathBounds(points)
399
- result?.let {
401
+ jsValue(result?.let {
400
402
  mapOf(
401
403
  "north" to it.north,
402
404
  "south" to it.south,
@@ -407,7 +409,7 @@ class ExpoGaodeMapModule : Module() {
407
409
  "longitude" to it.centerLon
408
410
  )
409
411
  )
410
- }
412
+ })
411
413
  }
412
414
 
413
415
  /**
@@ -418,11 +420,11 @@ class ExpoGaodeMapModule : Module() {
418
420
  */
419
421
  Function("encodeGeoHash") { coordinate: Map<String, Any>?, precision: Int ->
420
422
  val latLng = LatLngParser.parseLatLng(coordinate)
421
- if (latLng != null) {
423
+ jsValue(if (latLng != null) {
422
424
  GeometryUtils.encodeGeoHash(latLng, precision)
423
425
  } else {
424
426
  ""
425
- }
427
+ })
426
428
  }
427
429
 
428
430
  /**
@@ -434,12 +436,12 @@ class ExpoGaodeMapModule : Module() {
434
436
  Function("simplifyPolyline") { points: List<Any>?, tolerance: Double ->
435
437
  val poly = LatLngParser.parseLatLngList(points)
436
438
  val simplified = GeometryUtils.simplifyPolyline(poly, tolerance)
437
- simplified.map {
439
+ jsValue(simplified.map {
438
440
  mapOf(
439
441
  "latitude" to it.latitude,
440
442
  "longitude" to it.longitude
441
443
  )
442
- }
444
+ })
443
445
  }
444
446
 
445
447
  /**
@@ -449,7 +451,7 @@ class ExpoGaodeMapModule : Module() {
449
451
  */
450
452
  Function("calculatePathLength") { points: List<Any>? ->
451
453
  val poly = LatLngParser.parseLatLngList(points)
452
- GeometryUtils.calculatePathLength(poly)
454
+ jsValue(GeometryUtils.calculatePathLength(poly))
453
455
  }
454
456
 
455
457
  /**
@@ -459,12 +461,12 @@ class ExpoGaodeMapModule : Module() {
459
461
  */
460
462
  Function("parsePolyline") { polylineStr: String? ->
461
463
  val result = GeometryUtils.parsePolyline(polylineStr)
462
- result.map {
464
+ jsValue(result.map {
463
465
  mapOf(
464
466
  "latitude" to it.latitude,
465
467
  "longitude" to it.longitude
466
468
  )
467
- }
469
+ })
468
470
  }
469
471
 
470
472
  /**
@@ -476,7 +478,7 @@ class ExpoGaodeMapModule : Module() {
476
478
  Function("getPointAtDistance") { points: List<Any>?, distance: Double ->
477
479
  val poly = LatLngParser.parseLatLngList(points)
478
480
  val result = GeometryUtils.getPointAtDistance(poly, distance)
479
- if (result != null) {
481
+ jsValue(if (result != null) {
480
482
  mapOf(
481
483
  "latitude" to result.point.latitude,
482
484
  "longitude" to result.point.longitude,
@@ -484,7 +486,7 @@ class ExpoGaodeMapModule : Module() {
484
486
  )
485
487
  } else {
486
488
  null
487
- }
489
+ })
488
490
  }
489
491
 
490
492
  /**
@@ -495,7 +497,7 @@ class ExpoGaodeMapModule : Module() {
495
497
  */
496
498
  Function("latLngToTile") { coordinate: Map<String, Any>?, zoom: Int ->
497
499
  val latLng = LatLngParser.parseLatLng(coordinate)
498
- if (latLng != null) {
500
+ jsValue(if (latLng != null) {
499
501
  val result = GeometryUtils.latLngToTile(latLng, zoom)
500
502
  if (result != null && result.size >= 2) {
501
503
  mapOf("x" to result[0], "y" to result[1])
@@ -504,7 +506,7 @@ class ExpoGaodeMapModule : Module() {
504
506
  }
505
507
  } else {
506
508
  null
507
- }
509
+ })
508
510
  }
509
511
 
510
512
  /**
@@ -517,9 +519,9 @@ class ExpoGaodeMapModule : Module() {
517
519
  val y = (tile?.get("y") as? Number)?.toInt() ?: 0
518
520
  val zoom = (tile?.get("z") as? Number)?.toInt() ?: (tile?.get("zoom") as? Number)?.toInt() ?: 0
519
521
  val result = GeometryUtils.tileToLatLng(x, y, zoom)
520
- result?.let {
522
+ jsValue(result?.let {
521
523
  mapOf("latitude" to it.latitude, "longitude" to it.longitude)
522
- }
524
+ })
523
525
  }
524
526
 
525
527
  /**
@@ -530,7 +532,7 @@ class ExpoGaodeMapModule : Module() {
530
532
  */
531
533
  Function("latLngToPixel") { coordinate: Map<String, Any>?, zoom: Int ->
532
534
  val latLng = LatLngParser.parseLatLng(coordinate)
533
- if (latLng != null) {
535
+ jsValue(if (latLng != null) {
534
536
  val result = GeometryUtils.latLngToPixel(latLng, zoom)
535
537
  if (result != null && result.size >= 2) {
536
538
  mapOf("x" to result[0], "y" to result[1])
@@ -539,7 +541,7 @@ class ExpoGaodeMapModule : Module() {
539
541
  }
540
542
  } else {
541
543
  null
542
- }
544
+ })
543
545
  }
544
546
 
545
547
  /**
@@ -552,9 +554,9 @@ class ExpoGaodeMapModule : Module() {
552
554
  val x = (pixel?.get("x") as? Number)?.toDouble() ?: 0.0
553
555
  val y = (pixel?.get("y") as? Number)?.toDouble() ?: 0.0
554
556
  val result = GeometryUtils.pixelToLatLng(x, y, zoom)
555
- result?.let {
557
+ jsValue(result?.let {
556
558
  mapOf("latitude" to it.latitude, "longitude" to it.longitude)
557
- }
559
+ })
558
560
  }
559
561
 
560
562
  /**
@@ -566,11 +568,11 @@ class ExpoGaodeMapModule : Module() {
566
568
  Function("findPointInPolygons") { point: Map<String, Any>?, polygons: List<List<Any>>? ->
567
569
  val pt = LatLngParser.parseLatLng(point)
568
570
  val polys = polygons?.map { LatLngParser.parseLatLngList(it) }
569
- if (pt != null && polys != null) {
571
+ jsValue(if (pt != null && polys != null) {
570
572
  GeometryUtils.findPointInPolygons(pt, polys)
571
573
  } else {
572
574
  -1
573
- }
575
+ })
574
576
  }
575
577
 
576
578
  /**
@@ -579,7 +581,7 @@ class ExpoGaodeMapModule : Module() {
579
581
  * @param gridSizeMeters 网格大小(米)
580
582
  */
581
583
  Function("generateHeatmapGrid") { points: List<Map<String, Any>>?, gridSizeMeters: Double ->
582
- if (points == null || points.isEmpty()) return@Function emptyList<Map<String, Any>>()
584
+ if (points == null || points.isEmpty()) return@Function jsValue(emptyList<Map<String, Any>>())
583
585
 
584
586
  val count = points.size
585
587
  val latitudes = DoubleArray(count)
@@ -593,13 +595,13 @@ class ExpoGaodeMapModule : Module() {
593
595
  }
594
596
 
595
597
  val result = GeometryUtils.generateHeatmapGrid(latitudes, longitudes, weights, gridSizeMeters)
596
- result.map {
598
+ jsValue(result.map {
597
599
  mapOf(
598
600
  "latitude" to it.latitude,
599
601
  "longitude" to it.longitude,
600
602
  "intensity" to it.intensity
601
603
  )
602
- }
604
+ })
603
605
  }
604
606
 
605
607
  // ==================== 定位配置 ====================
@@ -30,8 +30,8 @@ public class ExpoGaodeMapSearchModule: Module {
30
30
 
31
31
  let city = options["city"] as? String ?? ""
32
32
  let types = options["types"] as? String ?? ""
33
- let pageSize = options["pageSize"] as? Int ?? 20
34
- let pageNum = options["pageNum"] as? Int ?? 1
33
+ let pageSize = self.intOption(options, "pageSize", defaultValue: 20)
34
+ let pageNum = self.intOption(options, "pageNum", defaultValue: 1)
35
35
 
36
36
  let request = AMapPOIKeywordsSearchRequest()
37
37
  request.keywords = keyword
@@ -65,10 +65,10 @@ public class ExpoGaodeMapSearchModule: Module {
65
65
  return
66
66
  }
67
67
 
68
- let radius = options["radius"] as? Int ?? 1000
68
+ let radius = self.intOption(options, "radius", defaultValue: 1000)
69
69
  let types = options["types"] as? String ?? ""
70
- let pageSize = options["pageSize"] as? Int ?? 20
71
- let pageNum = options["pageNum"] as? Int ?? 1
70
+ let pageSize = self.intOption(options, "pageSize", defaultValue: 20)
71
+ let pageNum = self.intOption(options, "pageNum", defaultValue: 1)
72
72
 
73
73
  let request = AMapPOIAroundSearchRequest()
74
74
  request.keywords = keyword
@@ -136,7 +136,7 @@ public class ExpoGaodeMapSearchModule: Module {
136
136
  let request = AMapRoutePOISearchRequest()
137
137
  request.polyline = Array(points.prefix(100))
138
138
  request.searchType = searchType
139
- request.range = min(max(options["range"] as? Int ?? 250, 0), 500)
139
+ request.range = min(max(self.intOption(options, "range", defaultValue: 250), 0), 500)
140
140
  request.strategy = 0
141
141
 
142
142
  guard let searchAPI = self.createSearchAPI(promise: promise, errorCode: "SEARCH_ERROR") else {
@@ -160,8 +160,8 @@ public class ExpoGaodeMapSearchModule: Module {
160
160
  }
161
161
 
162
162
  let types = options["types"] as? String ?? ""
163
- let pageSize = options["pageSize"] as? Int ?? 20
164
- let pageNum = options["pageNum"] as? Int ?? 1
163
+ let pageSize = self.intOption(options, "pageSize", defaultValue: 20)
164
+ let pageNum = self.intOption(options, "pageNum", defaultValue: 1)
165
165
 
166
166
  // 转换路线点
167
167
  var points: [AMapGeoPoint] = []
@@ -224,7 +224,7 @@ public class ExpoGaodeMapSearchModule: Module {
224
224
  return
225
225
  }
226
226
 
227
- let radius = options["radius"] as? Int ?? 1000
227
+ let radius = self.intOption(options, "radius", defaultValue: 1000)
228
228
  let requireExtension = options["requireExtension"] as? Bool ?? true
229
229
 
230
230
  let request = AMapReGeocodeSearchRequest()
@@ -259,6 +259,18 @@ public class ExpoGaodeMapSearchModule: Module {
259
259
 
260
260
 
261
261
  // MARK: - Private Methods
262
+
263
+ private func intOption(_ options: [String: Any], _ key: String, defaultValue: Int) -> Int {
264
+ if let value = options[key] as? Int {
265
+ return value
266
+ }
267
+
268
+ if let value = options[key] as? NSNumber {
269
+ return value.intValue
270
+ }
271
+
272
+ return defaultValue
273
+ }
262
274
 
263
275
  private func limitReGeocodeRadius(_ radius: Int) -> Int {
264
276
  // AMapReGeocodeSearchRequest radius property is NSInteger
@@ -102,10 +102,8 @@ class LocationManager: NSObject, AMapLocationManagerDelegate {
102
102
  }
103
103
  }
104
104
 
105
- private func setReGeocodeLanguage(_ rawValue: AMapRegionLanguageType.RawValue) {
106
- if let language = AMapRegionLanguageType(rawValue: rawValue) {
107
- ensureLocationManager()?.reGeocodeLanguage = language
108
- }
105
+ private func setReGeocodeLanguage(_ rawValue: Int) {
106
+ ensureLocationManager()?.setValue(rawValue, forKey: "reGeocodeLanguage")
109
107
  }
110
108
 
111
109
  func setGeoLanguage(_ language: Int) {
@@ -243,6 +243,7 @@ class MarkerView: ExpoView {
243
243
  // 异步渲染并设置
244
244
  DispatchQueue.main.async { [weak self, weak annotationView] in
245
245
  guard let self = self, let annotationView = annotationView else { return }
246
+ guard self.isAnnotationView(annotationView, boundTo: annotation) else { return }
246
247
  if let generated = self.createImageFromSubviews() {
247
248
  annotationView.image = generated
248
249
  self.applyCenterOffset(to: annotationView, defaultOffset: .zero)
@@ -265,6 +266,7 @@ class MarkerView: ExpoView {
265
266
  // 异步加载图标
266
267
  loadIcon(iconUri: iconUri) { [weak self, weak annotationView] image in
267
268
  guard let self = self, let image = image, let annotationView = annotationView else { return }
269
+ guard self.isAnnotationView(annotationView, boundTo: annotation) else { return }
268
270
  let size = CGSize(width: self.iconWidth, height: self.iconHeight)
269
271
  UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
270
272
  image.draw(in: CGRect(origin: .zero, size: size))
@@ -347,6 +349,7 @@ class MarkerView: ExpoView {
347
349
  // 🔑 修复:延长延迟时间,给 React Native Image 更多加载时间
348
350
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self, weak annotationView] in
349
351
  guard let self = self, let annotationView = annotationView else { return }
352
+ guard self.isAnnotationView(annotationView, boundTo: annotation) else { return }
350
353
  // 再次检查缓存(避免重复渲染)
351
354
  if let cached = IconBitmapCache.shared.image(forKey: key) {
352
355
  annotationView.image = cached
@@ -410,12 +413,12 @@ class MarkerView: ExpoView {
410
413
  UIGraphicsEndImageContext()
411
414
 
412
415
  DispatchQueue.main.async {
416
+ guard let annotationView else { return }
417
+ guard self.isAnnotationView(annotationView, boundTo: annotation) else { return }
413
418
  if let img = resizedImage {
414
419
  IconBitmapCache.shared.setImage(img, forKey: key)
415
- annotationView?.image = img
416
- if let annotationView = annotationView {
417
- self.applyCenterOffset(to: annotationView, defaultOffset: CGPoint(x: 0, y: -img.size.height / 2))
418
- }
420
+ annotationView.image = img
421
+ self.applyCenterOffset(to: annotationView, defaultOffset: CGPoint(x: 0, y: -img.size.height / 2))
419
422
  }
420
423
  }
421
424
  }
@@ -580,6 +583,13 @@ class MarkerView: ExpoView {
580
583
  return .zero
581
584
  }
582
585
 
586
+ private func isAnnotationView(_ annotationView: MAAnnotationView, boundTo annotation: MAAnnotation) -> Bool {
587
+ guard let current = annotationView.annotation else {
588
+ return false
589
+ }
590
+ return (current as AnyObject) === (annotation as AnyObject)
591
+ }
592
+
583
593
  private func resolvedCustomSubviewSize(defaultSize: CGSize) -> CGSize {
584
594
  guard let firstSubview = subviews.first else {
585
595
  return defaultSize
@@ -725,36 +735,42 @@ class MarkerView: ExpoView {
725
735
  pendingUpdateTask?.cancel(); pendingUpdateTask = nil
726
736
  pendingSubviewRefreshTask?.cancel(); pendingSubviewRefreshTask = nil
727
737
 
728
- guard let mapView = mapView else {
729
- isRemoving = false
730
- return
731
- }
732
-
733
- // 确保在主线程执行移除操作
734
- let cleanup = { [weak self, weak mapView] in
735
- guard let self = self, let mapView = mapView else { return }
736
-
737
- // 1. 停止任何正在进行的平滑移动
738
- if self.animatedAnnotation != nil {
739
- self.stopSmoothMove()
740
- }
741
-
742
- // 2. 移除普通标记点
743
- if let annotation = self.annotation {
744
- mapView.removeAnnotation(annotation)
745
- self.annotation = nil
738
+ if Thread.isMainThread {
739
+ cleanupAnnotationFromMap()
740
+ } else {
741
+ DispatchQueue.main.sync {
742
+ cleanupAnnotationFromMap()
746
743
  }
744
+ }
745
+ }
747
746
 
748
- self.annotationView = nil
749
- self.animatedAnnotationView = nil
750
- self.isRemoving = false
747
+ private func cleanupAnnotationFromMap() {
748
+ defer { isRemoving = false }
749
+
750
+ guard let mapView = mapView else { return }
751
+
752
+ if let animAnnotation = animatedAnnotation {
753
+ if let animations = animAnnotation.allMoveAnimations() {
754
+ for animation in animations {
755
+ animation.cancel()
756
+ }
757
+ }
758
+ mapView.removeAnnotation(animAnnotation)
759
+ animatedAnnotation = nil
751
760
  }
752
761
 
753
- if Thread.isMainThread {
754
- cleanup()
755
- } else {
756
- DispatchQueue.main.async(execute: cleanup)
762
+ if let annotation = annotation {
763
+ mapView.removeAnnotation(annotation)
764
+ self.annotation = nil
757
765
  }
766
+
767
+ annotationView?.annotation = nil
768
+ animatedAnnotationView?.annotation = nil
769
+ annotationView = nil
770
+ animatedAnnotationView = nil
771
+ isAnimating = false
772
+ lastSetMapView = nil
773
+ self.mapView = nil
758
774
  }
759
775
 
760
776
  override func willRemoveSubview(_ subview: UIView) {
@@ -780,10 +796,12 @@ class MarkerView: ExpoView {
780
796
  }
781
797
 
782
798
  private func scheduleSubviewRefresh(allowFallbackToDefault: Bool) {
799
+ guard superview != nil else { return }
800
+
783
801
  pendingSubviewRefreshTask?.cancel()
784
802
 
785
803
  let task = DispatchWorkItem { [weak self] in
786
- guard let self = self, !self.isRemoving else { return }
804
+ guard let self = self, !self.isRemoving, self.superview != nil else { return }
787
805
  self.refreshAnnotationForSubviewChanges(allowFallbackToDefault: allowFallbackToDefault)
788
806
  }
789
807
 
@@ -1262,11 +1280,17 @@ class MarkerView: ExpoView {
1262
1280
  pendingAddTask?.cancel()
1263
1281
  pendingUpdateTask?.cancel()
1264
1282
  pendingSubviewRefreshTask?.cancel()
1283
+
1284
+ if Thread.isMainThread {
1285
+ cleanupAnnotationFromMap()
1286
+ }
1265
1287
 
1266
1288
  // 清理引用,防止内存泄漏
1267
1289
  mapView = nil
1268
1290
  annotation = nil
1269
1291
  annotationView = nil
1292
+ animatedAnnotation = nil
1293
+ animatedAnnotationView = nil
1270
1294
  lastSetMapView = nil
1271
1295
  }
1272
1296
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-gaode-map-navigation",
3
- "version": "2.0.14",
3
+ "version": "2.0.16",
4
4
  "description": "React Native AMap (Gaode Map) navigation module for Expo: route planning and turn-by-turn navigation, includes full map features.",
5
5
  "author": "TomWq <582752848@qq.com> (https://github.com/TomWq)",
6
6
  "repository": {