expo-gaode-map-navigation 2.0.3 → 2.0.4

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.
Files changed (70) hide show
  1. package/android/build.gradle +3 -0
  2. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +45 -49
  3. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +5 -15
  4. package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +143 -14
  5. package/build/ExpoGaodeMapNaviView.d.ts.map +1 -1
  6. package/build/ExpoGaodeMapNaviView.js +3 -2
  7. package/build/ExpoGaodeMapNaviView.js.map +1 -1
  8. package/build/ExpoGaodeMapNavigationModule.d.ts +2 -7
  9. package/build/ExpoGaodeMapNavigationModule.d.ts.map +1 -1
  10. package/build/ExpoGaodeMapNavigationModule.js +19 -2
  11. package/build/ExpoGaodeMapNavigationModule.js.map +1 -1
  12. package/build/index.d.ts.map +1 -1
  13. package/build/index.js +8 -2
  14. package/build/index.js.map +1 -1
  15. package/build/map/ExpoGaodeMapModule.d.ts +245 -4
  16. package/build/map/ExpoGaodeMapModule.d.ts.map +1 -1
  17. package/build/map/ExpoGaodeMapModule.js +197 -15
  18. package/build/map/ExpoGaodeMapModule.js.map +1 -1
  19. package/build/map/ExpoGaodeMapOfflineModule.d.ts.map +1 -1
  20. package/build/map/ExpoGaodeMapOfflineModule.js +19 -2
  21. package/build/map/ExpoGaodeMapOfflineModule.js.map +1 -1
  22. package/build/map/ExpoGaodeMapView.d.ts.map +1 -1
  23. package/build/map/ExpoGaodeMapView.js +8 -2
  24. package/build/map/ExpoGaodeMapView.js.map +1 -1
  25. package/build/map/components/overlays/Circle.d.ts.map +1 -1
  26. package/build/map/components/overlays/Circle.js +3 -2
  27. package/build/map/components/overlays/Circle.js.map +1 -1
  28. package/build/map/components/overlays/Cluster.d.ts.map +1 -1
  29. package/build/map/components/overlays/Cluster.js +3 -2
  30. package/build/map/components/overlays/Cluster.js.map +1 -1
  31. package/build/map/components/overlays/HeatMap.d.ts.map +1 -1
  32. package/build/map/components/overlays/HeatMap.js +3 -2
  33. package/build/map/components/overlays/HeatMap.js.map +1 -1
  34. package/build/map/components/overlays/Marker.d.ts.map +1 -1
  35. package/build/map/components/overlays/Marker.js +3 -2
  36. package/build/map/components/overlays/Marker.js.map +1 -1
  37. package/build/map/components/overlays/MultiPoint.d.ts.map +1 -1
  38. package/build/map/components/overlays/MultiPoint.js +3 -2
  39. package/build/map/components/overlays/MultiPoint.js.map +1 -1
  40. package/build/map/components/overlays/Polygon.d.ts.map +1 -1
  41. package/build/map/components/overlays/Polygon.js +3 -2
  42. package/build/map/components/overlays/Polygon.js.map +1 -1
  43. package/build/map/components/overlays/Polyline.d.ts.map +1 -1
  44. package/build/map/components/overlays/Polyline.js +3 -2
  45. package/build/map/components/overlays/Polyline.js.map +1 -1
  46. package/build/map/types/common.types.d.ts +26 -0
  47. package/build/map/types/common.types.d.ts.map +1 -1
  48. package/build/map/types/common.types.js.map +1 -1
  49. package/build/map/types/native-module.types.d.ts +28 -1
  50. package/build/map/types/native-module.types.d.ts.map +1 -1
  51. package/build/map/types/native-module.types.js.map +1 -1
  52. package/build/map/utils/ErrorHandler.d.ts +6 -0
  53. package/build/map/utils/ErrorHandler.d.ts.map +1 -1
  54. package/build/map/utils/ErrorHandler.js +42 -0
  55. package/build/map/utils/ErrorHandler.js.map +1 -1
  56. package/build/map/utils/GeoUtils.d.ts.map +1 -1
  57. package/build/map/utils/GeoUtils.js +6 -2
  58. package/build/map/utils/GeoUtils.js.map +1 -1
  59. package/build/map/utils/lazyNativeViewManager.d.ts +3 -0
  60. package/build/map/utils/lazyNativeViewManager.d.ts.map +1 -0
  61. package/build/map/utils/lazyNativeViewManager.js +11 -0
  62. package/build/map/utils/lazyNativeViewManager.js.map +1 -0
  63. package/ios/ExpoGaodeMapNavigation.podspec +5 -0
  64. package/ios/map/ExpoGaodeMapModule.swift +27 -40
  65. package/ios/map/ExpoGaodeMapView.swift +160 -77
  66. package/ios/map/GaodeMapPrivacyManager.swift +155 -0
  67. package/ios/map/modules/LocationManager.swift +43 -24
  68. package/package.json +1 -1
  69. package/android/src/main/java/expo/modules/gaodemap/map/MapPreloadManager.kt +0 -494
  70. package/ios/map/MapPreloadManager.swift +0 -348
@@ -40,49 +40,32 @@ public class ExpoGaodeMapModule: Module {
40
40
  return true // 已经设置过了
41
41
  }
42
42
 
43
- /**
44
- * 尝试启动预加载(检查 API Key 后)
45
- * @param delay 延迟时间(秒)
46
- * @param poolSize 预加载池大小
47
- */
48
- private func tryStartPreload(delay: Double = 1.0, poolSize: Int = 1) {
49
- if let apiKey = AMapServices.shared().apiKey, !apiKey.isEmpty {
50
- DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
51
- let status = MapPreloadManager.shared.getStatus()
52
- let isPreloading = (status["isPreloading"] as? Bool) ?? false
53
-
54
- if !MapPreloadManager.shared.hasPreloadedMapView() && !isPreloading {
55
-
56
- MapPreloadManager.shared.startPreload(poolSize: poolSize)
57
- }
58
- }
59
- } else {
60
- print("⚠️ ExpoGaodeMap: API Key 未设置,跳过自动预加载")
61
- }
62
- }
63
-
64
43
  public func definition() -> ModuleDefinition {
65
44
  Name("ExpoGaodeMap")
66
-
67
- // 模块初始化:尝试从本地缓存恢复隐私同意状态
68
- OnCreate {
69
45
 
70
- // 1. 告知 SDK:隐私协议已展示且包含隐私内容
71
- MAMapView.updatePrivacyShow(
72
- AMapPrivacyShowStatus.didShow,
73
- privacyInfo: AMapPrivacyInfoStatus.didContain
74
- )
46
+ OnCreate {
47
+ GaodeMapPrivacyManager.restorePersistedState()
48
+ _ = self.trySetupApiKeyFromPlist()
49
+ }
50
+
51
+ Function("setPrivacyShow") { (hasShow: Bool, hasContainsPrivacy: Bool) in
52
+ GaodeMapPrivacyManager.setPrivacyShow(hasShow, hasContainsPrivacy: hasContainsPrivacy)
53
+ }
75
54
 
76
- // 2. 告知 SDK:用户已同意隐私协议(关键)
77
- MAMapView.updatePrivacyAgree(AMapPrivacyAgreeStatus.didAgree)
55
+ Function("setPrivacyAgree") { (hasAgree: Bool) in
56
+ GaodeMapPrivacyManager.setPrivacyAgree(hasAgree)
57
+ }
78
58
 
79
- print(" ExpoGaodeMap: 原生侧已默认同意隐私协议")
59
+ Function("setPrivacyVersion") { (version: String) in
60
+ GaodeMapPrivacyManager.setPrivacyVersion(version)
61
+ }
80
62
 
81
- // 3. 自动设置 API Key(Info.plist)
82
- self.trySetupApiKeyFromPlist()
63
+ Function("resetPrivacyConsent") {
64
+ GaodeMapPrivacyManager.resetPrivacyConsent()
65
+ }
83
66
 
84
- // 4. 自动启动预加载(可选)
85
- self.tryStartPreload(delay: 2.0, poolSize: 1)
67
+ Function("getPrivacyStatus") { () -> [String: Any] in
68
+ GaodeMapPrivacyManager.status()
86
69
  }
87
70
 
88
71
  // ==================== SDK 初始化 ====================
@@ -92,6 +75,11 @@ public class ExpoGaodeMapModule: Module {
92
75
  * @param config 配置字典,包含 iosKey
93
76
  */
94
77
  Function("initSDK") { (config: [String: String]) in
78
+ guard GaodeMapPrivacyManager.isReady else {
79
+ throw Exception(name: "PRIVACY_NOT_AGREED", description: "隐私协议未完成确认,请先调用 setPrivacyShow/setPrivacyAgree")
80
+ }
81
+ GaodeMapPrivacyManager.applyPrivacyState()
82
+
95
83
  // 1) 优先使用传入的 iosKey;2) 否则回退读取 Info.plist 的 AMapApiKey
96
84
  let providedKey = config["iosKey"]?.trimmingCharacters(in: .whitespacesAndNewlines)
97
85
  var finalKey: String? = (providedKey?.isEmpty == false) ? providedKey : nil
@@ -113,10 +101,7 @@ public class ExpoGaodeMapModule: Module {
113
101
  }
114
102
  AMapServices.shared().enableHTTPS = true
115
103
 
116
- // 初始化定位管理器(触发原生侧懒加载)
117
104
  self.getLocationManager()
118
-
119
- print("✅ ExpoGaodeMap: 已设置 API Key 并完成初始化(来源:\(providedKey != nil ? "入参 iosKey" : "Info.plist" ))")
120
105
  }
121
106
 
122
107
  /**
@@ -141,6 +126,9 @@ public class ExpoGaodeMapModule: Module {
141
126
  if let apiKey = AMapServices.shared().apiKey, !apiKey.isEmpty {
142
127
  return true
143
128
  }
129
+ if let plistKey = Bundle.main.infoDictionary?["AMapApiKey"] as? String, !plistKey.isEmpty {
130
+ return true
131
+ }
144
132
  return false
145
133
  }
146
134
 
@@ -774,7 +762,6 @@ public class ExpoGaodeMapModule: Module {
774
762
  OnDestroy {
775
763
  self.locationManager?.destroy()
776
764
  self.locationManager = nil
777
- MapPreloadManager.shared.cleanup()
778
765
  }
779
766
  }
780
767
 
@@ -109,27 +109,14 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
109
109
  private var zoomVelocity: Double = 0
110
110
  private let friction: Double = 0.92 // 摩擦系数,越接近 1 滑得越远
111
111
  private let velocityThreshold: Double = 0.001 // 停止阈值
112
+ private var privacyObserver: NSObjectProtocol?
112
113
 
113
114
  // MARK: - 初始化
114
115
 
115
116
  required init(appContext: AppContext? = nil) {
116
117
  super.init(appContext: appContext)
117
118
 
118
- // 确保隐私合规已设置
119
- MAMapView.updatePrivacyAgree(.didAgree)
120
- MAMapView.updatePrivacyShow(.didShow, privacyInfo: .didContain)
121
-
122
- // 创建 MAMapView
123
- // 尝试从预加载池获取 MapView
124
- if let preloaded = MapPreloadManager.shared.getPreloadedMapView() {
125
- mapView = preloaded
126
- mapView.frame = bounds
127
- } else {
128
- mapView = MAMapView(frame: bounds)
129
- }
130
-
131
- mapView.delegate = self
132
- mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
119
+ GaodeMapPrivacyManager.applyPrivacyState()
133
120
 
134
121
  // 创建 MKMapView
135
122
  appleMapView = MKMapView(frame: bounds)
@@ -155,36 +142,25 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
155
142
  // 2. - markerContainer (隐藏)
156
143
  // 3. - overlayContainer (隐藏)
157
144
  // 4. - appleMapView (隐藏)
158
- // 5. - mapView (可见,在最上层)
145
+ // 5. - mapView (隐私合规完成后再创建,在最上层)
159
146
  addSubview(markerContainer)
160
147
  addSubview(overlayContainer)
161
148
  addSubview(appleMapView)
162
- addSubview(mapView)
163
-
164
- cameraManager = CameraManager(mapView: mapView)
165
- uiManager = UIManager(mapView: mapView)
166
-
167
- // 设置定位变化回调
168
- uiManager.onLocationChanged = { [weak self] latitude, longitude, accuracy in
169
- self?.onLocation([
170
- "latitude": latitude,
171
- "longitude": longitude,
172
- "accuracy": accuracy,
173
- "timestamp": Date().timeIntervalSince1970 * 1000
174
- ])
149
+
150
+ privacyObserver = NotificationCenter.default.addObserver(
151
+ forName: .gaodeMapPrivacyStatusDidChange,
152
+ object: nil,
153
+ queue: .main
154
+ ) { [weak self] _ in
155
+ self?.handlePrivacyStatusChanged()
175
156
  }
176
-
177
- setupDefaultConfig()
178
-
179
- // 添加 Pinch 手势以支持惯性缩放
180
- pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
181
- pinchGesture.delegate = self
182
- mapView.addGestureRecognizer(pinchGesture)
157
+
158
+ ensureMapViewIfReady()
183
159
  }
184
160
 
185
161
  override func layoutSubviews() {
186
162
  super.layoutSubviews()
187
- mapView.frame = bounds
163
+ mapView?.frame = bounds
188
164
  appleMapView.frame = bounds
189
165
  // 🔑 移除自动调用 setupAllOverlayViews(),避免频繁触发
190
166
  // layoutSubviews 会在任何视图变化时调用,导致不必要的批量刷新
@@ -197,6 +173,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
197
173
  override func didMoveToWindow() {
198
174
  super.didMoveToWindow()
199
175
  if window != nil {
176
+ ensureMapViewIfReady()
200
177
 
201
178
  // 🔑 只在首次添加到窗口时批量设置,后续添加通过 didAddSubview 单独处理
202
179
  setupAllOverlayViews()
@@ -208,6 +185,10 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
208
185
  * 这个函数是幂等的,重复调用是安全的
209
186
  */
210
187
  private func setupAllOverlayViews() {
188
+ guard let mapView else {
189
+ return
190
+ }
191
+
211
192
  // 统一从 overlayViews 数组设置所有覆盖物(包括 MarkerView)
212
193
  for view in overlayViews {
213
194
  if let markerView = view as? MarkerView {
@@ -240,7 +221,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
240
221
  // 🔑 关键:MarkerView 不能隐藏,否则 children 无法渲染成图片
241
222
  // 通过 hitTest 返回 nil 已经确保不阻挡地图交互
242
223
  overlayViews.append(markerView)
243
- markerView.setMap(mapView)
224
+ if let mapView {
225
+ markerView.setMap(mapView)
226
+ }
244
227
 
245
228
  return
246
229
  }
@@ -250,7 +233,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
250
233
  circleView.alpha = 0
251
234
  circleView.isHidden = true
252
235
  overlayViews.append(circleView)
253
- circleView.setMap(mapView)
236
+ if let mapView {
237
+ circleView.setMap(mapView)
238
+ }
254
239
 
255
240
  return
256
241
  } else if let polylineView = view as? PolylineView {
@@ -258,7 +243,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
258
243
  polylineView.alpha = 0
259
244
  polylineView.isHidden = true
260
245
  overlayViews.append(polylineView)
261
- polylineView.setMap(mapView)
246
+ if let mapView {
247
+ polylineView.setMap(mapView)
248
+ }
262
249
 
263
250
  return
264
251
  } else if let polygonView = view as? PolygonView {
@@ -266,7 +253,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
266
253
  polygonView.alpha = 0
267
254
  polygonView.isHidden = true
268
255
  overlayViews.append(polygonView)
269
- polygonView.setMap(mapView)
256
+ if let mapView {
257
+ polygonView.setMap(mapView)
258
+ }
270
259
 
271
260
  return
272
261
  } else if let heatMapView = view as? HeatMapView {
@@ -274,7 +263,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
274
263
  heatMapView.alpha = 0
275
264
  heatMapView.isHidden = true
276
265
  overlayViews.append(heatMapView)
277
- heatMapView.setMap(mapView)
266
+ if let mapView {
267
+ heatMapView.setMap(mapView)
268
+ }
278
269
 
279
270
  return
280
271
  } else if let multiPointView = view as? MultiPointView {
@@ -282,7 +273,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
282
273
  multiPointView.alpha = 0
283
274
  multiPointView.isHidden = true
284
275
  overlayViews.append(multiPointView)
285
- multiPointView.setMap(mapView)
276
+ if let mapView {
277
+ multiPointView.setMap(mapView)
278
+ }
286
279
 
287
280
  return
288
281
  } else if let clusterView = view as? ClusterView {
@@ -290,7 +283,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
290
283
  clusterView.alpha = 0
291
284
  clusterView.isHidden = true
292
285
  overlayViews.append(clusterView)
293
- clusterView.setMap(mapView)
286
+ if let mapView {
287
+ clusterView.setMap(mapView)
288
+ }
294
289
 
295
290
  return
296
291
  }
@@ -324,7 +319,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
324
319
 
325
320
  // 🔑 新架构下也不能隐藏 MarkerView,否则 children 无法渲染
326
321
  overlayViews.append(markerView)
327
- markerView.setMap(mapView)
322
+ if let mapView {
323
+ markerView.setMap(mapView)
324
+ }
328
325
  // 🔑 关键修复:不再调用 setupAllOverlayViews(),避免所有覆盖物重新设置
329
326
  return
330
327
  }
@@ -339,7 +336,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
339
336
  circleView.alpha = 0
340
337
  circleView.isHidden = true
341
338
  overlayViews.append(circleView)
342
- circleView.setMap(mapView)
339
+ if let mapView {
340
+ circleView.setMap(mapView)
341
+ }
343
342
  // 🔑 关键修复:不再调用 setupAllOverlayViews()
344
343
  return
345
344
  } else if let polylineView = subview as? PolylineView {
@@ -351,7 +350,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
351
350
  polylineView.alpha = 0
352
351
  polylineView.isHidden = true
353
352
  overlayViews.append(polylineView)
354
- polylineView.setMap(mapView)
353
+ if let mapView {
354
+ polylineView.setMap(mapView)
355
+ }
355
356
  // 🔑 关键修复:不再调用 setupAllOverlayViews()
356
357
  return
357
358
  } else if let polygonView = subview as? PolygonView {
@@ -363,7 +364,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
363
364
  polygonView.alpha = 0
364
365
  polygonView.isHidden = true
365
366
  overlayViews.append(polygonView)
366
- polygonView.setMap(mapView)
367
+ if let mapView {
368
+ polygonView.setMap(mapView)
369
+ }
367
370
  // 🔑 关键修复:不再调用 setupAllOverlayViews()
368
371
  return
369
372
  } else if let heatMapView = subview as? HeatMapView {
@@ -375,7 +378,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
375
378
  heatMapView.alpha = 0
376
379
  heatMapView.isHidden = true
377
380
  overlayViews.append(heatMapView)
378
- heatMapView.setMap(mapView)
381
+ if let mapView {
382
+ heatMapView.setMap(mapView)
383
+ }
379
384
  // 🔑 关键修复:不再调用 setupAllOverlayViews()
380
385
  return
381
386
  } else if let multiPointView = subview as? MultiPointView {
@@ -387,7 +392,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
387
392
  multiPointView.alpha = 0
388
393
  multiPointView.isHidden = true
389
394
  overlayViews.append(multiPointView)
390
- multiPointView.setMap(mapView)
395
+ if let mapView {
396
+ multiPointView.setMap(mapView)
397
+ }
391
398
  // 🔑 关键修复:不再调用 setupAllOverlayViews()
392
399
  return
393
400
  } else if let clusterView = subview as? ClusterView {
@@ -399,7 +406,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
399
406
  clusterView.alpha = 0
400
407
  clusterView.isHidden = true
401
408
  overlayViews.append(clusterView)
402
- clusterView.setMap(mapView)
409
+ if let mapView {
410
+ clusterView.setMap(mapView)
411
+ }
403
412
  // 🔑 关键修复:不再调用 setupAllOverlayViews()
404
413
  return
405
414
  }
@@ -419,17 +428,17 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
419
428
  // MarkerView 内部的 willMove(toSuperview: nil) 会处理 annotation 的移除
420
429
  } else if let circleView = subview as? CircleView {
421
430
  overlayViews.removeAll { $0 === circleView }
422
- if let circle = circleView.circle {
431
+ if let mapView, let circle = circleView.circle {
423
432
  mapView.remove(circle)
424
433
  }
425
434
  } else if let polylineView = subview as? PolylineView {
426
435
  overlayViews.removeAll { $0 === polylineView }
427
- if let polyline = polylineView.polyline {
436
+ if let mapView, let polyline = polylineView.polyline {
428
437
  mapView.remove(polyline)
429
438
  }
430
439
  } else if let polygonView = subview as? PolygonView {
431
440
  overlayViews.removeAll { $0 === polygonView }
432
- if let polygon = polygonView.polygon {
441
+ if let mapView, let polygon = polygonView.polygon {
433
442
  mapView.remove(polygon)
434
443
  }
435
444
  } else if let heatMapView = subview as? HeatMapView {
@@ -447,6 +456,10 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
447
456
  * 设置默认配置
448
457
  */
449
458
  private func setupDefaultConfig() {
459
+ guard let uiManager else {
460
+ return
461
+ }
462
+
450
463
  uiManager.setMapType(0)
451
464
  uiManager.setShowsScale(showsScale)
452
465
  uiManager.setShowsCompass(showsCompass)
@@ -462,6 +475,12 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
462
475
  * 在 Props 更新时调用
463
476
  */
464
477
  func applyProps() {
478
+ ensureMapViewIfReady()
479
+ guard let uiManager else {
480
+ updateAppleMapStyle()
481
+ return
482
+ }
483
+
465
484
  uiManager.setMapType(mapType)
466
485
 
467
486
  // 如果有初始位置,设置相机位置
@@ -479,6 +498,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
479
498
  uiManager.setShowsTraffic(showsTraffic)
480
499
  uiManager.setShowsBuildings(showsBuildings)
481
500
  uiManager.setShowsIndoorMap(showsIndoorMap)
501
+ if let customMapStyleData {
502
+ uiManager.setCustomMapStyle(customMapStyleData)
503
+ }
482
504
 
483
505
  // 更新苹果地图样式
484
506
  updateAppleMapStyle()
@@ -573,33 +595,38 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
573
595
  // MARK: - 缩放控制
574
596
 
575
597
  func setMaxZoom(_ maxZoom: Double) {
576
- cameraManager.setMaxZoomLevel(CGFloat(maxZoom))
598
+ cameraManager?.setMaxZoomLevel(CGFloat(maxZoom))
577
599
  }
578
600
 
579
601
  func setMinZoom(_ minZoom: Double) {
580
- cameraManager.setMinZoomLevel(CGFloat(minZoom))
602
+ cameraManager?.setMinZoomLevel(CGFloat(minZoom))
581
603
  }
582
604
 
583
605
  // MARK: - 相机控制
584
606
 
585
607
  func moveCamera(position: [String: Any], duration: Int) {
586
- cameraManager.moveCamera(position: position, duration: duration)
608
+ ensureMapViewIfReady()
609
+ cameraManager?.moveCamera(position: position, duration: duration)
587
610
  }
588
611
 
589
612
  func getLatLng(point: [String: Double]) -> [String: Double] {
590
- return cameraManager.getLatLng(point: point)
613
+ ensureMapViewIfReady()
614
+ return cameraManager?.getLatLng(point: point) ?? [:]
591
615
  }
592
616
 
593
617
  func setCenter(center: [String: Double], animated: Bool) {
594
- cameraManager.setCenter(center: center, animated: animated)
618
+ ensureMapViewIfReady()
619
+ cameraManager?.setCenter(center: center, animated: animated)
595
620
  }
596
621
 
597
622
  func setZoom(zoom: Double, animated: Bool) {
598
- cameraManager.setZoomLevel(zoom: CGFloat(zoom), animated: animated)
623
+ ensureMapViewIfReady()
624
+ cameraManager?.setZoomLevel(zoom: CGFloat(zoom), animated: animated)
599
625
  }
600
626
 
601
627
  func getCameraPosition() -> [String: Any] {
602
- return cameraManager.getCameraPosition()
628
+ ensureMapViewIfReady()
629
+ return cameraManager?.getCameraPosition() ?? [:]
603
630
  }
604
631
 
605
632
 
@@ -607,17 +634,17 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
607
634
 
608
635
  func setShowsTraffic(_ show: Bool) {
609
636
  showsTraffic = show
610
- uiManager.setShowsTraffic(show)
637
+ uiManager?.setShowsTraffic(show)
611
638
  }
612
639
 
613
640
  func setShowsBuildings(_ show: Bool) {
614
641
  showsBuildings = show
615
- uiManager.setShowsBuildings(show)
642
+ uiManager?.setShowsBuildings(show)
616
643
  }
617
644
 
618
645
  func setShowsIndoorMap(_ show: Bool) {
619
646
  showsIndoorMap = show
620
- uiManager.setShowsIndoorMap(show)
647
+ uiManager?.setShowsIndoorMap(show)
621
648
  }
622
649
 
623
650
  /**
@@ -628,18 +655,18 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
628
655
  customMapStyleData = styleData
629
656
  // 如果地图已加载,立即应用样式
630
657
  if isMapLoaded {
631
- uiManager.setCustomMapStyle(styleData)
658
+ uiManager?.setCustomMapStyle(styleData)
632
659
  }
633
660
  }
634
661
 
635
662
  func setFollowUserLocation(_ follow: Bool) {
636
663
  followUserLocation = follow
637
- uiManager.setShowsUserLocation(showsUserLocation, followUser: follow)
664
+ uiManager?.setShowsUserLocation(showsUserLocation, followUser: follow)
638
665
  }
639
666
 
640
667
  func setShowsUserLocation(_ show: Bool) {
641
668
  showsUserLocation = show
642
- uiManager.setShowsUserLocation(show, followUser: followUserLocation)
669
+ uiManager?.setShowsUserLocation(show, followUser: followUserLocation)
643
670
  if show {
644
671
  applyUserLocationStyle()
645
672
  }
@@ -648,7 +675,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
648
675
  func setUserLocationRepresentation(_ config: [String: Any]) {
649
676
  userLocationRepresentation = config
650
677
  if showsUserLocation {
651
- uiManager.setUserLocationRepresentation(config)
678
+ uiManager?.setUserLocationRepresentation(config)
652
679
  }
653
680
  }
654
681
 
@@ -657,7 +684,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
657
684
  */
658
685
  private func applyUserLocationStyle() {
659
686
  guard let config = userLocationRepresentation else { return }
660
- uiManager.setUserLocationRepresentation(config)
687
+ uiManager?.setUserLocationRepresentation(config)
661
688
  }
662
689
 
663
690
 
@@ -665,6 +692,10 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
665
692
  // MARK: - 地图切换逻辑
666
693
 
667
694
  func handleMapviewRegionChange(mapView: UIView) {
695
+ guard self.mapView != nil else {
696
+ return
697
+ }
698
+
668
699
  if !enableWorldMapSwitch {
669
700
  return
670
701
  }
@@ -707,12 +738,15 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
707
738
  }
708
739
 
709
740
  func performSwitching() {
741
+ guard let mapView else {
742
+ return
743
+ }
710
744
 
711
745
  self.isSwitching = true
712
746
 
713
- let isGaodeCurrentlyVisible = !self.mapView.isHidden
747
+ let isGaodeCurrentlyVisible = !mapView.isHidden
714
748
 
715
- self.mapView.isHidden = isGaodeCurrentlyVisible
749
+ mapView.isHidden = isGaodeCurrentlyVisible
716
750
  self.appleMapView.isHidden = !isGaodeCurrentlyVisible
717
751
 
718
752
  if !isGaodeCurrentlyVisible {
@@ -720,15 +754,15 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
720
754
  let region = self.MARegionForMKRegion(mkRegion: self.appleMapView.region)
721
755
  // 简单的合法性检查
722
756
  if region.span.latitudeDelta > 0 && region.span.longitudeDelta > 0 {
723
- self.mapView.region = region
757
+ mapView.region = region
724
758
  }
725
- self.mapView.centerCoordinate = self.appleMapView.centerCoordinate
726
- self.mapView.rotationDegree = CGFloat(self.appleMapView.camera.heading)
759
+ mapView.centerCoordinate = self.appleMapView.centerCoordinate
760
+ mapView.rotationDegree = CGFloat(self.appleMapView.camera.heading)
727
761
  } else {
728
762
  // 切换到苹果 (Gaode -> Apple)
729
- let gaodeRegion = self.mapView.region
730
- let gaodeCenter = self.mapView.centerCoordinate
731
- let gaodeHeading = self.mapView.rotationDegree
763
+ let gaodeRegion = mapView.region
764
+ let gaodeCenter = mapView.centerCoordinate
765
+ let gaodeHeading = mapView.rotationDegree
732
766
 
733
767
 
734
768
  // 1. 设置 Region
@@ -789,6 +823,11 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
789
823
  saveSnapshot(image: image, completion: completion)
790
824
  return
791
825
  }
826
+
827
+ guard let mapView else {
828
+ completion(nil, NSError(domain: "ExpoGaodeMap", code: -2, userInfo: [NSLocalizedDescriptionKey: "Map view is not initialized yet"]))
829
+ return
830
+ }
792
831
 
793
832
  // 高德地图:使用新的异步 API (takeSnapshotInRect:withCompletionBlock:)
794
833
  mapView.takeSnapshot(in: bounds) { [weak self] (image, state) in
@@ -860,6 +899,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
860
899
  throttleTimer?.invalidate()
861
900
  throttleTimer = nil
862
901
  pendingCameraMoveData = nil
902
+ if let privacyObserver {
903
+ NotificationCenter.default.removeObserver(privacyObserver)
904
+ }
863
905
 
864
906
  // 清理代理,停止接收回调
865
907
  mapView?.delegate = nil
@@ -887,6 +929,47 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
887
929
  cameraManager = nil
888
930
  uiManager = nil
889
931
  }
932
+
933
+ @objc
934
+ private func handlePrivacyStatusChanged() {
935
+ ensureMapViewIfReady()
936
+ applyProps()
937
+ setupAllOverlayViews()
938
+ }
939
+
940
+ private func ensureMapViewIfReady() {
941
+ guard mapView == nil, GaodeMapPrivacyManager.isReady else {
942
+ return
943
+ }
944
+
945
+ GaodeMapPrivacyManager.applyPrivacyState()
946
+
947
+ let resolvedMapView = MAMapView(frame: bounds)
948
+ resolvedMapView.frame = bounds
949
+ resolvedMapView.delegate = self
950
+ resolvedMapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
951
+
952
+ mapView = resolvedMapView
953
+ super.addSubview(resolvedMapView)
954
+
955
+ cameraManager = CameraManager(mapView: resolvedMapView)
956
+ uiManager = UIManager(mapView: resolvedMapView)
957
+ uiManager.onLocationChanged = { [weak self] latitude, longitude, accuracy in
958
+ self?.onLocation([
959
+ "latitude": latitude,
960
+ "longitude": longitude,
961
+ "accuracy": accuracy,
962
+ "timestamp": Date().timeIntervalSince1970 * 1000
963
+ ])
964
+ }
965
+
966
+ setupDefaultConfig()
967
+
968
+ let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
969
+ pinchGesture.delegate = self
970
+ resolvedMapView.addGestureRecognizer(pinchGesture)
971
+ self.pinchGesture = pinchGesture
972
+ }
890
973
  }
891
974
 
892
975
  // MARK: - AppleMapDelegate