Skip to content

Commit

Permalink
ios: fix unavailable mapView on initialization (#3477)
Browse files Browse the repository at this point in the history
  • Loading branch information
mfazekas authored May 7, 2024
1 parent dd71431 commit 9a9bc35
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 68 deletions.
34 changes: 24 additions & 10 deletions ios/RNMBX/RNMBXMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ open class RNMBXMapView: UIView {
}()

var _mapView: MapView! = nil
func createMapView() {
func createMapView() -> MapView {
if let mapViewImpl = mapViewImpl, let mapViewInstance = createAndAddMapViewImpl(mapViewImpl, self) {
_mapView = mapViewInstance
} else {
Expand All @@ -192,6 +192,7 @@ open class RNMBXMapView: UIView {
_mapView.gestures.delegate = self
setupEvents()
afterMapViewAdded()
return _mapView
}

func createAndAddMapViewImpl(_ impl: String, _ view: RNMBXMapView) -> MapView? {
Expand All @@ -203,17 +204,20 @@ open class RNMBXMapView: UIView {
}
}

@available(*, deprecated, renamed: "withMapView", message: "mapView can be nil if the map initialization has not finished, use withMapView instead")
public var mapView : MapView! {
get { return _mapView }
}

@available(*, deprecated, renamed: "withMapboxMap", message: "mapboxMap can be nil if the map initialization has not finished, use withMapboxMap instead")
var mapboxMap: MapboxMap! {
get { _mapView.mapboxMap }
get { _mapView?.mapboxMap }
}

@objc public func addToMap(_ subview: UIView) {
withMapView {
withMapView { mapView in
if let mapComponent = subview as? RNMBXMapComponent {
let style = self.mapView.mapboxMap.style
let style = mapView.mapboxMap.style
var addToMap = false
if mapComponent.waitForStyleLoad() {
if (self.styleLoaded) {
Expand Down Expand Up @@ -303,7 +307,7 @@ open class RNMBXMapView: UIView {

// MARK: - React Native properties
let changes : PropertyChanges<RNMBXMapView> = PropertyChanges()
var mapViewWaiters : [()->Void] = []
var mapViewWaiters : [(_: MapView)->Void] = []

enum Property : String {
case projection
Expand Down Expand Up @@ -363,14 +367,24 @@ open class RNMBXMapView: UIView {
changes.add(name: property.rawValue, update: property.apply)
}

func withMapView(callback: @escaping () -> Void) {
if _mapView != nil {
callback()
func withMapView(callback: @escaping (_: MapView) -> Void) {
if let mapView = _mapView {
callback(mapView)
} else {
mapViewWaiters.append(callback)
}
}

func withMapboxMap(callback: @escaping (_: MapboxMap) -> Void) {
if let mapboxMap = _mapView?.mapboxMap {
callback(mapboxMap)
} else {
mapViewWaiters.append { mapView in
callback(mapView.mapboxMap)
}
}
}

var projection: StyleProjection?

@objc public func setReactProjection(_ value: String?) {
Expand Down Expand Up @@ -698,9 +712,9 @@ open class RNMBXMapView: UIView {

@objc override public func didSetProps(_ props: [String]) {
if (_mapView == nil) {
createMapView()
let view = createMapView()

mapViewWaiters.forEach { $0() }
mapViewWaiters.forEach { $0(view) }
mapViewWaiters.removeAll()
}
changes.apply(self)
Expand Down
94 changes: 36 additions & 58 deletions ios/RNMBX/RNMBXMapViewManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,6 @@ open class RNMBXMapViewManager: RCTViewManager {
}
}

// MARK: helpers

extension RNMBXMapViewManager {
static func withMapboxMap(
_ view: RNMBXMapView,
name: String,
rejecter: @escaping RCTPromiseRejectBlock,
fn: @escaping (_: MapboxMap) -> Void) -> Void
{
guard let mapboxMap = view.mapboxMap else {
RNMBXLogError("MapboxMap is not yet available");
rejecter(name, "Map not loaded yet", nil)
return;
}

fn(mapboxMap)
}
}

// MARK: - react methods

extension RNMBXMapViewManager {
Expand Down Expand Up @@ -76,23 +57,23 @@ extension RNMBXMapViewManager {
}

@objc public static func getCenter(_ view: RNMBXMapView, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
withMapboxMap(view, name: "getCenter", rejecter:rejecter) { map in
resolver(["center": [
map.cameraState.center.longitude,
map.cameraState.center.latitude
]])
}
view.withMapboxMap { map in
resolver(["center": [
map.cameraState.center.longitude,
map.cameraState.center.latitude
]])
}
}

@objc public static func getCoordinateFromView(
_ view: RNMBXMapView,
atPoint point: CGPoint,
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) {
withMapboxMap(view, name: "getCoordinateFromView", rejecter:rejecter) { map in
let coordinates = map.coordinate(for: point)
resolver(["coordinateFromView": [coordinates.longitude, coordinates.latitude]])
}
view.withMapboxMap { map in
let coordinates = map.coordinate(for: point)
resolver(["coordinateFromView": [coordinates.longitude, coordinates.latitude]])
}

}

Expand All @@ -101,12 +82,11 @@ extension RNMBXMapViewManager {
atCoordinate coordinate: [NSNumber],
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) {
withMapboxMap(view, name: "getPointInView", rejecter:rejecter) { map in
let coordinate = CLLocationCoordinate2DMake(coordinate[1].doubleValue, coordinate[0].doubleValue)
let point = map.point(for: coordinate)
resolver(["pointInView": [(point.x), (point.y)]])
}

view.withMapboxMap { map in
let coordinate = CLLocationCoordinate2DMake(coordinate[1].doubleValue, coordinate[0].doubleValue)
let point = map.point(for: coordinate)
resolver(["pointInView": [(point.x), (point.y)]])
}
}

@objc public static func setHandledMapChangedEvents(
Expand All @@ -124,10 +104,9 @@ extension RNMBXMapViewManager {
_ view: RNMBXMapView,
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) {
withMapboxMap(view, name: "getZoom", rejecter:rejecter) { map in
resolver(["zoom": map.cameraState.zoom])
}

view.withMapboxMap { map in
resolver(["zoom": map.cameraState.zoom])
}
}

@objc public static func getVisibleBounds(
Expand All @@ -148,27 +127,26 @@ extension RNMBXMapViewManager {
withLayerIDs layerIDs: [String]?,
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) -> Void {
withMapboxMap(view, name: "queryRenderedFeaturesAtPoint", rejecter:rejecter) { map in
let point = CGPoint(x: CGFloat(point[0].floatValue), y: CGFloat(point[1].floatValue))

logged("queryRenderedFeaturesAtPoint.option", rejecter: rejecter) {
let options = try RenderedQueryOptions(layerIds: (layerIDs ?? []).isEmpty ? nil : layerIDs, filter: filter?.asExpression())

map.queryRenderedFeatures(with: point, options: options) { result in
switch result {
case .success(let features):
resolver([
"data": ["type": "FeatureCollection", "features": features.compactMap { queriedFeature in
logged("queryRenderedFeaturesAtPoint.feature.toJSON") { try queriedFeature.feature.toJSON() }
}]
])
case .failure(let error):
rejecter("queryRenderedFeaturesAtPoint","failed to query features", error)
}
view.withMapboxMap { map in
let point = CGPoint(x: CGFloat(point[0].floatValue), y: CGFloat(point[1].floatValue))

logged("queryRenderedFeaturesAtPoint.option", rejecter: rejecter) {
let options = try RenderedQueryOptions(layerIds: (layerIDs ?? []).isEmpty ? nil : layerIDs, filter: filter?.asExpression())

map.queryRenderedFeatures(with: point, options: options) { result in
switch result {
case .success(let features):
resolver([
"data": ["type": "FeatureCollection", "features": features.compactMap { queriedFeature in
logged("queryRenderedFeaturesAtPoint.feature.toJSON") { try queriedFeature.feature.toJSON() }
}]
])
case .failure(let error):
rejecter("queryRenderedFeaturesAtPoint","failed to query features", error)
}
}
}

}
}
}

@objc public static func queryRenderedFeaturesInRect(
Expand Down

0 comments on commit 9a9bc35

Please sign in to comment.