From 1edc9604deef14fc3e9825c42e9511a054929230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Barbet?= Date: Sun, 16 Apr 2023 09:48:26 +0000 Subject: [PATCH 1/2] chore: setup swiftlint for iOS --- .github/workflows/on-push.yml | 3 +++ .swiftlint.yml | 14 ++++++++++++++ package.json | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 .swiftlint.yml diff --git a/.github/workflows/on-push.yml b/.github/workflows/on-push.yml index 4904af2c3..b0349ecea 100644 --- a/.github/workflows/on-push.yml +++ b/.github/workflows/on-push.yml @@ -30,6 +30,9 @@ jobs: - name: Install run: yarn install --network-timeout 1000000 + - name: SwiftLint + run: swiftlint lint --config .swiftlint.yml ios/**/*.swift + - name: Lint run: yarn lint diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 000000000..822e2921a --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,14 @@ +opt_in_rules: + - vertical_whitespace_between_cases + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - vertical_parameter_alignment_on_call + - operator_usage_whitespace + - redundant_type_annotation + +excluded: + # Exclude `RCTMGLStyle.swift` because it is automatically generated from "RCTMGLStyle.swift.ejs" + - ios/RCTMGL-v10/RCTMGLStyle.swift + +indentation: 2 +vertical_whitespace_opening_braces: true diff --git a/package.json b/package.json index af7c6a061..020634d00 100644 --- a/package.json +++ b/package.json @@ -48,10 +48,11 @@ "unittest:single": "yarn jest --testNamePattern", "lint": "yarn eslint .", "lint:fix": "yarn eslint . --fix", + "lint:plugin": "yarn eslint plugin/src/*", + "lint:swift": "swiftlint lint --fix --format --config .swiftlint.yml ios/**/*.swift", "type:check": "yarn tsc --noEmit", "test:plugin": "yarn expo-module test plugin", "build:plugin": "yarn tsc --build plugin", - "lint:plugin": "yarn eslint plugin/src/*", "build": "yarn bob build", "prepare": "yarn bob build && yarn husky install" }, From f905710c170e1430144732b0ec874a2b2ed76394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Barbet?= Date: Sun, 16 Apr 2023 09:48:38 +0000 Subject: [PATCH 2/2] chore: lint all swift files --- ios/RCTMGL-v10/CustomHttpHeaders.swift | 8 +- ios/RCTMGL-v10/MGLModule.swift | 41 +- ios/RCTMGL-v10/MGLSnapshotModule.swift | 44 +- ios/RCTMGL-v10/RCMTGLImage.swift | 49 +- ios/RCTMGL-v10/RCMTGLImageManager.swift | 3 +- ios/RCTMGL-v10/RCTLog.swift | 12 +- ios/RCTMGL-v10/RCTMGLAtmosphere.swift | 30 +- ios/RCTMGL-v10/RCTMGLAtmosphereManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLBackgroundLayer.swift | 15 +- .../RCTMGLBackgroundLayerManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLCallout.swift | 3 +- ios/RCTMGL-v10/RCTMGLCalloutManager.swift | 18 +- ios/RCTMGL-v10/RCTMGLCamera.swift | 236 ++++---- ios/RCTMGL-v10/RCTMGLCameraManager.swift | 18 +- ios/RCTMGL-v10/RCTMGLCircleLayer.swift | 15 +- ios/RCTMGL-v10/RCTMGLCircleLayerManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLEvent.swift | 76 ++- ios/RCTMGL-v10/RCTMGLFeatureUtils.swift | 47 +- .../RCTMGLFillExtrusionLayerManager.swift | 20 +- .../RCTMGLFillExtrustionLayer.swift | 14 +- ios/RCTMGL-v10/RCTMGLFillLayer.swift | 18 +- ios/RCTMGL-v10/RCTMGLFillLayerManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLHeatmapLayer.swift | 20 +- .../RCTMGLHeatmapLayetManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLImageQueue.swift | 89 ++- ios/RCTMGL-v10/RCTMGLImageSource.swift | 25 +- ios/RCTMGL-v10/RCTMGLImages.swift | 148 +++-- ios/RCTMGL-v10/RCTMGLImagesManager.swift | 3 +- ios/RCTMGL-v10/RCTMGLInteractiveElement.swift | 36 +- ios/RCTMGL-v10/RCTMGLLayer.swift | 122 ++--- ios/RCTMGL-v10/RCTMGLLight.swift | 20 +- ios/RCTMGL-v10/RCTMGLLightManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLLineLayer.swift | 16 +- ios/RCTMGL-v10/RCTMGLLineLayerManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLLocationModule.swift | 204 ++++--- ios/RCTMGL-v10/RCTMGLLogging.swift | 59 +- ios/RCTMGL-v10/RCTMGLMapView.swift | 514 +++++++++--------- ios/RCTMGL-v10/RCTMGLMapViewManager.swift | 266 ++++----- ios/RCTMGL-v10/RCTMGLMarkerView.swift | 88 +-- ios/RCTMGL-v10/RCTMGLMarkerViewManager.swift | 4 +- ios/RCTMGL-v10/RCTMGLNativeUserLocation.swift | 16 +- .../RCTMGLNativeUserLocationManager.swift | 2 +- ios/RCTMGL-v10/RCTMGLOfflineModule.swift | 255 +++++---- ios/RCTMGL-v10/RCTMGLPointAnnotation.swift | 107 ++-- .../RCTMGLPointAnnotationManager.swift | 15 +- ios/RCTMGL-v10/RCTMGLRasterDemSource.swift | 36 +- ios/RCTMGL-v10/RCTMGLRasterLayer.swift | 16 +- ios/RCTMGL-v10/RCTMGLRasterLayerManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLRasterSource.swift | 32 +- .../RCTMGLRasterSourceManager.swift | 4 +- ios/RCTMGL-v10/RCTMGLShapeSource.swift | 120 ++-- ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift | 45 +- ios/RCTMGL-v10/RCTMGLSingletonLayer.swift | 24 +- ios/RCTMGL-v10/RCTMGLSkyLayer.swift | 15 +- ios/RCTMGL-v10/RCTMGLSkyLayerManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLSource.swift | 28 +- ios/RCTMGL-v10/RCTMGLStyleValue.swift | 233 ++++---- ios/RCTMGL-v10/RCTMGLSymbolLayer.swift | 17 +- ios/RCTMGL-v10/RCTMGLSymbolLayerManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLTerrain.swift | 38 +- ios/RCTMGL-v10/RCTMGLTerrainManager.swift | 20 +- ios/RCTMGL-v10/RCTMGLTileSource.swift | 5 +- ios/RCTMGL-v10/RCTMGLUtils.swift | 31 +- ios/RCTMGL-v10/RCTMGLVectorSource.swift | 39 +- .../RCTMGLVectorSourceManager.swift | 2 +- ios/RCTMGL-v10/RNMBImageUtils.swift | 9 +- 66 files changed, 1783 insertions(+), 1807 deletions(-) diff --git a/ios/RCTMGL-v10/CustomHttpHeaders.swift b/ios/RCTMGL-v10/CustomHttpHeaders.swift index af2393b31..1938a4a40 100644 --- a/ios/RCTMGL-v10/CustomHttpHeaders.swift +++ b/ios/RCTMGL-v10/CustomHttpHeaders.swift @@ -1,13 +1,13 @@ import MapboxMaps -class CustomHttpHeaders : HttpServiceInterceptorInterface { - static var shared : CustomHttpHeaders = { +class CustomHttpHeaders: HttpServiceInterceptorInterface { + static var shared: CustomHttpHeaders = { let headers = CustomHttpHeaders() headers.install() return headers }() - var customHeaders : [String:String] = [:] + var customHeaders: [String: String] = [:] func install() { HttpServiceFactory.getInstance().setInterceptorForInterceptor(self) @@ -27,7 +27,7 @@ class CustomHttpHeaders : HttpServiceInterceptorInterface { } func onDownload(forDownload download: DownloadOptions) -> DownloadOptions { - customHeaders.forEach {(key,value) in + customHeaders.forEach {(key, value) in download.request.headers[key] = value } return download diff --git a/ios/RCTMGL-v10/MGLModule.swift b/ios/RCTMGL-v10/MGLModule.swift index 1b599605e..600b8c249 100644 --- a/ios/RCTMGL-v10/MGLModule.swift +++ b/ios/RCTMGL-v10/MGLModule.swift @@ -2,17 +2,16 @@ import Foundation import MapboxMaps import MapboxMobileEvents - -let DEFAULT_SOURCE_ID = "composite"; +let DEFAULT_SOURCE_ID = "composite" @objc(MGLModule) -class MGLModule : NSObject { - static var accessToken : String? - +class MGLModule: NSObject { + static var accessToken: String? + @objc func constantsToExport() -> [AnyHashable: Any]! { return [ - "MapboxV10":true, + "MapboxV10": true, "StyleURL": [ "Street": StyleURI.streets.rawValue, @@ -20,14 +19,14 @@ class MGLModule : NSObject { "Light": StyleURI.light.rawValue, "Dark": StyleURI.dark.rawValue, "Satellite": StyleURI.satellite.rawValue, - "SatelliteStreet": StyleURI.satelliteStreets.rawValue, + "SatelliteStreet": StyleURI.satelliteStreets.rawValue ], "OfflinePackDownloadState": [ "Inactive": RCTMGLOfflineModule.State.inactive.rawValue, "Active": RCTMGLOfflineModule.State.active.rawValue, "Complete": RCTMGLOfflineModule.State.complete.rawValue, - "Unknown": RCTMGLOfflineModule.State.unknown.rawValue, + "Unknown": RCTMGLOfflineModule.State.unknown.rawValue ], "StyleSource": ["DefaultSourceID": DEFAULT_SOURCE_ID], @@ -35,7 +34,7 @@ class MGLModule : NSObject { [ "Bevel": LineJoin.bevel.rawValue, "Round": LineJoin.round.rawValue, - "Miter": LineJoin.miter.rawValue, + "Miter": LineJoin.miter.rawValue ], "LocationCallbackName": ["Update": RCT_MAPBOX_USER_LOCATION_UPDATE], @@ -48,16 +47,16 @@ class MGLModule : NSObject { ], "EventTypes": [ - "RegionIsChanging" : RCTMGLEvent.EventType.regionIsChanging.rawValue, - "RegionDidChange" : RCTMGLEvent.EventType.regionDidChange.rawValue, - "CameraChanged" : RCTMGLEvent.EventType.cameraChanged.rawValue, - "MapIdle" : RCTMGLEvent.EventType.mapIdle.rawValue, + "RegionIsChanging": RCTMGLEvent.EventType.regionIsChanging.rawValue, + "RegionDidChange": RCTMGLEvent.EventType.regionDidChange.rawValue, + "CameraChanged": RCTMGLEvent.EventType.cameraChanged.rawValue, + "MapIdle": RCTMGLEvent.EventType.mapIdle.rawValue, "WillStartLoadingMap": RCTMGLEvent.EventType.willStartLoadingMap.rawValue, "DidFinishLoadingStyle": RCTMGLEvent.EventType.didFinishLoadingStyle.rawValue, "DidFinishLoadingMap": RCTMGLEvent.EventType.didFinishLoadingMap.rawValue, "MapLoadingError": RCTMGLEvent.EventType.mapLoadingError.rawValue, - "DidFinishRenderingFrameFully": RCTMGLEvent.EventType.didFinishRenderingFully.rawValue, - "DidFinishRenderingFrame": RCTMGLEvent.EventType.didFinishRendering.rawValue, + "DidFinishRenderingFrameFully": RCTMGLEvent.EventType.didFinishRenderingFully.rawValue, + "DidFinishRenderingFrame": RCTMGLEvent.EventType.didFinishRendering.rawValue ], "OfflineCallbackName": [ @@ -66,20 +65,20 @@ class MGLModule : NSObject { ], "TileServers": ["Mapbox": "mapbox"] - ]; + ] } @objc static func requiresMainQueueSetup() -> Bool { - return true + return true } @objc func setAccessToken( - _ token: String, + _ token: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) { - MGLModule.accessToken = token - resolver(token) + MGLModule.accessToken = token + resolver(token) } @objc func addCustomHeader(_ headerName: String, forHeaderValue headerValue: String ) { @@ -89,7 +88,7 @@ class MGLModule : NSObject { @objc func removeCustomHeader(_ headerName: String) { CustomHttpHeaders.shared.customHeaders[headerName] = nil } - + @objc func setTelemetryEnabled(_ telemetryEnabled: Bool) { UserDefaults.mme_configuration().mme_isCollectionEnabled = telemetryEnabled } diff --git a/ios/RCTMGL-v10/MGLSnapshotModule.swift b/ios/RCTMGL-v10/MGLSnapshotModule.swift index e76e0bdda..ede2173c5 100644 --- a/ios/RCTMGL-v10/MGLSnapshotModule.swift +++ b/ios/RCTMGL-v10/MGLSnapshotModule.swift @@ -1,40 +1,41 @@ import MapboxMaps @objc(MGLSnapshotModule) -class MGLSnapshotModule : NSObject { +class MGLSnapshotModule: NSObject { @objc static func requiresMainQueueSetup() -> Bool { - return true + return true } - + @objc func takeSnap(_ jsOptions: [String: Any], - resolver:@escaping RCTPromiseResolveBlock, - rejecter:@escaping RCTPromiseRejectBlock + resolver: @escaping RCTPromiseResolveBlock, + rejecter: @escaping RCTPromiseRejectBlock ) { DispatchQueue.main.async { - logged("takeSnap", rejecter:rejecter) { + logged("takeSnap", rejecter: rejecter) { let snapshotterOptions = try self._getSnapshotterOptions(jsOptions) let snapshotter = Snapshotter(options: snapshotterOptions) let cameraOptions = try self._getCameraOptions(jsOptions, snapshotter) - + snapshotter.setCamera(to: cameraOptions) if let styleURL = jsOptions["styleURL"] as? String { - snapshotter.style.uri = StyleURI(rawValue:styleURL) + snapshotter.style.uri = StyleURI(rawValue: styleURL) } - var snapshotterReference : Snapshotter? = snapshotter + var snapshotterReference: Snapshotter? = snapshotter snapshotter.start(overlayHandler: nil, completion: { result in do { - switch (result) { + switch result { case .success(let image): guard let writeToDisk = jsOptions["writeToDisk"] as? NSNumber else { throw RCTMGLError.paramError("writeToDisk: is not a number") } - + let value = writeToDisk.boolValue ? RNMBImageUtils.createTempFile(image) : RNMBImageUtils.createBase64(image) _ = snapshotterReference snapshotterReference = nil resolver(value.absoluteString) + case .failure(let error): _ = snapshotterReference snapshotterReference = nil @@ -49,11 +50,11 @@ class MGLSnapshotModule : NSObject { } } - func _getCameraOptions(_ jsOptions: [String:Any], _ snaphotter: Snapshotter) throws -> CameraOptions { + func _getCameraOptions(_ jsOptions: [String: Any], _ snaphotter: Snapshotter) throws -> CameraOptions { guard let pitch = jsOptions["pitch"] as? NSNumber else { throw RCTMGLError.paramError("pitch: is not a number") } - + guard let zoomLevel = jsOptions["zoomLevel"] as? NSNumber else { throw RCTMGLError.paramError("zoomLevel: is not a number") } @@ -61,22 +62,21 @@ class MGLSnapshotModule : NSObject { guard let heading = jsOptions["heading"] as? NSNumber else { throw RCTMGLError.paramError("heading: is not a number") } - + if let centerCoordinateString = jsOptions["centerCoordinate"] as? String { guard let centerCoordinateData = centerCoordinateString.data(using: .utf8), let centerCoordinateGeometry = try JSONDecoder().decode(Feature.self, from: centerCoordinateData).geometry, case .point(let centerCoordinatePoint) = centerCoordinateGeometry else { throw RCTMGLError.paramError("centerCoordinate: bad format") } - + return CameraOptions(center: centerCoordinatePoint.coordinates, padding: nil, anchor: nil, zoom: zoomLevel.doubleValue, bearing: heading.doubleValue, pitch: pitch.doubleValue) - } - else if let bounds = jsOptions["bounds"] as? String { + } else if let bounds = jsOptions["bounds"] as? String { guard let boundsData = bounds.data(using: .utf8) else { throw RCTMGLError.paramError("bounds: bad format") } let boundsFeatures = try JSONDecoder().decode(FeatureCollection.self, from: boundsData).features - let coords : [CLLocationCoordinate2D] = try boundsFeatures.map { + let coords: [CLLocationCoordinate2D] = try boundsFeatures.map { guard case .point(let centerCoordinatePoint) = $0.geometry else { throw RCTMGLError.paramError("Invalid bounds geometry") } @@ -87,20 +87,20 @@ class MGLSnapshotModule : NSObject { throw RCTMGLError.paramError("neither centerCoordinate nor bounds provided") } } - - func _getSnapshotterOptions(_ jsOptions: [String:Any]) throws -> MapSnapshotOptions { + + func _getSnapshotterOptions(_ jsOptions: [String: Any]) throws -> MapSnapshotOptions { guard let width = jsOptions["width"] as? NSNumber, let height = jsOptions["height"] as? NSNumber else { throw RCTMGLError.paramError("width, height: is not a number") } - + let resourceOptions = ResourceOptions(accessToken: MGLModule.accessToken!) let mapSnapshotOptions = MapSnapshotOptions( size: CGSize(width: width.doubleValue, height: height.doubleValue), pixelRatio: 1.0, resourceOptions: resourceOptions ) - + return mapSnapshotOptions } } diff --git a/ios/RCTMGL-v10/RCMTGLImage.swift b/ios/RCTMGL-v10/RCMTGLImage.swift index 737263698..2694f2c77 100644 --- a/ios/RCTMGL-v10/RCMTGLImage.swift +++ b/ios/RCTMGL-v10/RCMTGLImage.swift @@ -1,27 +1,27 @@ import MapboxMaps -class RCTMGLImage : UIView { +class RCTMGLImage: UIView { @objc var name: String = "" - var image: UIImage? = nil - - var sdf: Bool? = nil + var image: UIImage? + + var sdf: Bool? var stretchX: [[NSNumber]] = [] var stretchY: [[NSNumber]] = [] - var content: [NSNumber]? = nil + var content: [NSNumber]? - weak var images: RCTMGLImageSetter? = nil { + weak var images: RCTMGLImageSetter? { didSet { DispatchQueue.main.async { self.setImage() } } } - weak var bridge : RCTBridge! = nil - - var reactSubviews : [UIView] = [] - + weak var bridge: RCTBridge! = nil + + var reactSubviews: [UIView] = [] + // MARK: - subview management - + @objc open override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { reactSubviews.insert(subview, at: atIndex) if reactSubviews.count > 1 { @@ -38,15 +38,15 @@ class RCTMGLImage : UIView { open override func removeReactSubview(_ subview: UIView!) { reactSubviews.removeAll(where: { $0 == subview }) } - + // MARK: - view shnapshot - + func changeImage(_ image: UIImage, name: String) { if let images = images { - let _ = images.addImage(name: name, image: image, sdf: sdf, stretchX:stretchX, stretchY:stretchY, content:content, log: "RCTMGLImage.addImage") + _ = images.addImage(name: name, image: image, sdf: sdf, stretchX: stretchX, stretchY: stretchY, content: content, log: "RCTMGLImage.addImage") } } - + func setImage() { if let image = _createViewSnapshot() { changeImage(image, name: name) @@ -60,9 +60,9 @@ class RCTMGLImage : UIView { let renderer = UIGraphicsImageRenderer(size: size) let image = renderer.image { context in UIColor.darkGray.setStroke() - context.stroke(CGRect(x: 0, y:0, width: 32, height: 32)) - UIColor(red: 158/255, green: 215/255, blue: 245/255, alpha: 1).setFill() - context.fill(CGRect(x: 2, y: 2, width: 30, height: 30)) + context.stroke(CGRect(x: 0, y: 0, width: 32, height: 32)) + UIColor(red: 158 / 255, green: 215 / 255, blue: 245 / 255, alpha: 1).setFill() + context.fill(CGRect(x: 2, y: 2, width: 30, height: 30)) } return image } @@ -71,19 +71,19 @@ class RCTMGLImage : UIView { } return _createViewSnapshot(view: reactSubviews[0]) } - + func _createViewSnapshot(view: UIView) -> UIImage? { guard view.bounds.size.width > 0 && view.bounds.size.height > 0 else { return nil } - + let roundUp = 4 - + let adjustedSize = CGSize( - width: ((Int(view.bounds.size.width)+roundUp-1)/roundUp)*roundUp, - height: ((Int(view.bounds.size.height)+roundUp-1)/roundUp)*roundUp + width: ((Int(view.bounds.size.width) + roundUp - 1) / roundUp) * roundUp, + height: ((Int(view.bounds.size.height) + roundUp - 1) / roundUp) * roundUp ) - + let renderer = UIGraphicsImageRenderer(size: adjustedSize) let image = renderer.image { context in view.layer.render(in: context.cgContext) @@ -91,4 +91,3 @@ class RCTMGLImage : UIView { return image } } - diff --git a/ios/RCTMGL-v10/RCMTGLImageManager.swift b/ios/RCTMGL-v10/RCMTGLImageManager.swift index 275478b2f..554554ca0 100644 --- a/ios/RCTMGL-v10/RCMTGLImageManager.swift +++ b/ios/RCTMGL-v10/RCMTGLImageManager.swift @@ -1,6 +1,5 @@ - @objc(RCTMGLImageManager) -class RCTMGLImageManager : RCTViewManager { +class RCTMGLImageManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true diff --git a/ios/RCTMGL-v10/RCTLog.swift b/ios/RCTMGL-v10/RCTLog.swift index e5d7817dd..70d64dbf9 100644 --- a/ios/RCTMGL-v10/RCTLog.swift +++ b/ios/RCTMGL-v10/RCTLog.swift @@ -1,19 +1,19 @@ -func RCTMGLLogError(_ message: String, _ file: String=#file, _ line: UInt=#line) { +func RCTMGLLogError(_ message: String, _ file: String = #file, _ line: UInt = #line) { RCTMGLSwiftLog.error(message, file: file, line: line) } -func RCTMGLLogWarn(_ message: String, _ file: String=#file, _ line: UInt=#line) { +func RCTMGLLogWarn(_ message: String, _ file: String = #file, _ line: UInt = #line) { RCTMGLSwiftLog.warn(message, file: file, line: line) } -func RCTMGLLogInfo(_ message: String, _ file: String=#file, _ line: UInt=#line) { +func RCTMGLLogInfo(_ message: String, _ file: String = #file, _ line: UInt = #line) { RCTMGLSwiftLog.info(message, file: file, line: line) } -func RCTMGLLog(_ message: String, _ file: String=#file, _ line: UInt=#line) { +func RCTMGLLog(_ message: String, _ file: String = #file, _ line: UInt = #line) { RCTMGLSwiftLog.log(message, file: file, line: line) } -func RCTMGLLogTrace(_ message: String, _ file: String=#file, _ line: UInt=#line) { +func RCTMGLLogTrace(_ message: String, _ file: String = #file, _ line: UInt = #line) { RCTMGLSwiftLog.trace(message, file: file, line: line) -} \ No newline at end of file +} diff --git a/ios/RCTMGL-v10/RCTMGLAtmosphere.swift b/ios/RCTMGL-v10/RCTMGLAtmosphere.swift index 45a1ad863..871f34505 100644 --- a/ios/RCTMGL-v10/RCTMGLAtmosphere.swift +++ b/ios/RCTMGL-v10/RCTMGLAtmosphere.swift @@ -1,9 +1,9 @@ import MapboxMaps @objc(RCTMGLAtmosphere) -class RCTMGLAtmosphere : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceConsumer { - var atmosphere : Atmosphere? = nil - +class RCTMGLAtmosphere: RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceConsumer { + var atmosphere: Atmosphere? + func makeAtmosphere() -> Atmosphere { return Atmosphere() } @@ -11,27 +11,27 @@ class RCTMGLAtmosphere : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceC func addToMap(_ map: RCTMGLMapView, style: Style) { self.map = map self.style = style - + let atmosphere = self.makeAtmosphere() self.atmosphere = atmosphere addStylesAndUpdate() } - + func removeFromMap(_ map: RCTMGLMapView) { self.map = nil - + guard let mapboxMap = map.mapboxMap else { return } - + let style = mapboxMap.style removeFromMap(map, style: style) } - + func waitForStyleLoad() -> Bool { return true } - + func removeFromMap(_ map: RCTMGLMapView, style: Style) { logged("RCTMGLAtmosphere.removeFromMap") { try style.removeAtmosphere() @@ -45,19 +45,19 @@ class RCTMGLAtmosphere : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceC super.addStylesAndUpdate() } - + override func addStyles() { - if let style : Style = self.style, + if let style: Style = self.style, let reactStyle = self.reactStyle { let styler = RCTMGLStyle(style: style) styler.bridge = self.bridge - + if var atmosphere = atmosphere { styler.atmosphereLayer( layer: &atmosphere, reactStyle: reactStyle, oldReactStyle: oldReactStyle, - applyUpdater: { (updater) in fatalError("Atmosphere: TODO - implement apply updater")}, + applyUpdater: { (_) in fatalError("Atmosphere: TODO - implement apply updater")}, isValid: { fatalError("Atmosphere: TODO - no isValid") } ) self.atmosphere = atmosphere @@ -66,8 +66,8 @@ class RCTMGLAtmosphere : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceC } } } - - override func apply(style : Style) throws { + + override func apply(style: Style) throws { if let atmosphere = atmosphere { try style.setAtmosphere(atmosphere) } diff --git a/ios/RCTMGL-v10/RCTMGLAtmosphereManager.swift b/ios/RCTMGL-v10/RCTMGLAtmosphereManager.swift index 8e19a97a1..7eaf78a1c 100644 --- a/ios/RCTMGL-v10/RCTMGLAtmosphereManager.swift +++ b/ios/RCTMGL-v10/RCTMGLAtmosphereManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLAtmosphereManager) class RCTMGLAtmosphereManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let atmosphere = RCTMGLAtmosphere() - //atmosphere.bridge = self.bridge - return atmosphere - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let atmosphere = RCTMGLAtmosphere() + // atmosphere.bridge = self.bridge + return atmosphere + } } diff --git a/ios/RCTMGL-v10/RCTMGLBackgroundLayer.swift b/ios/RCTMGL-v10/RCTMGLBackgroundLayer.swift index 919fd5442..19ae3b685 100644 --- a/ios/RCTMGL-v10/RCTMGLBackgroundLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLBackgroundLayer.swift @@ -5,7 +5,7 @@ class RCTMGLBackgroundLayer: RCTMGLLayer { typealias LayerType = BackgroundLayer override func makeLayer(style: Style) throws -> Layer { - let vectorSource : VectorSource = try self.layerWithSourceID(in: style) + let vectorSource: VectorSource = try self.layerWithSourceID(in: style) var layer = LayerType(id: self.id!) layer.sourceLayer = self.sourceLayerID layer.source = sourceID @@ -15,9 +15,9 @@ class RCTMGLBackgroundLayer: RCTMGLLayer { override func layerType() -> Layer.Type { return LayerType.self } - - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout BackgroundLayer) in + + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout BackgroundLayer) in if let styleLayer = self.styleLayer as? LayerType { layer = styleLayer } @@ -25,8 +25,8 @@ class RCTMGLBackgroundLayer: RCTMGLLayer { } override func addStyles() { - if let style : Style = self.style { - let styler = RCTMGLStyle(style: self.style!) + if let style: Style = self.style { + let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge if var styleLayer = self.styleLayer as? LayerType, let reactStyle = self.reactStyle { @@ -42,9 +42,8 @@ class RCTMGLBackgroundLayer: RCTMGLLayer { } } } - + func isAddedToMap() -> Bool { return true } - } diff --git a/ios/RCTMGL-v10/RCTMGLBackgroundLayerManager.swift b/ios/RCTMGL-v10/RCTMGLBackgroundLayerManager.swift index 1280880a3..d111fe6bc 100644 --- a/ios/RCTMGL-v10/RCTMGLBackgroundLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLBackgroundLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLBackgroundLayerManager) class RCTMGLBackgroundLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLBackgroundLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLBackgroundLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLCallout.swift b/ios/RCTMGL-v10/RCTMGLCallout.swift index 82e2ab7cc..50db5ce2c 100644 --- a/ios/RCTMGL-v10/RCTMGLCallout.swift +++ b/ios/RCTMGL-v10/RCTMGLCallout.swift @@ -1,3 +1,2 @@ -class RCTMGLCallout : UIView { - +class RCTMGLCallout: UIView { } diff --git a/ios/RCTMGL-v10/RCTMGLCalloutManager.swift b/ios/RCTMGL-v10/RCTMGLCalloutManager.swift index f957fb2c3..0b8fd31a1 100644 --- a/ios/RCTMGL-v10/RCTMGLCalloutManager.swift +++ b/ios/RCTMGL-v10/RCTMGLCalloutManager.swift @@ -2,13 +2,13 @@ import Foundation import MapboxMaps @objc(RCTMGLCalloutManager) -class RCTMGLCalloutManager : RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - return RCTMGLCallout() - } +class RCTMGLCalloutManager: RCTViewManager { + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + return RCTMGLCallout() + } } diff --git a/ios/RCTMGL-v10/RCTMGLCamera.swift b/ios/RCTMGL-v10/RCTMGLCamera.swift index c4c20d015..71f77d350 100644 --- a/ios/RCTMGL-v10/RCTMGLCamera.swift +++ b/ios/RCTMGL-v10/RCTMGLCamera.swift @@ -2,10 +2,10 @@ import Foundation import MapboxMaps import Turf -protocol RCTMGLMapComponent : class { +protocol RCTMGLMapComponent: class { func addToMap(_ map: RCTMGLMapView, style: Style) func removeFromMap(_ map: RCTMGLMapView) - + func waitForStyleLoad() -> Bool } @@ -21,55 +21,58 @@ struct CameraUpdateItem { var camera: CameraOptions var mode: CameraMode var duration: TimeInterval? - + func execute(map: RCTMGLMapView, cameraAnimator: inout BasicCameraAnimator?) { logged("CameraUpdateItem.execute") { if let center = camera.center { try center.validate() } switch mode { - case .flight: - map.camera.fly(to: camera, duration: duration) - case .ease: - map.camera.ease(to: camera, duration: duration ?? 0, curve: .easeInOut, completion: nil) - case .linear: - map.camera.ease(to: camera, duration: duration ?? 0, curve: .linear, completion: nil) - default: - map.mapboxMap.setCamera(to: camera) + case .flight: + map.camera.fly(to: camera, duration: duration) + + case .ease: + map.camera.ease(to: camera, duration: duration ?? 0, curve: .easeInOut, completion: nil) + + case .linear: + map.camera.ease(to: camera, duration: duration ?? 0, curve: .linear, completion: nil) + + default: + map.mapboxMap.setCamera(to: camera) } } } } class CameraUpdateQueue { - var queue: [CameraUpdateItem] = []; - + var queue: [CameraUpdateItem] = [] + func dequeue() -> CameraUpdateItem? { guard !queue.isEmpty else { return nil } return queue.removeFirst() } - + func enqueue(stop: CameraUpdateItem) { queue.append(stop) } - + func execute(map: RCTMGLMapView, cameraAnimator: inout BasicCameraAnimator?) { guard let stop = dequeue() else { return } - + stop.execute(map: map, cameraAnimator: &cameraAnimator) } } -open class RCTMGLMapComponentBase : UIView, RCTMGLMapComponent { +open class RCTMGLMapComponentBase: UIView, RCTMGLMapComponent { private weak var _map: RCTMGLMapView! = nil private var _mapCallbacks: [(RCTMGLMapView) -> Void] = [] - - weak var map : RCTMGLMapView? { - return _map; + + weak var map: RCTMGLMapView? { + return _map } func withMapView(_ callback: @escaping (_ mapView: MapView) -> Void) { @@ -85,89 +88,89 @@ open class RCTMGLMapComponentBase : UIView, RCTMGLMapComponent { _mapCallbacks.append(callback) } } - + func waitForStyleLoad() -> Bool { return false } - + func addToMap(_ map: RCTMGLMapView, style: Style) { _mapCallbacks.forEach { callback in - callback(map) + callback(map) } _mapCallbacks = [] _map = map } - + func removeFromMap(_ map: RCTMGLMapView) { _mapCallbacks = [] _map = nil } } -class RCTMGLCamera : RCTMGLMapComponentBase { +class RCTMGLCamera: RCTMGLMapComponentBase { var cameraAnimator: BasicCameraAnimator? let cameraUpdateQueue = CameraUpdateQueue() - + // MARK: React properties - + @objc var animationDuration: NSNumber? - + @objc var animationMode: NSString? - + @objc var defaultStop: [String: Any]? - - @objc var followUserLocation : Bool = false { + + @objc var followUserLocation = false { didSet { _updateCameraFromTrackingMode() } } - + @objc var followUserMode: String? { didSet { _updateCameraFromTrackingMode() } } - + @objc var followZoomLevel: NSNumber? { didSet { _updateCameraFromTrackingMode() } } - + @objc var followPitch: NSNumber? { didSet { _updateCameraFromTrackingMode() } } - + @objc var followHeading: NSNumber? { didSet { _updateCameraFromTrackingMode() } } - + @objc var followPadding: NSDictionary? { didSet { _updateCameraFromTrackingMode() } } - + @objc var maxZoomLevel: NSNumber? { didSet { _updateMaxBounds() } } - + @objc var minZoomLevel: NSNumber? { didSet { _updateMaxBounds() } } - - @objc var onUserTrackingModeChange: RCTBubblingEventBlock? = nil - + + @objc var onUserTrackingModeChange: RCTBubblingEventBlock? + @objc var stop: [String: Any]? { didSet { _updateCamera() } } - + @objc var maxBounds: String? { didSet { if let maxBounds = maxBounds { @@ -180,27 +183,27 @@ class RCTMGLCamera : RCTMGLMapComponentBase { _updateMaxBounds() } } - var maxBoundsFeature : FeatureCollection? = nil - + var maxBoundsFeature: FeatureCollection? + // MARK: Update methods func _updateCameraFromJavascript() { guard !followUserLocation else { return } - + guard let stop = stop else { return } - + /* - V10 TODO - if let map = map, map.userTrackingMode != .none { - map.userTrackingMode = .none - } - */ + V10 TODO + if let map = map, map.userTrackingMode != .none { + map.userTrackingMode = .none + } + */ - if let stops = stop["stops"] as? [[String:Any]] { + if let stops = stop["stops"] as? [[String: Any]] { stops.forEach { if let stop = toUpdateItem(stop: $0) { cameraUpdateQueue.enqueue(stop: stop) @@ -216,18 +219,18 @@ class RCTMGLCamera : RCTMGLMapComponentBase { cameraUpdateQueue.execute(map: map, cameraAnimator: &cameraAnimator) } } - + func _disableUserTracking(_ map: MapView) { map.viewport.idle() } - - func _toCoordinateBounds(_ bounds: FeatureCollection) throws -> CoordinateBounds { + + func _toCoordinateBounds(_ bounds: FeatureCollection) throws -> CoordinateBounds { guard bounds.features.count == 2 else { throw RCTMGLError.paramError("Expected two Points in FeatureColletion") } let swFeature = bounds.features[0] let neFeature = bounds.features[1] - + guard case let .point(sw) = swFeature.geometry, case let .point(ne) = neFeature.geometry else { throw RCTMGLError.paramError("Expected two Points in FeatureColletion") @@ -235,11 +238,11 @@ class RCTMGLCamera : RCTMGLMapComponentBase { return CoordinateBounds(southwest: sw.coordinates, northeast: ne.coordinates) } - + func _updateMaxBounds() { withMapView { map in var options = CameraBoundsOptions() - + if let maxBounds = self.maxBoundsFeature { logged("RCTMGLCamera._updateMaxBounds._toCoordinateBounds") { options.bounds = try self._toCoordinateBounds(maxBounds) @@ -289,57 +292,60 @@ class RCTMGLCamera : RCTMGLMapComponentBase { switch userTrackingMode { case .none: Logger.assert("RCTMGLCamera, userTrackingModes should not be none here") + case .compass: followOptions.bearing = FollowPuckViewportStateBearing.heading trackingModeChanged = true + case .course: followOptions.bearing = FollowPuckViewportStateBearing.course trackingModeChanged = true + case .normal: followOptions.bearing = nil trackingModeChanged = true } - + if let onUserTrackingModeChange = self.onUserTrackingModeChange { - if (trackingModeChanged) { + if trackingModeChanged { let event = RCTMGLEvent(type: .onUserTrackingModeChange, payload: ["followUserMode": self.followUserMode ?? "normal", "followUserLocation": self.followUserLocation]) onUserTrackingModeChange(event.toJSON()) } } - + var _camera = CameraOptions() - + if let zoom = self.followZoomLevel as? CGFloat { - if (zoom >= 0.0) { + if zoom >= 0.0 { _camera.zoom = zoom followOptions.zoom = zoom } } - + if let followPitch = self.followPitch as? CGFloat { - if (followPitch >= 0.0) { + if followPitch >= 0.0 { _camera.pitch = followPitch followOptions.pitch = followPitch } } else if let stopPitch = self.stop?["pitch"] as? CGFloat { - if (stopPitch >= 0.0) { + if stopPitch >= 0.0 { _camera.pitch = stopPitch followOptions.pitch = stopPitch } } else { followOptions.pitch = nil } - + if let followHeading = self.followHeading as? CGFloat { - if (followHeading >= 0.0) { + if followHeading >= 0.0 { _camera.bearing = followHeading } } else if let stopHeading = self.stop?["heading"] as? CGFloat { - if (stopHeading >= 0.0) { + if stopHeading >= 0.0 { _camera.bearing = stopHeading } } - + if let padding = self.followPadding { let edgeInsets = UIEdgeInsets( top: padding["paddingTop"] as? Double ?? 0, @@ -349,31 +355,31 @@ class RCTMGLCamera : RCTMGLMapComponentBase { ) followOptions.padding = edgeInsets } - + let followState = map.viewport.makeFollowPuckViewportState(options: followOptions) - + map.viewport.transition(to: followState) map.viewport.addStatusObserver(self) map.mapboxMap.setCamera(to: _camera) } } - + private func toUpdateItem(stop: [String: Any]) -> CameraUpdateItem? { var zoom: CGFloat? if let z = stop["zoom"] as? Double { zoom = CGFloat(z) } - + var pitch: CGFloat? if let p = stop["pitch"] as? Double { pitch = CGFloat(p) } - + var heading: CLLocationDirection? if let h = stop["heading"] as? Double { heading = CLLocationDirection(h) } - + let padding = UIEdgeInsets( top: stop["paddingTop"] as? Double ?? 0, left: stop["paddingLeft"] as? Double ?? 0, @@ -383,41 +389,43 @@ class RCTMGLCamera : RCTMGLMapComponentBase { var center: LocationCoordinate2D? if let feature: String = stop["centerCoordinate"] as? String { - - let centerFeature : Turf.Feature? = logged("RCTMGLCamera.toUpdateItem.decode.cc") { try + let centerFeature: Turf.Feature? = logged("RCTMGLCamera.toUpdateItem.decode.cc") { try JSONDecoder().decode(Turf.Feature.self, from: feature.data(using: .utf8)!) } - + switch centerFeature?.geometry { case .point(let centerPoint): center = centerPoint.coordinates + default: Logger.log(level: .error, message: "RCTMGLCamera.toUpdateItem: Unexpected geometry: \(String(describing: centerFeature?.geometry))") return nil } } else if let feature: String = stop["bounds"] as? String { - let collection : Turf.FeatureCollection? = logged("RCTMGLCamera.toUpdateItem.decode.bound") { try + let collection: Turf.FeatureCollection? = logged("RCTMGLCamera.toUpdateItem.decode.bound") { try JSONDecoder().decode(Turf.FeatureCollection.self, from: feature.data(using: .utf8)!) } let features = collection?.features - + let ne: CLLocationCoordinate2D switch features?.first?.geometry { - case .point(let point): - ne = point.coordinates - default: - Logger.log(level: .error, message: "RCTMGLCamera.toUpdateItem: Unexpected geometry: \(String(describing: features?.first?.geometry))") - return nil + case .point(let point): + ne = point.coordinates + + default: + Logger.log(level: .error, message: "RCTMGLCamera.toUpdateItem: Unexpected geometry: \(String(describing: features?.first?.geometry))") + return nil } - + let sw: CLLocationCoordinate2D switch features?.last?.geometry { - case .point(let point): - sw = point.coordinates - default: - Logger.log(level: .error, message: "RCTMGLCamera.toUpdateItem: Unexpected geometry: \(String(describing: features?.last?.geometry))") - return nil + case .point(let point): + sw = point.coordinates + + default: + Logger.log(level: .error, message: "RCTMGLCamera.toUpdateItem: Unexpected geometry: \(String(describing: features?.last?.geometry))") + return nil } - + withMapView { map in let bounds = CoordinateBounds(southwest: sw, northeast: ne) let camera = map.mapboxMap.camera( @@ -440,14 +448,14 @@ class RCTMGLCamera : RCTMGLMapComponentBase { } return nil }() - + let mode: CameraMode = { if let m = stop["mode"] as? String, let m = CameraMode(rawValue: m) { return m } return .flight }() - + if let z1 = minZoomLevel, let z2 = CGFloat(exactly: z1), zoom ?? 100 < z2 { zoom = z2 } @@ -470,7 +478,7 @@ class RCTMGLCamera : RCTMGLMapComponentBase { ) return result } - + func _updateCamera() { if let _ = map { if followUserLocation { @@ -480,29 +488,29 @@ class RCTMGLCamera : RCTMGLMapComponentBase { } } } - + func _setInitialCamera() { guard let stop = self.defaultStop, let map = map else { return } - + if var updateItem = toUpdateItem(stop: stop) { updateItem.mode = .none updateItem.duration = 0 updateItem.execute(map: map, cameraAnimator: &cameraAnimator) } } - + func initialLayout() { _setInitialCamera() _updateCamera() } - + override func addToMap(_ map: RCTMGLMapView, style: Style) { super.addToMap(map, style: style) map.reactCamera = self } - + override func removeFromMap(_ map: RCTMGLMapView) { map.viewport.removeStatusObserver(self) super.removeFromMap(map) @@ -511,17 +519,19 @@ class RCTMGLCamera : RCTMGLMapComponentBase { // MARK: - ViewportStatusObserver -extension RCTMGLCamera : ViewportStatusObserver { +extension RCTMGLCamera: ViewportStatusObserver { func toDict(_ status: ViewportStatus) -> [String: Any] { - switch (status) { + switch status { case .idle: - return ["state":"idle"] + return ["state": "idle"] + case .state(let state): - return ["state":String(describing: type(of: state))] + return ["state": String(describing: type(of: state))] + case .transition(let transition, toState: let toState): return [ "transition": String(describing: type(of: transition)), - "state":String(describing: type(of: toState)) + "state": String(describing: type(of: toState)) ] } } @@ -530,9 +540,11 @@ extension RCTMGLCamera : ViewportStatusObserver { switch status { case .idle: return false - case .state(_): + + case .state: return true - case .transition(_, toState: _): + + case .transition: return true } } @@ -560,8 +572,10 @@ extension RCTMGLCamera : ViewportStatusObserver { switch status { case .idle: return nil + case .state(let state): return toFollowUserMode(state) + case .transition(_, toState: let state): return toFollowUserMode(state) } @@ -585,9 +599,8 @@ extension RCTMGLCamera : ViewportStatusObserver { func viewportStatusDidChange(from fromStatus: ViewportStatus, to toStatus: ViewportStatus, - reason: ViewportStatusChangeReason) - { - if (reason == .userInteraction) { + reason: ViewportStatusChangeReason) { + if reason == .userInteraction { followUserLocation = toFollowUserLocation(toStatus) if let onUserTrackingModeChange = onUserTrackingModeChange { @@ -611,4 +624,3 @@ extension RCTMGLCamera : ViewportStatusObserver { private func toSeconds(_ ms: Double) -> TimeInterval { return ms * 0.001 } - diff --git a/ios/RCTMGL-v10/RCTMGLCameraManager.swift b/ios/RCTMGL-v10/RCTMGLCameraManager.swift index 59c9979e3..5d05f45cc 100644 --- a/ios/RCTMGL-v10/RCTMGLCameraManager.swift +++ b/ios/RCTMGL-v10/RCTMGLCameraManager.swift @@ -2,13 +2,13 @@ import Foundation import MapboxMaps @objc(RCTMGLCameraManager) -class RCTMGLCameraManager : RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - return RCTMGLCamera() - } +class RCTMGLCameraManager: RCTViewManager { + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + return RCTMGLCamera() + } } diff --git a/ios/RCTMGL-v10/RCTMGLCircleLayer.swift b/ios/RCTMGL-v10/RCTMGLCircleLayer.swift index b7f3ef7d1..ab92f31a7 100644 --- a/ios/RCTMGL-v10/RCTMGLCircleLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLCircleLayer.swift @@ -2,11 +2,10 @@ import MapboxMaps @objc(RCTMGLCircleLayer) class RCTMGLCircleLayer: RCTMGLVectorLayer { - typealias LayerType = CircleLayer override func makeLayer(style: Style) throws -> Layer { - let _ : VectorSource = try self.layerWithSourceID(in: style) + let _: VectorSource = try self.layerWithSourceID(in: style) var layer = LayerType(id: self.id!) layer.sourceLayer = self.sourceLayerID layer.source = sourceID @@ -16,9 +15,9 @@ class RCTMGLCircleLayer: RCTMGLVectorLayer { override func layerType() -> Layer.Type { return LayerType.self } - - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout CircleLayer) in + + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout CircleLayer) in if let styleLayer = self.styleLayer as? LayerType { layer = styleLayer } @@ -26,9 +25,9 @@ class RCTMGLCircleLayer: RCTMGLVectorLayer { } override func addStyles() { - if let style : Style = self.style, + if let style: Style = self.style, let reactStyle = self.reactStyle { - let styler = RCTMGLStyle(style: self.style!) + let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge if var styleLayer = self.styleLayer as? LayerType { styler.circleLayer( @@ -43,7 +42,7 @@ class RCTMGLCircleLayer: RCTMGLVectorLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLCircleLayerManager.swift b/ios/RCTMGL-v10/RCTMGLCircleLayerManager.swift index a14d7a1a9..c82fd573c 100644 --- a/ios/RCTMGL-v10/RCTMGLCircleLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLCircleLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLCircleLayerManager) class RCTMGLCircleLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLCircleLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLCircleLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLEvent.swift b/ios/RCTMGL-v10/RCTMGLEvent.swift index 01aa5e129..70e865e0c 100644 --- a/ios/RCTMGL-v10/RCTMGLEvent.swift +++ b/ios/RCTMGL-v10/RCTMGLEvent.swift @@ -1,48 +1,46 @@ import Foundation protocol RCTMGLEventProtocol { - func toJSON() -> [String: Any?]; + func toJSON() -> [String: Any?] } @objc -class RCTMGLEvent : NSObject, RCTMGLEventProtocol { - var type: String = "" - var payload: [String:Any?]? = nil - func toJSON() -> [String: Any?] - { - if let payload = payload { - return ["type": type, "payload": payload]; - } else { - return ["type": type] - } +class RCTMGLEvent: NSObject, RCTMGLEventProtocol { + var type: String = "" + var payload: [String: Any?]? + func toJSON() -> [String: Any?] { + if let payload = payload { + return ["type": type, "payload": payload] + } else { + return ["type": type] } + } - enum EventType : String { - case tap - case longPress - //case regionWillChange - case regionIsChanging - case regionDidChange - case cameraChanged - case mapIdle - case imageMissing - case didFinishLoadingMap - case mapLoadingError - case didFinishRenderingFully - case didFinishRendering - case didFinishLoadingStyle - case willStartLoadingMap - case offlineProgress - case offlineError - case offlineTileLimit - case onUserTrackingModeChange - case vectorSourceLayerPress - case shapeSourceLayerPress - } - - init(type: EventType, payload: [String:Any?]?) { - self.type = type.rawValue - self.payload = payload - } - + enum EventType: String { + case tap + case longPress + // case regionWillChange + case regionIsChanging + case regionDidChange + case cameraChanged + case mapIdle + case imageMissing + case didFinishLoadingMap + case mapLoadingError + case didFinishRenderingFully + case didFinishRendering + case didFinishLoadingStyle + case willStartLoadingMap + case offlineProgress + case offlineError + case offlineTileLimit + case onUserTrackingModeChange + case vectorSourceLayerPress + case shapeSourceLayerPress + } + + init(type: EventType, payload: [String: Any?]?) { + self.type = type.rawValue + self.payload = payload + } } diff --git a/ios/RCTMGL-v10/RCTMGLFeatureUtils.swift b/ios/RCTMGL-v10/RCTMGLFeatureUtils.swift index 2d4adfab5..05449eb4f 100644 --- a/ios/RCTMGL-v10/RCTMGLFeatureUtils.swift +++ b/ios/RCTMGL-v10/RCTMGLFeatureUtils.swift @@ -2,46 +2,50 @@ import MapboxMaps import MapKit class RCTMGLFeatureUtils { - - enum ParseError : Error { + enum ParseError: Error { case fcParseError(String) } - + static func parseAsFC(string: String) throws -> GeoJSONObject { let data = string.data(using: .utf8)! - let geojson = try JSONDecoder().decode(GeoJSONObject.self, from:data) + let geojson = try JSONDecoder().decode(GeoJSONObject.self, from: data) return geojson - //let feature = Feature(geometry: try JSONDecoder().decode(Geometry.self, from: data)) + // let feature = Feature(geometry: try JSONDecoder().decode(Geometry.self, from: data)) // return feature } - + static func toNSValue(_ cglocation: CLLocationCoordinate2D) -> NSValue { return NSValue(mkCoordinate: cglocation) -// return NSValue(cgPoint: CGPoint(x: cglocation.latitude, y: cglocation.longitude)) + // return NSValue(cgPoint: CGPoint(x: cglocation.latitude, y: cglocation.longitude)) } - + static func geometryToGeometry(_ geometry: Turf.Geometry) -> MapboxCommon.Geometry { switch geometry { case .geometryCollection(let collection): return MapboxCommon.Geometry(geometryCollection: collection.geometries.map { geometryToGeometry($0) }) + case .lineString(let lineString): return MapboxCommon.Geometry(line: lineString.coordinates.map { toNSValue($0) }) + case .multiLineString(let multiLineString): return MapboxCommon.Geometry(multiLine: multiLineString.coordinates.map { $0.map { toNSValue($0) }}) + case .multiPoint(let multiPoint): return MapboxCommon.Geometry(multiPoint: multiPoint.coordinates.map { toNSValue($0) }) + case .multiPolygon(let multiPolygon): return MapboxCommon.Geometry(multiPolygon: multiPolygon.coordinates.map { $0.map { $0.map { toNSValue($0) }}}) + case .point(let point): return MapboxCommon.Geometry(point: toNSValue(point.coordinates)) -/* - let value = NSValue(cgPoint: CGPoint(x: point.coordinates.longitude, y: point.coordinates.latitude)) - return MapboxCommon.Geometry(point: value) */ + /* + let value = NSValue(cgPoint: CGPoint(x: point.coordinates.longitude, y: point.coordinates.latitude)) + return MapboxCommon.Geometry(point: value) */ case .polygon(let polygon): return MapboxCommon.Geometry(polygon: polygon.coordinates.map { $0.map { toNSValue($0)}}) } } - + static func fcToGeomtry(_ collection: FeatureCollection) -> Turf.Geometry { return .geometryCollection(GeometryCollection(geometries: collection.features.map { $0.geometry! })) } @@ -49,31 +53,36 @@ class RCTMGLFeatureUtils { static func boundingBox(geometry: Geometry) -> BoundingBox? { switch geometry { case .polygon(let polygon): - return BoundingBox(from: polygon.outerRing.coordinates) + return BoundingBox(from: polygon.outerRing.coordinates) + case .lineString(let lineString): return BoundingBox(from: lineString.coordinates) + case .point(let point): return BoundingBox(from: [point.coordinates]) + case .multiPoint(let multiPoint): return BoundingBox(from: multiPoint.coordinates) + case .multiPolygon(let multiPolygon): - let coordinates : [[[LocationCoordinate2D]]] = multiPolygon.coordinates; + let coordinates: [[[LocationCoordinate2D]]] = multiPolygon.coordinates return BoundingBox(from: Array(coordinates.joined().joined())) + case .geometryCollection(let collection): let geometries = collection.geometries - let coordinates : [[LocationCoordinate2D]] = geometries.map { (geometry) in + let coordinates: [[LocationCoordinate2D]] = geometries.map { (geometry) in if let bb = boundingBox(geometry: geometry) { - return [bb.northEast,bb.southWest] + return [bb.northEast, bb.southWest] } else { return [] } - }; - + } + return BoundingBox(from: Array(coordinates.joined())) + case .multiLineString(let multiLineString): let coordinates = multiLineString.coordinates return BoundingBox(from: Array(coordinates.joined())) } } - } diff --git a/ios/RCTMGL-v10/RCTMGLFillExtrusionLayerManager.swift b/ios/RCTMGL-v10/RCTMGLFillExtrusionLayerManager.swift index e044eff7e..f1d46cfc6 100644 --- a/ios/RCTMGL-v10/RCTMGLFillExtrusionLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLFillExtrusionLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLFillExtrusionLayerManager) class RCTMGLFillExtrusionLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLFillExtrusionLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLFillExtrusionLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLFillExtrustionLayer.swift b/ios/RCTMGL-v10/RCTMGLFillExtrustionLayer.swift index b9d68a225..b0ea093db 100644 --- a/ios/RCTMGL-v10/RCTMGLFillExtrustionLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLFillExtrustionLayer.swift @@ -5,7 +5,7 @@ class RCTMGLFillExtrusionLayer: RCTMGLVectorLayer { typealias LayerType = FillExtrusionLayer override func makeLayer(style: Style) throws -> Layer { - let _ : VectorSource = try self.layerWithSourceID(in: style) + let _: VectorSource = try self.layerWithSourceID(in: style) var layer = LayerType(id: self.id!) layer.sourceLayer = self.sourceLayerID layer.source = sourceID @@ -15,9 +15,9 @@ class RCTMGLFillExtrusionLayer: RCTMGLVectorLayer { override func layerType() -> Layer.Type { return LayerType.self } - - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout FillExtrusionLayer) in + + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout FillExtrusionLayer) in if let styleLayer = self.styleLayer as? LayerType { layer = styleLayer } @@ -25,9 +25,9 @@ class RCTMGLFillExtrusionLayer: RCTMGLVectorLayer { } override func addStyles() { - if let style : Style = self.style, + if let style: Style = self.style, let reactStyle = self.reactStyle { - let styler = RCTMGLStyle(style: self.style!) + let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge if var styleLayer = self.styleLayer as? LayerType { styler.fillExtrusionLayer( @@ -42,7 +42,7 @@ class RCTMGLFillExtrusionLayer: RCTMGLVectorLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLFillLayer.swift b/ios/RCTMGL-v10/RCTMGLFillLayer.swift index 8674c131b..163529c0a 100644 --- a/ios/RCTMGL-v10/RCTMGLFillLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLFillLayer.swift @@ -5,20 +5,20 @@ class RCTMGLFillLayer: RCTMGLVectorLayer { typealias LayerType = FillLayer override func makeLayer(style: Style) throws -> Layer { - let _ : VectorSource = try self.layerWithSourceID(in: style) + let _: VectorSource = try self.layerWithSourceID(in: style) var layer: Layer = FillLayer(id: self.id!) - + setOptions(&layer) - + return layer } override func layerType() -> Layer.Type { return LayerType.self } - - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout FillLayer) in + + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout FillLayer) in if let styleLayer = self.styleLayer as? LayerType { layer = styleLayer } @@ -26,11 +26,11 @@ class RCTMGLFillLayer: RCTMGLVectorLayer { } override func addStyles() { - if let style : Style = self.style, + if let style: Style = self.style, let reactStyle = reactStyle { let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge - + if var styleLayer = self.styleLayer as? FillLayer { styler.fillLayer( layer: &styleLayer, @@ -47,7 +47,7 @@ class RCTMGLFillLayer: RCTMGLVectorLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLFillLayerManager.swift b/ios/RCTMGL-v10/RCTMGLFillLayerManager.swift index 817682830..440a60d9b 100644 --- a/ios/RCTMGL-v10/RCTMGLFillLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLFillLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLFillLayerManager) class RCTMGLFillLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLFillLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLFillLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLHeatmapLayer.swift b/ios/RCTMGL-v10/RCTMGLHeatmapLayer.swift index 9d5093b48..265500d3e 100644 --- a/ios/RCTMGL-v10/RCTMGLHeatmapLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLHeatmapLayer.swift @@ -5,20 +5,20 @@ class RCTMGLHeatmapLayer: RCTMGLVectorLayer { typealias LayerType = HeatmapLayer override func makeLayer(style: Style) throws -> Layer { - let _ : VectorSource = try self.layerWithSourceID(in: style) + let _: VectorSource = try self.layerWithSourceID(in: style) var layer: Layer = LayerType(id: self.id!) - + setOptions(&layer) - + return layer } override func layerType() -> Layer.Type { return LayerType.self } - - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout HeatmapLayer) in + + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout HeatmapLayer) in if let styleLayer = self.styleLayer as? LayerType { layer = styleLayer } @@ -26,11 +26,11 @@ class RCTMGLHeatmapLayer: RCTMGLVectorLayer { } override func addStyles() { - if let style : Style = self.style, + if let style: Style = self.style, let reactStyle = reactStyle { - let styler = RCTMGLStyle(style: style) + let styler = RCTMGLStyle(style: style) styler.bridge = self.bridge - + if var styleLayer = self.styleLayer as? HeatmapLayer { styler.heatmapLayer( layer: &styleLayer, @@ -47,7 +47,7 @@ class RCTMGLHeatmapLayer: RCTMGLVectorLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLHeatmapLayetManager.swift b/ios/RCTMGL-v10/RCTMGLHeatmapLayetManager.swift index b747d169a..50a0dcf3a 100644 --- a/ios/RCTMGL-v10/RCTMGLHeatmapLayetManager.swift +++ b/ios/RCTMGL-v10/RCTMGLHeatmapLayetManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLHeatmapLayerManager) class RCTMGLHeatmapLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLHeatmapLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLHeatmapLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLImageQueue.swift b/ios/RCTMGL-v10/RCTMGLImageQueue.swift index 68f0c4ce3..6737aa526 100644 --- a/ios/RCTMGL-v10/RCTMGLImageQueue.swift +++ b/ios/RCTMGL-v10/RCTMGLImageQueue.swift @@ -1,5 +1,5 @@ -class RCTMGLImageQueueOperation : Operation { - enum State : Equatable { +class RCTMGLImageQueueOperation: Operation { + enum State: Equatable { case Initial case Executing case Finished @@ -7,23 +7,23 @@ class RCTMGLImageQueueOperation : Operation { case None case All } - - weak var bridge: RCTBridge? = nil + + weak var bridge: RCTBridge? var completionHandler: ((Error?, UIImage?) -> Void)? var cancellationBlock: RCTImageLoaderCancellationBlock? - var urlRequest : URLRequest! = nil - var scale:Double! = 1.0 - + var urlRequest: URLRequest! = nil + var scale: Double! = 1.0 + var state: State = .Initial - - func syncronized(_ body: () throws -> T) rethrows -> T { + + func syncronized(_ body: () throws -> T) rethrows -> T { objc_sync_enter(self) defer { objc_sync_exit(self) } return try body() } - + func setState(state newState: State, only: State, except: State) -> State { - var prevState : State = .None; + var prevState: State = .None self.willChangeValue(forKey: "isExecuting") self.willChangeValue(forKey: "isFinished") self.willChangeValue(forKey: "isCancelled") @@ -32,65 +32,64 @@ class RCTMGLImageQueueOperation : Operation { var allowed = true prevState = self.state if !(only == State.All || prevState == only) { - allowed = false; + allowed = false } - if (prevState == except) { - allowed = false; + if prevState == except { + allowed = false } - if (allowed) { - self.state = newState; + if allowed { + self.state = newState } } - + self.didChangeValue(forKey: "isExecuting") self.didChangeValue(forKey: "isFinished") self.didChangeValue(forKey: "isCancelled") - return prevState; + return prevState } - + func setState(state newState: State, except: State) -> State { setState(state: newState, only: .All, except: except) } - + func setState(state newState: State, only: State) -> State { setState(state: newState, only: only, except: .None) } - + func callCancellationBlock() { if let cancellationBlock = cancellationBlock { cancellationBlock() } } - + override func start() { - weak var weakSelf : RCTMGLImageQueueOperation! = self - + weak var weakSelf: RCTMGLImageQueueOperation! = self + DispatchQueue.global(qos: .default).async { - - let loader : RCTImageLoaderProtocol = weakSelf.bridge!.module(forName: "ImageLoader", lazilyLoadIfNecessary: true) as! RCTImageLoaderProtocol - - let cancellationBlock = loader.loadImage(with: weakSelf.urlRequest, size: .zero, scale: CGFloat(weakSelf.scale), clipped: true, resizeMode: .stretch, progressBlock: { _,_ in }, partialLoad: { _ in }) { error, image in + let loader: RCTImageLoaderProtocol = weakSelf.bridge!.module(forName: "ImageLoader", lazilyLoadIfNecessary: true) as! RCTImageLoaderProtocol + + let cancellationBlock = loader.loadImage(with: weakSelf.urlRequest, size: .zero, scale: CGFloat(weakSelf.scale), clipped: true, resizeMode: .stretch, progressBlock: { _, _ in }, partialLoad: { _ in }) { error, image in if let completionHandler = weakSelf.completionHandler { completionHandler(error, image) } - _ = weakSelf.setState(state:.Finished, except:.Finished) + _ = weakSelf.setState(state: .Finished, except: .Finished) } if let weakSelf = weakSelf { weakSelf.cancellationBlock = cancellationBlock - if (weakSelf.setState(state:.Executing, only:.Initial) == .CancelDoNotExecute) { + if weakSelf.setState(state: .Executing, only: .Initial) == .CancelDoNotExecute { weakSelf.callCancellationBlock() } } } } - + override func cancel() { - if self.setState(state: .CancelDoNotExecute, except:.Finished) == .Executing { + if self.setState(state: .CancelDoNotExecute, except: .Finished) == .Executing { self.callCancellationBlock() } } - + override var isExecuting: Bool { get { return syncronized { @@ -106,7 +105,7 @@ class RCTMGLImageQueueOperation : Operation { } } } - + override var isCancelled: Bool { get { return syncronized { @@ -117,24 +116,24 @@ class RCTMGLImageQueueOperation : Operation { } class RCTMGLImageQueue { - static let sharedInstance: RCTMGLImageQueue = { - let instance = RCTMGLImageQueue() - // setup code - return instance - }() - - var imageQueue : OperationQueue = { + static let sharedInstance: RCTMGLImageQueue = { + let instance = RCTMGLImageQueue() + // setup code + return instance + }() + + var imageQueue: OperationQueue = { let result = OperationQueue() result.name = "comp.mapbox.rctmgl.DownloadImageQueue" return result }() - - public func addImage(_ json : Any!, scale: Double?, bridge: RCTBridge, handler: @escaping (Error?, UIImage?) -> Void) { + + public func addImage(_ json: Any!, scale: Double?, bridge: RCTBridge, handler: @escaping (Error?, UIImage?) -> Void) { let operation = RCTMGLImageQueueOperation() operation.bridge = bridge operation.urlRequest = RCTConvert.nsurlRequest(json) - operation.completionHandler = handler; - operation.scale = scale; + operation.completionHandler = handler + operation.scale = scale imageQueue.addOperation(operation) } } diff --git a/ios/RCTMGL-v10/RCTMGLImageSource.swift b/ios/RCTMGL-v10/RCTMGLImageSource.swift index 5a4e8d8e7..aa7820a17 100644 --- a/ios/RCTMGL-v10/RCTMGLImageSource.swift +++ b/ios/RCTMGL-v10/RCTMGLImageSource.swift @@ -1,9 +1,8 @@ import MapboxMaps @objc -class RCTMGLImageSource : RCTMGLSource { - - @objc var url: String? = nil { +class RCTMGLImageSource: RCTMGLSource { + @objc var url: String? { didSet { if var source = source as? ImageSource { source.url = url @@ -13,8 +12,8 @@ class RCTMGLImageSource : RCTMGLSource { } } } - - @objc var coordinates: [[NSNumber]]? = nil { + + @objc var coordinates: [[NSNumber]]? { didSet { if var source = source as? ImageSource { if let coordinates = coordinates { @@ -28,34 +27,32 @@ class RCTMGLImageSource : RCTMGLSource { } } } - + override func sourceType() -> Source.Type { return ImageSource.self } - override func makeSource() -> Source - { + override func makeSource() -> Source { var result = ImageSource() if let url = url { result.url = url } - + if let coordinates = coordinates { result.coordinates = coordinates.map { $0.map { $0.doubleValue }} } - + return result } - - func doUpdate(_ update:(Style) -> Void) { + + func doUpdate(_ update: (Style) -> Void) { guard let map = self.map, let _ = self.source, map.mapboxMap.style.sourceExists(withId: id) else { return } - + let style = map.mapboxMap.style update(style) } - } diff --git a/ios/RCTMGL-v10/RCTMGLImages.swift b/ios/RCTMGL-v10/RCTMGLImages.swift index 41ecc7cad..61d4e5241 100644 --- a/ios/RCTMGL-v10/RCTMGLImages.swift +++ b/ios/RCTMGL-v10/RCTMGLImages.swift @@ -1,22 +1,21 @@ import MapboxMaps -protocol RCTMGLImageSetter : AnyObject { +protocol RCTMGLImageSetter: AnyObject { func addImage(name: String, image: UIImage, sdf: Bool?, stretchX: [[NSNumber]], stretchY: [[NSNumber]], content: [NSNumber]?, log: String) -> Bool } -class RCTMGLImages : UIView, RCTMGLMapComponent { - - weak var bridge : RCTBridge! = nil - var remoteImages : [String:String] = [:] - - weak var style: Style? = nil +class RCTMGLImages: UIView, RCTMGLMapComponent { + weak var bridge: RCTBridge! = nil + var remoteImages: [String: String] = [:] + + weak var style: Style? @objc - var onImageMissing: RCTBubblingEventBlock? = nil - + var onImageMissing: RCTBubblingEventBlock? + @objc - var images : [String:Any] = [:] - + var images: [String: Any] = [:] + var imageViews: [RCTMGLImage] = [] @objc @@ -24,20 +23,20 @@ class RCTMGLImages : UIView, RCTMGLMapComponent { didSet { nativeImageInfos = nativeImages.compactMap { decodeImage($0) } } - }; + } - typealias NativeImageInfo = (name:String, sdf: Bool, stretchX:[(from:Float, to:Float)], stretchY:[(from:Float, to:Float)], content: (left:Float,top:Float,right:Float,bottom:Float)? ); + typealias NativeImageInfo = (name: String, sdf: Bool, stretchX: [(from: Float, to: Float)], stretchY: [(from: Float, to: Float)], content: (left: Float, top: Float, right: Float, bottom: Float)? ) var nativeImageInfos: [NativeImageInfo] = [] - + @objc open override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { if let image = subview as? RCTMGLImage { imageViews.insert(image, at: atIndex) } else { - Logger.log(level:.warn, message: "RCTMGLImages children can only be RCTMGLImage, got \(optional: subview)") + Logger.log(level: .warn, message: "RCTMGLImages children can only be RCTMGLImage, got \(optional: subview)") } super.insertReactSubview(subview, at: atIndex) } - + @objc open override func removeReactSubview(_ subview: UIView!) { if let image = subview as? RCTMGLImage { imageViews.removeAll { $0 == image } @@ -45,30 +44,30 @@ class RCTMGLImages : UIView, RCTMGLMapComponent { } super.removeReactSubview(subview) } - + // MARK: - RCTMGLMapComponent func waitForStyleLoad() -> Bool { return false } - + func addToMap(_ map: RCTMGLMapView, style: Style) { self.style = style map.images.append(self) - + self.addNativeImages(style: style, nativeImages: nativeImageInfos) self.addRemoteImages(style: style, remoteImages: images) self.addImageViews(style: style, imageViews: imageViews) } - + func removeFromMap(_ map: RCTMGLMapView) { self.style = nil // v10todo } - + func addRemoteImages(style: Style, remoteImages: [String: Any]) { - var missingImages : [String:Any] = [:] - + var missingImages: [String: Any] = [:] + // Add image placeholder for images that are not yet available in the style. This way // we can load the images asynchronously and add the ShapeSource to the map without delay. // The same is required when this ShapeSource is updated with new/added images and the @@ -76,7 +75,7 @@ class RCTMGLImages : UIView, RCTMGLMapComponent { // them in a similar way. // // See also: https://github.com/mapbox/mapbox-gl-native/pull/14253#issuecomment-478827792 - + for imageName in remoteImages.keys { if style.styleManager.getStyleImage(forImageId: imageName) == nil { logged("RCTMGLImages.addImagePlaceholder") { @@ -85,62 +84,62 @@ class RCTMGLImages : UIView, RCTMGLMapComponent { } } } - + if missingImages.count > 0 { RCTMGLUtils.fetchImages(bridge, style: style, objects: missingImages, forceUpdate: true, callback: { }) } } - + private func addImageViews(style: Style, imageViews: [RCTMGLImage]) { imageViews.forEach { imageView in imageView.images = self } } - + public func addMissingImageToStyle(style: Style, imageName: String) -> Bool { if let nativeImage = nativeImageInfos.first(where: { $0.name == imageName }) { addNativeImages(style: style, nativeImages: [nativeImage]) return true } - + if let remoteImage = images[imageName] { addRemoteImages(style: style, remoteImages: [imageName: remoteImage]) return true } return false } - + public func sendImageMissingEvent(imageName: String, payload: StyleImageMissingPayload) { - let payload = ["imageKey":imageName] + let payload = ["imageKey": imageName] let event = RCTMGLEvent(type: .imageMissing, payload: payload) if let onImageMissing = onImageMissing { onImageMissing(event.toJSON()) } } - + static func convert(stretch: [[NSNumber]], scale: Float = 1.0) -> [(from: Float, to: Float)] { - return stretch.map{ pair in + return stretch.map { pair in return (from: pair[0].floatValue * scale, to: pair[1].floatValue * scale) } } - + static func convert(stretch: [(from: Float, to: Float)]) -> [ImageStretches] { return stretch.map { v in ImageStretches(first: v.from, second: v.to) } } - + static func convert(stretch: [[NSNumber]], scale: Float = 1.0) -> [ImageStretches] { return convert(stretch: convert(stretch: stretch, scale: scale)) } - static func convert(content: (left:Float, top:Float, right:Float, bottom:Float)?) -> ImageContent? { + static func convert(content: (left: Float, top: Float, right: Float, bottom: Float)?) -> ImageContent? { guard let content = content else { return nil } - - return ImageContent(left:content.left, top:content.top, right:content.right, bottom:content.bottom) + + return ImageContent(left: content.left, top: content.top, right: content.right, bottom: content.bottom) } - static func convert(content: [NSNumber]?, scale: Float = 1.0) -> (left:Float,top:Float,right:Float,bottom:Float)? { + static func convert(content: [NSNumber]?, scale: Float = 1.0) -> (left: Float, top: Float, right: Float, bottom: Float)? { guard let content = content else { return nil } @@ -149,52 +148,52 @@ class RCTMGLImages : UIView, RCTMGLMapComponent { return nil } return ( - left: content[0].floatValue*scale, - top: content[1].floatValue*scale, - right: content[2].floatValue*scale, - bottom: content[3].floatValue*scale + left: content[0].floatValue * scale, + top: content[1].floatValue * scale, + right: content[2].floatValue * scale, + bottom: content[3].floatValue * scale ) } - + static func convert(content: [NSNumber]?, scale: Float = 1.0) -> ImageContent? { return convert(content: convert(content: content, scale: scale)) } - + func decodeImage(_ imageNameOrInfo: Any) -> NativeImageInfo? { if let imageName = imageNameOrInfo as? String { - return (name: imageName, sdf: false, stretchX:[],stretchY:[],content:nil) - } else if let imageInfo = imageNameOrInfo as? [String:Any] { + return (name: imageName, sdf: false, stretchX: [], stretchY: [], content: nil) + } else if let imageInfo = imageNameOrInfo as? [String: Any] { guard let name = imageInfo["name"] as? String else { Logger.log(level: .warn, message: "NativeImage: \(imageInfo) has no name key") return nil } var sdf = false - var stretchX : [(from:Float, to:Float)] = [] - var stretchY : [(from:Float, to:Float)] = [] + var stretchX: [(from: Float, to: Float)] = [] + var stretchY: [(from: Float, to: Float)] = [] if let sdfV = imageInfo["sdf"] as? NSNumber { sdf = sdfV.boolValue } - + if let stretchXV = imageInfo["stretchX"] as? [[NSNumber]] { stretchX = RCTMGLImages.convert(stretch: stretchXV) } - + if let stretchYV = imageInfo["stretchY"] as? [[NSNumber]] { stretchY = RCTMGLImages.convert(stretch: stretchYV) } - - var content : (left:Float, top:Float, right:Float, bottom:Float)? = nil + + var content: (left: Float, top: Float, right: Float, bottom: Float)? if let contentV = imageInfo["content"] as? [NSNumber] { content = RCTMGLImages.convert(content: contentV) } - + return (name: name, sdf: sdf, stretchX: stretchX, stretchY: stretchY, content: content) } else { Logger.log(level: .warn, message: "RCTMGLImage.nativeImage, unexpected image: \(imageNameOrInfo)") return nil } } - + func addNativeImages(style: Style, nativeImages: [NativeImageInfo]) { for imageInfo in nativeImages { let imageName = imageInfo.name @@ -208,13 +207,13 @@ class RCTMGLImages : UIView, RCTMGLMapComponent { ) } } else { - Logger.log(level:.error, message: "Cannot find nativeImage named \(imageName)") + Logger.log(level: .error, message: "Cannot find nativeImage named \(imageName)") } } } } - - lazy var placeholderImage : UIImage = { + + lazy var placeholderImage: UIImage = { UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), false, 0.0) let result = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() @@ -222,22 +221,21 @@ class RCTMGLImages : UIView, RCTMGLMapComponent { }() } -extension RCTMGLImages : RCTMGLImageSetter { - func addImage(name: String, image: UIImage, sdf: Bool?, stretchX: [[NSNumber]], stretchY: [[NSNumber]], content: [NSNumber]?, log: String) -> Bool - { - return logged("\(log).addImage") { - if let style = style { - try style.addImage(image, - id:name, - sdf: sdf ?? false, - stretchX: RCTMGLImages.convert(stretch: stretchX), - stretchY: RCTMGLImages.convert(stretch: stretchY), - content: RCTMGLImages.convert(content: content) - ) - return true - } else { - return false - } - } ?? false - } +extension RCTMGLImages: RCTMGLImageSetter { + func addImage(name: String, image: UIImage, sdf: Bool?, stretchX: [[NSNumber]], stretchY: [[NSNumber]], content: [NSNumber]?, log: String) -> Bool { + return logged("\(log).addImage") { + if let style = style { + try style.addImage(image, + id: name, + sdf: sdf ?? false, + stretchX: RCTMGLImages.convert(stretch: stretchX), + stretchY: RCTMGLImages.convert(stretch: stretchY), + content: RCTMGLImages.convert(content: content) + ) + return true + } else { + return false + } + } ?? false + } } diff --git a/ios/RCTMGL-v10/RCTMGLImagesManager.swift b/ios/RCTMGL-v10/RCTMGLImagesManager.swift index 480665287..c5a64299c 100644 --- a/ios/RCTMGL-v10/RCTMGLImagesManager.swift +++ b/ios/RCTMGL-v10/RCTMGLImagesManager.swift @@ -1,6 +1,5 @@ - @objc(RCTMGLImagesManager) -class RCTMGLImagesManager : RCTViewManager { +class RCTMGLImagesManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true diff --git a/ios/RCTMGL-v10/RCTMGLInteractiveElement.swift b/ios/RCTMGL-v10/RCTMGLInteractiveElement.swift index ab60ce549..1ca80f61f 100644 --- a/ios/RCTMGL-v10/RCTMGLInteractiveElement.swift +++ b/ios/RCTMGL-v10/RCTMGLInteractiveElement.swift @@ -1,24 +1,24 @@ import MapboxMaps @objc -class RCTMGLInteractiveElement : UIView, RCTMGLMapComponent { - weak var map : RCTMGLMapView? = nil +class RCTMGLInteractiveElement: UIView, RCTMGLMapComponent { + weak var map: RCTMGLMapView? static let hitboxDefault = 44.0 - @objc var draggable: Bool = false - - @objc var hasPressListener: Bool = false - - @objc var hitbox : [String:NSNumber] = [ + @objc var draggable = false + + @objc var hasPressListener = false + + @objc var hitbox: [String: NSNumber] = [ "width": NSNumber(value: hitboxDefault), "height": NSNumber(value: hitboxDefault) ] - + @objc var id: String! = nil { willSet { if id != nil && newValue != id { - Logger.log(level:.warn, message: "Changing id from: \(optional: id) to \(optional: newValue), changing of id is supported") + Logger.log(level: .warn, message: "Changing id from: \(optional: id) to \(optional: newValue), changing of id is supported") if let map = map { removeFromMap(map) } } } @@ -28,11 +28,11 @@ class RCTMGLInteractiveElement : UIView, RCTMGLMapComponent { } } } - - @objc var onDragStart: RCTBubblingEventBlock? = nil - - @objc var onPress: RCTBubblingEventBlock? = nil - + + @objc var onDragStart: RCTBubblingEventBlock? + + @objc var onPress: RCTBubblingEventBlock? + func getLayerIDs() -> [String] { return [] } @@ -40,14 +40,14 @@ class RCTMGLInteractiveElement : UIView, RCTMGLMapComponent { func isDraggable() -> Bool { return draggable } - + func isTouchable() -> Bool { return hasPressListener } - + // MARK: - RCTMGLMapComponent func addToMap(_ map: RCTMGLMapView, style: Style) { - if (self.id == nil) { + if self.id == nil { Logger.log(level: .error, message: "id is required on \(self) but not specified") } self.map = map @@ -56,7 +56,7 @@ class RCTMGLInteractiveElement : UIView, RCTMGLMapComponent { func removeFromMap(_ map: RCTMGLMapView) { self.map = nil } - + func waitForStyleLoad() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLLayer.swift b/ios/RCTMGL-v10/RCTMGLLayer.swift index ff3f68c45..941791aff 100644 --- a/ios/RCTMGL-v10/RCTMGLLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLLayer.swift @@ -1,22 +1,22 @@ @_spi(Experimental) import MapboxMaps -protocol RCTMGLSourceConsumer : class { +protocol RCTMGLSourceConsumer: class { func addToMap(_ map: RCTMGLMapView, style: Style) func removeFromMap(_ map: RCTMGLMapView, style: Style) } @objc(RCTMGLLayer) -class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { - weak var bridge : RCTBridge? = nil +class RCTMGLLayer: UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { + weak var bridge: RCTBridge? - var waitingForID: String? = nil + var waitingForID: String? - @objc var sourceLayerID : String? = nil { + @objc var sourceLayerID: String? { didSet { self.optionsChanged() } } - var oldReatStyle: Dictionary? = nil - @objc var reactStyle : Dictionary? = nil { + var oldReatStyle: [String: Any]? + @objc var reactStyle: [String: Any]? { willSet { oldReatStyle = reactStyle } @@ -26,17 +26,17 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } } } - - var style: Style? = nil - @objc var filter : Array? = nil { + var style: Style? + + @objc var filter: [Any]? { didSet { optionsChanged() } } - + @objc var id: String! = nil { willSet { if id != nil && newValue != id { - Logger.log(level:.warn, message: "Changing id from: \(optional: id) to \(optional: newValue), changing of id is supported") + Logger.log(level: .warn, message: "Changing id from: \(optional: id) to \(optional: newValue), changing of id is supported") if let style = style { self.removeFromMap(style) } } } @@ -47,18 +47,18 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } } - @objc var sourceID: String? = nil { + @objc var sourceID: String? { didSet { optionsChanged() } } - - @objc var minZoomLevel : NSNumber? = nil { + + @objc var minZoomLevel: NSNumber? { didSet { optionsChanged() } } - @objc var maxZoomLevel : NSNumber? = nil { + @objc var maxZoomLevel: NSNumber? { didSet { optionsChanged() } } - @objc var aboveLayerID : String? = nil { + @objc var aboveLayerID: String? { didSet { if let aboveLayerID = aboveLayerID { if aboveLayerID != oldValue { @@ -68,7 +68,7 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } } - @objc var belowLayerID : String? = nil { + @objc var belowLayerID: String? { didSet { if let belowLayerID = belowLayerID { if belowLayerID != oldValue { @@ -77,8 +77,8 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } } } - - @objc var layerIndex : NSNumber? = nil { + + @objc var layerIndex: NSNumber? { didSet { if let layerIndex = layerIndex { if layerIndex != oldValue { @@ -87,18 +87,18 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } } } - - @objc weak var map: RCTMGLMapView? = nil + + @objc weak var map: RCTMGLMapView? deinit { if let waitingForID = waitingForID { - Logger.log(level:.warn, message: "RCTMGLLayer.removeFromMap - unmetPositionDependency: layer: \(optional: id) was waiting for layer: \(optional: waitingForID) but it hasn't added to map") + Logger.log(level: .warn, message: "RCTMGLLayer.removeFromMap - unmetPositionDependency: layer: \(optional: id) was waiting for layer: \(optional: waitingForID) but it hasn't added to map") self.waitingForID = nil } } - - var styleLayer: Layer? = nil - + + var styleLayer: Layer? + /// wearther we inserted the layer or we're referring to an existing layer var existingLayer = false @@ -106,21 +106,21 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { func waitForStyleLoad() -> Bool { return true } - + func removeAndReaddLayer() { if let map = map, let style = style { self.removeFromMap(style) - self.addToMap(map, style:style) + self.addToMap(map, style: style) } } - + /** - addStyles - adds the styles defined by reactStyle to the current layer, but does not apply to the style to the map style + addStyles - adds the styles defined by reactStyle to the current layer, but does not apply to the style to the map style */ func addStyles() { fatalError("Subclasses need to implement the `addStyles()` method.") } - + func addStylesAndUpdate() { guard styleLayer != nil else { return @@ -128,26 +128,26 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { addStyles() if let style = style, - let map = map { + let map = map { if style.styleManager.styleLayerExists(forLayerId: id) { self.updateLayer(map) } } } - + func makeLayer(style: Style) throws -> Layer { fatalError("Subclasses need to implement the `makeLayer(style:)` method.") } - + func findLayer(style: Style, id: String) throws -> Layer { return try style.layer(withId: id) } - + func layerType() -> Layer.Type { fatalError("Subclasses need to implement the `layerType` method. \(self)") } - func apply(style : Style) throws { + func apply(style: Style) throws { fatalError("Subclasses need to implement the `apply` method.") } @@ -168,7 +168,7 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { return .default } } - + func inserLayer(_ map: RCTMGLMapView) { if self.style == nil { print("inserLayer but style is nil") @@ -185,21 +185,20 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { loggedApply(style: style) } } - - func layerWithSourceID(in style: Style) throws -> T { + + func layerWithSourceID(in style: Style) throws -> T { let result = try style.source(withId: self.sourceID!, type: T.self) return result } - func sourceWithSourceID(in style: Style) throws -> T { + func sourceWithSourceID(in style: Style) throws -> T { let result = try style.source(withId: self.sourceID!, type: T.self) return result } func addedToMap() { - } - + func addToMap(_ map: RCTMGLMapView, style: Style) { self.map = map self.style = style @@ -209,7 +208,7 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } do { - if (style.styleManager.styleLayerExists(forLayerId: id)) { + if style.styleManager.styleLayerExists(forLayerId: id) { styleLayer = try findLayer(style: style, id: id) existingLayer = true } else { @@ -219,7 +218,7 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } catch { Logger.log(level: .error, message: "find/makeLayer failed for layer id=\(id)", error: error) } - + guard self.styleLayer != nil else { Logger.log(level: .error, message: "find/makeLayer retuned nil for layer id=\(id)") return @@ -233,23 +232,22 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { } addedToMap() } - + func removeFromMap(_ map: RCTMGLMapView, style: Style) { removeFromMap(style) } - + func setOptions(_ layer: inout Layer) { if let sourceLayerID = sourceLayerID { layer.sourceLayer = sourceLayerID } - + if let sourceID = sourceID { if !(existingLayer && sourceID == DEFAULT_SOURCE_ID) && hasSource() { - layer.source = sourceID } } - + if let filter = filter, filter.count > 0 { do { let data = try JSONSerialization.data(withJSONObject: filter, options: .prettyPrinted) @@ -259,16 +257,16 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { Logger.log(level: .error, message: "parsing filters failed for layer \(optional: id): \(error.localizedDescription)") } } - + if let minZoom = minZoomLevel { layer.minZoom = minZoom.doubleValue } - + if let maxZoom = maxZoomLevel { layer.maxZoom = maxZoom.doubleValue } } - + private func optionsChanged() { if let style = self.style, self.styleLayer != nil { self.setOptions(&self.styleLayer!) @@ -279,10 +277,10 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { func removeFromMap(_ map: RCTMGLMapView) { removeFromMap(map.mapboxMap.style) } - + private func removeFromMap(_ style: Style) { if let waitingForID = waitingForID { - Logger.log(level:.warn, message: "RCTMGLLayer.removeFromMap - unmetPositionDependency: layer: \(optional: id) was waiting for layer: \(optional: waitingForID) but it hasn't added to map") + Logger.log(level: .warn, message: "RCTMGLLayer.removeFromMap - unmetPositionDependency: layer: \(optional: id) was waiting for layer: \(optional: waitingForID) but it hasn't added to map") } do { @@ -291,21 +289,23 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { Logger.log(level: .error, message: "RCTMGLLayer.removeFromMap: removing layer failed for layer \(optional: id): \(error.localizedDescription)") } } - + func insert(_ style: Style, layerPosition: LayerPosition, onInsert: (() -> Void)? = nil) { var idToWaitFor: String? switch layerPosition { case .above(let aboveId): idToWaitFor = aboveId + case .below(let belowId): idToWaitFor = belowId - case .at(_): + + case .at: idToWaitFor = nil + default: idToWaitFor = nil } - - + if let idToWaitFor = idToWaitFor { self.waitingForID = idToWaitFor map!.waitForLayerWithID(idToWaitFor) { _ in @@ -316,12 +316,12 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { self.attemptInsert(style, layerPosition: layerPosition, onInsert: onInsert) } } - + private func attemptInsert(_ style: Style, layerPosition: LayerPosition, onInsert: (() -> Void)? = nil) { guard let styleLayer = self.styleLayer else { return } - + do { try style.addLayer(styleLayer, layerPosition: layerPosition) onInsert?() @@ -329,7 +329,7 @@ class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer { Logger.log(level: .error, message: "inserting layer failed at position \(layerPosition): \(error.localizedDescription)") } } - + internal func hasSource() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLLight.swift b/ios/RCTMGL-v10/RCTMGLLight.swift index fe5bef85c..91a2856a8 100644 --- a/ios/RCTMGL-v10/RCTMGLLight.swift +++ b/ios/RCTMGL-v10/RCTMGLLight.swift @@ -2,10 +2,10 @@ import MapboxMaps @objc(RCTMGLLight) class RCTMGLLight: UIView, RCTMGLMapComponent { - weak var bridge : RCTBridge! = nil + weak var bridge: RCTBridge! = nil weak var map: MapboxMap! = nil - var oldReactStyle: [String:Any]? - @objc var reactStyle : [String:Any]! = nil { + var oldReactStyle: [String: Any]? + @objc var reactStyle: [String: Any]! = nil { willSet { oldReactStyle = reactStyle } @@ -15,11 +15,11 @@ class RCTMGLLight: UIView, RCTMGLMapComponent { } } } - + func apply(light: Light) { let lightData = try! JSONEncoder().encode(light) let lightDictionary = try! JSONSerialization.jsonObject(with: lightData) - try! self.map.style.setLight(properties: lightDictionary as! [String:Any]) + try! self.map.style.setLight(properties: lightDictionary as! [String: Any]) } func addStyles() { @@ -31,14 +31,14 @@ class RCTMGLLight: UIView, RCTMGLMapComponent { }, isValid: { return self.isAddedToMap() }) - + apply(light: light) } - + func isAddedToMap() -> Bool { return map != nil } - + // MARK: - RCTMGLMapComponent func waitForStyleLoad() -> Bool { @@ -47,11 +47,11 @@ class RCTMGLLight: UIView, RCTMGLMapComponent { func addToMap(_ map: RCTMGLMapView, style: Style) { self.map = map.mapboxMap - if (reactStyle != nil) { + if reactStyle != nil { addStyles() } } - + func removeFromMap(_ map: RCTMGLMapView) { self.map = nil } diff --git a/ios/RCTMGL-v10/RCTMGLLightManager.swift b/ios/RCTMGL-v10/RCTMGLLightManager.swift index 331568551..1301199b2 100644 --- a/ios/RCTMGL-v10/RCTMGLLightManager.swift +++ b/ios/RCTMGL-v10/RCTMGLLightManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLLightManager) class RCTMGLLightManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let light = RCTMGLLight() - light.bridge = self.bridge - return light - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let light = RCTMGLLight() + light.bridge = self.bridge + return light + } } diff --git a/ios/RCTMGL-v10/RCTMGLLineLayer.swift b/ios/RCTMGL-v10/RCTMGLLineLayer.swift index 68a318b0b..86b36d904 100644 --- a/ios/RCTMGL-v10/RCTMGLLineLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLLineLayer.swift @@ -5,7 +5,7 @@ class RCTMGLLineLayer: RCTMGLVectorLayer { typealias LayerType = LineLayer override func makeLayer(style: Style) throws -> Layer { - let vectorSource : VectorSource = try self.layerWithSourceID(in: style) + let vectorSource: VectorSource = try self.layerWithSourceID(in: style) var layer = LayerType(id: self.id!) layer.sourceLayer = self.sourceLayerID layer.source = sourceID @@ -16,8 +16,8 @@ class RCTMGLLineLayer: RCTMGLVectorLayer { return LayerType.self } - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout LineLayer) in + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout LineLayer) in if self.styleLayer != nil { self.setOptions(&self.styleLayer!) } @@ -26,12 +26,12 @@ class RCTMGLLineLayer: RCTMGLVectorLayer { } } } - + override func addStyles() { - if let style : Style = self.style { - let styler = RCTMGLStyle(style: self.style!) + if let style: Style = self.style { + let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge - + if var styleLayer = self.styleLayer as? LayerType, let reactStyle = reactStyle { styler.lineLayer( @@ -48,7 +48,7 @@ class RCTMGLLineLayer: RCTMGLVectorLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLLineLayerManager.swift b/ios/RCTMGL-v10/RCTMGLLineLayerManager.swift index 705658eba..87f598779 100644 --- a/ios/RCTMGL-v10/RCTMGLLineLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLLineLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLLineLayerManager) class RCTMGLLineLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLLineLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLLineLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLLocationModule.swift b/ios/RCTMGL-v10/RCTMGLLocationModule.swift index ce99e03db..b88bea91a 100644 --- a/ios/RCTMGL-v10/RCTMGLLocationModule.swift +++ b/ios/RCTMGL-v10/RCTMGLLocationModule.swift @@ -3,13 +3,13 @@ import MapboxMaps @objc(RCTMGLLocation) class RCTMGLLocation: NSObject { - var location : CLLocation = CLLocation(latitude: 0.0, longitude: 0.0) - - var heading : CLHeading? = nil + var location = CLLocation(latitude: 0.0, longitude: 0.0) - var timestamp: Date? = nil + var heading: CLHeading? - func toJSON() -> [String:Any] { + var timestamp: Date? + + func toJSON() -> [String: Any] { return [ "coords": [ "longitude": location.coordinate.longitude, @@ -18,7 +18,7 @@ class RCTMGLLocation: NSObject { "accuracy": location.horizontalAccuracy, "heading": heading?.trueHeading ?? 0.0, "course": location.course, - "speed": location.speed, + "speed": location.speed ], "timestamp": (timestamp ?? location.timestamp).timeIntervalSince1970 * 1000 ] @@ -27,48 +27,47 @@ class RCTMGLLocation: NSObject { typealias RCTMGLLocationBlock = (RCTMGLLocation?) -> Void -let RCT_MAPBOX_USER_LOCATION_UPDATE = "MapboxUserLocationUpdate"; +let RCT_MAPBOX_USER_LOCATION_UPDATE = "MapboxUserLocationUpdate" /// This implementation of LocationProviderDelegate is used by `LocationManager` to work around /// the fact that the `LocationProvider` API does not allow the delegate to be set to `nil`. internal class EmptyLocationProviderDelegate: LocationProviderDelegate { - func locationProvider(_ provider: LocationProvider, didFailWithError error: Error) {} - func locationProvider(_ provider: LocationProvider, didUpdateHeading newHeading: CLHeading) {} - func locationProvider(_ provider: LocationProvider, didUpdateLocations locations: [CLLocation]) {} - func locationProviderDidChangeAuthorization(_ provider: LocationProvider) {} + func locationProvider(_ provider: LocationProvider, didFailWithError error: Error) {} + func locationProvider(_ provider: LocationProvider, didUpdateHeading newHeading: CLHeading) {} + func locationProvider(_ provider: LocationProvider, didUpdateLocations locations: [CLLocation]) {} + func locationProviderDidChangeAuthorization(_ provider: LocationProvider) {} } -protocol LocationProviderRCTMGLDelegate : AnyObject { +protocol LocationProviderRCTMGLDelegate: AnyObject { func locationManager(_ locationManager: LocationProviderRCTMGL, didUpdateLocation: RCTMGLLocation) } /// LocationProviderRCTMGL listens to updates from a locationProvider and implements the LocationProvider interface itself /// So it can be source of Mapbox locationProduces (which updates location pluck and viewport if configured) as well as source to updates /// to RCTMGLLocationModules. -class LocationProviderRCTMGL : LocationProviderDelegate { +class LocationProviderRCTMGL: LocationProviderDelegate { enum LocationUpdateType { case heading case location } - + var provider: LocationProvider - - var lastKnownLocation : CLLocation? - var lastKnownHeading : CLHeading? + + var lastKnownLocation: CLLocation? + var lastKnownHeading: CLHeading? var shouldRequestAlwaysAuthorization: Bool? - + weak var delegate: LocationProviderRCTMGLDelegate? weak var locationProviderDelage: LocationProviderDelegate? - - var headingSimulator: Timer? = nil + + var headingSimulator: Timer? var simulatedHeading: Double = 0.0 var simulatedHeadingIncrement: Double = 1.0 - - + struct Status { var provider = (updatingLocation: false, updatingHeading: false) var rctmglModule = false - + var shouldUpdateLocation: Bool { return provider.updatingLocation || rctmglModule } @@ -87,15 +86,15 @@ class LocationProviderRCTMGL : LocationProviderDelegate { provider = AppleLocationProvider() provider.setDelegate(self) } - + func setDistanceFilter(_ distanceFilter: CLLocationDistance) { var options = provider.locationProviderOptions options.distanceFilter = distanceFilter provider.locationProviderOptions = options } - + func setRequestsAlwaysUse(_ requestsAlwaysUse: Bool) { - shouldRequestAlwaysAuthorization = requestsAlwaysUse; + shouldRequestAlwaysAuthorization = requestsAlwaysUse } func start() { @@ -105,14 +104,14 @@ class LocationProviderRCTMGL : LocationProviderDelegate { provider.requestWhenInUseAuthorization() started.rctmglModule = true } - + func stop() { started.rctmglModule = false } func _syncStarted(oldValue: Status, started: Status) { var stoppedSomething = false - if (oldValue.shouldUpdateLocation != started.shouldUpdateLocation) { + if oldValue.shouldUpdateLocation != started.shouldUpdateLocation { if started.shouldUpdateLocation { provider.setDelegate(self) provider.startUpdatingLocation() @@ -121,8 +120,8 @@ class LocationProviderRCTMGL : LocationProviderDelegate { stoppedSomething = true } } - - if (oldValue.shouldUpdateHeading != started.shouldUpdateHeading) { + + if oldValue.shouldUpdateHeading != started.shouldUpdateHeading { if started.shouldUpdateHeading { provider.setDelegate(self) provider.startUpdatingHeading() @@ -131,59 +130,60 @@ class LocationProviderRCTMGL : LocationProviderDelegate { stoppedSomething = true } } - + if stoppedSomething && !started.shouldUpdateLocation && !started.shouldUpdateHeading { provider.setDelegate(EmptyLocationProviderDelegate()) } } - + func _convertToMapboxLocation(_ location: CLLocation?, type: LocationUpdateType) -> RCTMGLLocation { guard let location = location else { return RCTMGLLocation() } let userLocation = RCTMGLLocation() - userLocation.location = location; + userLocation.location = location userLocation.heading = lastKnownHeading switch type { case .location: userLocation.timestamp = location.timestamp + case .heading: userLocation.timestamp = lastKnownHeading!.timestamp } - return userLocation; + return userLocation } - + func _updateDelegate(type: LocationUpdateType) { if delegate == nil { - return; + return } let userLocation = _convertToMapboxLocation(lastKnownLocation, type: type) delegate?.locationManager(self, didUpdateLocation: userLocation) } - - // MARK: - LocationProviderDelegate - + + // MARK: - LocationProviderDelegate + func locationProvider(_ provider: LocationProvider, didUpdateLocations locations: [CLLocation]) { lastKnownLocation = locations.last self._updateDelegate(type: .location) - + locationProviderDelage?.locationProvider(provider, didUpdateLocations: locations) } - + func locationProvider(_ provider: LocationProvider, didUpdateHeading newHeading: CLHeading) { lastKnownHeading = newHeading self._updateDelegate(type: .heading) - + locationProviderDelage?.locationProvider(provider, didUpdateHeading: newHeading) } - + func locationProvider(_ provider: LocationProvider, didFailWithError error: Error) { locationProviderDelage?.locationProvider(provider, didFailWithError: error) } - + func locationProviderDidChangeAuthorization(_ provider: LocationProvider) { locationProviderDelage?.locationProviderDidChangeAuthorization(provider) } @@ -200,38 +200,38 @@ extension LocationProviderRCTMGL: LocationProvider { provider.locationProviderOptions = newValue } } - + var authorizationStatus: CLAuthorizationStatus { get { provider.authorizationStatus } } - + var accuracyAuthorization: CLAccuracyAuthorization { get { provider.accuracyAuthorization } } - + var heading: CLHeading? { get { provider.heading } } - + func setDelegate(_ delegate: LocationProviderDelegate) { provider.setDelegate(self) locationProviderDelage = delegate } - + func requestAlwaysAuthorization() { provider.requestAlwaysAuthorization() } - + func requestWhenInUseAuthorization() { provider.requestWhenInUseAuthorization() } - + func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String) { if #available(iOS 14.0, *) { provider.requestTemporaryFullAccuracyAuthorization(withPurposeKey: purposeKey) @@ -239,15 +239,15 @@ extension LocationProviderRCTMGL: LocationProvider { // Fallback on earlier versions } } - + func startUpdatingLocation() { started.provider.updatingLocation = true } - + func stopUpdatingLocation() { started.provider.updatingLocation = false } - + var headingOrientation: CLDeviceOrientation { get { return provider.headingOrientation @@ -256,15 +256,15 @@ extension LocationProviderRCTMGL: LocationProvider { provider.headingOrientation = newValue } } - + func startUpdatingHeading() { started.provider.updatingHeading = true } - + func stopUpdatingHeading() { started.provider.updatingHeading = false } - + func dismissHeadingCalibrationDisplay() { provider.dismissHeadingCalibrationDisplay() } @@ -278,23 +278,23 @@ final public class SimulatedHeading: CLHeading { _timestamp = timestamp super.init() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - - private var _trueHeading: CLLocationDirection = 0 - private var _timestamp: Date - public override var trueHeading: CLLocationDirection { - get { _trueHeading } - set { _trueHeading = newValue } - } + private var _trueHeading: CLLocationDirection = 0 + private var _timestamp: Date - public override var timestamp: Date{ - get { _timestamp } - set { _timestamp = newValue } - } + public override var trueHeading: CLLocationDirection { + get { _trueHeading } + set { _trueHeading = newValue } + } + + public override var timestamp: Date { + get { _timestamp } + set { _timestamp = newValue } + } } extension LocationProviderRCTMGL { @@ -306,8 +306,8 @@ extension LocationProviderRCTMGL { } self.headingSimulator = nil - if (changesPerSecond > 0) { - self.headingSimulator = Timer.scheduledTimer(withTimeInterval: 1.0/Double(changesPerSecond), repeats: true) { [weak self] (_) in + if changesPerSecond > 0 { + self.headingSimulator = Timer.scheduledTimer(withTimeInterval: 1.0 / Double(changesPerSecond), repeats: true) { [weak self] (_) in guard let self = self else { return } self.simulatedHeading = (self.simulatedHeading + self.simulatedHeadingIncrement).truncatingRemainder(dividingBy: 360.0) @@ -321,19 +321,18 @@ extension LocationProviderRCTMGL { // LocationModule is a sigleton class @objc(RCTMGLLocationModule) class RCTMGLLocationModule: RCTEventEmitter, LocationProviderRCTMGLDelegate { + static weak var shared: RCTMGLLocationModule? - static weak var shared : RCTMGLLocationModule? = nil - - var locationProviderRCTMGL : LocationProviderRCTMGL + var locationProviderRCTMGL: LocationProviderRCTMGL var hasListener = false - - var locationProvider : LocationProvider { + + var locationProvider: LocationProvider { get { return locationProviderRCTMGL } } - - var locationEventThrottle : ( + + var locationEventThrottle: ( waitBetweenEvents: Double?, lastSentTimestamp: Double? ) = ( @@ -347,41 +346,40 @@ class RCTMGLLocationModule: RCTEventEmitter, LocationProviderRCTMGLDelegate { locationProviderRCTMGL.delegate = self RCTMGLLocationModule.shared = self } - + @objc override static func requiresMainQueueSetup() -> Bool { return true } - + @objc override func constantsToExport() -> [AnyHashable: Any]! { - return [:]; + return [:] } - @objc override func supportedEvents() -> [String] - { - return [RCT_MAPBOX_USER_LOCATION_UPDATE]; + @objc override func supportedEvents() -> [String] { + return [RCT_MAPBOX_USER_LOCATION_UPDATE] } - + @objc func start(_ minDisplacement: CLLocationDistance) { if minDisplacement >= 0.0 { locationProviderRCTMGL.setDistanceFilter(minDisplacement) } locationProviderRCTMGL.start() } - + @objc func stop() { locationProviderRCTMGL.stop() } - + @objc func getLastKnownLocation() -> RCTMGLLocation? { return RCTMGLLocation() } - + @objc func setMinDisplacement(_ minDisplacement: CLLocationDistance) { locationProviderRCTMGL.setDistanceFilter(minDisplacement) } - + @objc func setRequestsAlwaysUse(_ requestsAlwaysUse: Bool) { - locationProviderRCTMGL.setRequestsAlwaysUse(requestsAlwaysUse); + locationProviderRCTMGL.setRequestsAlwaysUse(requestsAlwaysUse) } @objc func simulateHeading(_ changesPerSecond: NSNumber, increment: NSNumber) { @@ -393,13 +391,13 @@ class RCTMGLLocationModule: RCTEventEmitter, LocationProviderRCTMGLDelegate { super.startObserving() hasListener = true } - + @objc override func stopObserving() { super.stopObserving() hasListener = false } - + func locationManager(_ locationManager: LocationProviderRCTMGL, didUpdateLocation location: RCTMGLLocation) { guard hasListener, let _ = bridge else { return @@ -409,10 +407,10 @@ class RCTMGLLocationModule: RCTEventEmitter, LocationProviderRCTMGLDelegate { self.sendEvent(withName: RCT_MAPBOX_USER_LOCATION_UPDATE, body: location.toJSON()) } } - + // MARK: - location event throttle @objc - func setLocationEventThrottle(_ throttleValue:NSNumber) { + func setLocationEventThrottle(_ throttleValue: NSNumber) { let throttleValue = throttleValue.doubleValue if throttleValue > 0.0 { locationEventThrottle.waitBetweenEvents = throttleValue @@ -425,21 +423,19 @@ class RCTMGLLocationModule: RCTEventEmitter, LocationProviderRCTMGLDelegate { guard let waitBetweenEvents = locationEventThrottle.waitBetweenEvents, waitBetweenEvents > 0 else { return true } - + let currentTimestamp: Double = CACurrentMediaTime() * 1000.0 - + guard let lastSentTimestamp = locationEventThrottle.lastSentTimestamp else { locationEventThrottle.lastSentTimestamp = currentTimestamp - return true; + return true } - - if (currentTimestamp - lastSentTimestamp > waitBetweenEvents) { + + if currentTimestamp - lastSentTimestamp > waitBetweenEvents { locationEventThrottle.lastSentTimestamp = currentTimestamp - return true; + return true } - - return false; + + return false } } - - diff --git a/ios/RCTMGL-v10/RCTMGLLogging.swift b/ios/RCTMGL-v10/RCTMGLLogging.swift index fd5cbb151..7542fde7a 100644 --- a/ios/RCTMGL-v10/RCTMGLLogging.swift +++ b/ios/RCTMGL-v10/RCTMGLLogging.swift @@ -12,19 +12,19 @@ enum RCTMGLError: Error, LocalizedError { } class Logger { - enum LogLevel : String, Comparable { + enum LogLevel: String, Comparable { static func < (lhs: Logger.LogLevel, rhs: Logger.LogLevel) -> Bool { return lhs.intValue < rhs.intValue } - + case verbose = "verbose" case debug = "debug" case info = "info" case warn = "warning" case error = "error" - - var intValue : Int { - let values : [LogLevel:Int] = [ + + var intValue: Int { + let values: [LogLevel: Int] = [ .verbose: 0, .debug: 1, .info: 2, @@ -36,30 +36,30 @@ class Logger { } return result } - - var stringValue : String { + + var stringValue: String { return rawValue } } - + static let sharedInstance = Logger() - + var level: LogLevel = .info - var handler : (LogLevel, String) -> Void = { (level, message) in + var handler: (LogLevel, String) -> Void = { (_, _) in fatalError("Handler not yet installed") } - + func log(level: LogLevel, message: String) { print("LOG \(level) \(message)") if self.level <= level { handler(level, message) } } - + static func log(level: LogLevel, message: String) { sharedInstance.log(level: level, message: message) } - + static func log(level: LogLevel, message: String, error: Error) { sharedInstance.log(level: level, message: "\(message) - error: \(error.localizedDescription) \(error)") } @@ -84,11 +84,11 @@ func errorMessage(_ error: Error) -> String { } /// log message if optional returned by `fn` is nil -func logged(_ msg: String, info: (() -> String)? = nil, level: Logger.LogLevel = .error, rejecter: RCTPromiseRejectBlock? = nil, fn: () -> T?) ->T? { +func logged(_ msg: String, info: (() -> String)? = nil, level: Logger.LogLevel = .error, rejecter: RCTPromiseRejectBlock? = nil, fn: () -> T?) -> T? { let ret = fn() if ret == nil { - Logger.log(level:level, message: "\(msg) \(info?() ?? "")") - rejecter?(msg, "\(info?() ?? "")", NSError(domain:"is null", code: 0)) + Logger.log(level: level, message: "\(msg) \(info?() ?? "")") + rejecter?(msg, "\(info?() ?? "")", NSError(domain: "is null", code: 0)) return nil } else { return ret @@ -96,31 +96,31 @@ func logged(_ msg: String, info: (() -> String)? = nil, level: Logger.LogLeve } /// log message if `fn` throws and return nil -func logged(_ msg: String, info: (() -> String)? = nil, level: Logger.LogLevel = .error, rejecter: RCTPromiseRejectBlock? = nil, fn : () throws -> T) -> T? { +func logged(_ msg: String, info: (() -> String)? = nil, level: Logger.LogLevel = .error, rejecter: RCTPromiseRejectBlock? = nil, fn: () throws -> T) -> T? { do { return try fn() } catch { - Logger.log(level:level, message: "\(msg) \(info?() ?? "") \(errorMessage(error))") + Logger.log(level: level, message: "\(msg) \(info?() ?? "") \(errorMessage(error))") rejecter?(msg, "\(info?() ?? "") \(errorMessage(error))", error) return nil } } -func logged(_ msg: String, info: (() -> String)? = nil, errorResult: (Error) -> T, level: Logger.LogLevel = .error, fn : () throws -> T) -> T { +func logged(_ msg: String, info: (() -> String)? = nil, errorResult: (Error) -> T, level: Logger.LogLevel = .error, fn: () throws -> T) -> T { do { return try fn() } catch { - Logger.log(level:level, message: "\(msg) \(info?() ?? "") \(error.localizedDescription)") + Logger.log(level: level, message: "\(msg) \(info?() ?? "") \(error.localizedDescription)") return errorResult(error) } } @objc(RCTMGLLogging) class RCTMGLLogging: RCTEventEmitter { - static var shared : RCTMGLLogging? = nil - + static var shared: RCTMGLLogging? + enum ErrorType { - case argumentError + case argumentError } @objc @@ -130,7 +130,7 @@ class RCTMGLLogging: RCTEventEmitter { } Logger.sharedInstance.level = logLevel } - + override init() { super.init() if let _ = RCTMGLLogging.shared { @@ -150,15 +150,14 @@ class RCTMGLLogging: RCTEventEmitter { self.sendEvent(withName: "LogEvent", body: body) } } - + @objc static override func requiresMainQueueSetup() -> Bool { - return true + return true } - + @objc - override func supportedEvents() -> [String] - { - return ["LogEvent"]; + override func supportedEvents() -> [String] { + return ["LogEvent"] } } diff --git a/ios/RCTMGL-v10/RCTMGLMapView.swift b/ios/RCTMGL-v10/RCTMGLMapView.swift index 0238e6dc5..031354762 100644 --- a/ios/RCTMGL-v10/RCTMGLMapView.swift +++ b/ios/RCTMGL-v10/RCTMGLMapView.swift @@ -3,48 +3,48 @@ import Turf import MapKit @objc(RCTMGLMapView) -open class RCTMGLMapView : MapView { - var tapDelegate: IgnoreRCTMGLMakerViewGestureDelegate? = nil +open class RCTMGLMapView: MapView { + var tapDelegate: IgnoreRCTMGLMakerViewGestureDelegate? - var compassEnabled: Bool = false - var compassFadeWhenNorth: Bool = false + var compassEnabled = false + var compassFadeWhenNorth = false var compassImage: String? - - var reactOnPress : RCTBubblingEventBlock? - var reactOnLongPress : RCTBubblingEventBlock? - var reactOnMapChange : RCTBubblingEventBlock? - var styleLoaded: Bool = false - var styleLoadWaiters : [(MapboxMap)->Void] = [] + var reactOnPress: RCTBubblingEventBlock? + var reactOnLongPress: RCTBubblingEventBlock? + var reactOnMapChange: RCTBubblingEventBlock? + + var styleLoaded = false + var styleLoadWaiters: [(MapboxMap) -> Void] = [] var onStyleLoadedComponents: [RCTMGLMapComponent] = [] - + var componentsToRefreshOnStyleChange: [RCTMGLMapComponent] = [] - weak var reactCamera : RCTMGLCamera? - var images : [RCTMGLImages] = [] - var sources : [RCTMGLInteractiveElement] = [] - + weak var reactCamera: RCTMGLCamera? + var images: [RCTMGLImages] = [] + var sources: [RCTMGLInteractiveElement] = [] + var handleMapChangedEvents = Set() - var eventListeners : [Cancelable] = [] + var eventListeners: [Cancelable] = [] private var isPendingInitialLayout = true private var wasGestureActive = false private var isGestureActive = false - var layerWaiters : [String:[(String) -> Void]] = [:] - - lazy var pointAnnotationManager : PointAnnotationManager = { + var layerWaiters: [String: [(String) -> Void]] = [:] + + lazy var pointAnnotationManager: PointAnnotationManager = { let result = PointAnnotationManager(annotations: annotations, mapView: mapView) self._removeMapboxLongPressGestureRecognizer() return result }() - lazy var calloutAnnotationManager : MapboxMaps.PointAnnotationManager = { + lazy var calloutAnnotationManager: MapboxMaps.PointAnnotationManager = { return annotations.makePointAnnotationManager(id: "rctmgl-mapview-callouts") }() - - var mapView : MapView { + + var mapView: MapView { get { return self } } @@ -53,7 +53,7 @@ open class RCTMGLMapView : MapView { let style = mapView.mapboxMap.style if mapComponent.waitForStyleLoad() { componentsToRefreshOnStyleChange.append(mapComponent) - if (self.styleLoaded) { + if self.styleLoaded { mapComponent.addToMap(self, style: style) } else { onStyleLoadedComponents.append(mapComponent) @@ -68,7 +68,7 @@ open class RCTMGLMapView : MapView { sources.append(source) } } - + func removeFromMap(_ subview: UIView) { if let mapComponent = subview as? RCTMGLMapComponent { if mapComponent.waitForStyleLoad() { @@ -88,13 +88,13 @@ open class RCTMGLMapView : MapView { addToMap(subview) super.insertReactSubview(subview, at: atIndex) } - + @objc open override func removeReactSubview(_ subview: UIView!) { removeFromMap(subview) super.removeReactSubview(subview) } - public required init(frame:CGRect) { + public required init(frame: CGRect) { let resourceOptions = ResourceOptions(accessToken: MGLModule.accessToken!) super.init(frame: frame, mapInitOptions: MapInitOptions(resourceOptions: resourceOptions)) @@ -102,36 +102,35 @@ open class RCTMGLMapView : MapView { setupEvents() } - + public required init (coder: NSCoder) { - fatalError("not implemented") + fatalError("not implemented") } - + func layerAdded (_ layer: Layer) { - // TODO + // TODO } - + func waitForLayerWithID(_ layerId: String, _ callback: @escaping (_ layerId: String) -> Void) { - let style = mapboxMap.style; + let style = mapboxMap.style if style.layerExists(withId: layerId) { callback(layerId) } else { layerWaiters[layerId, default: []].append(callback) } } - + @objc public override func layoutSubviews() { super.layoutSubviews() if let camera = reactCamera { - if (isPendingInitialLayout) { - isPendingInitialLayout = false; + if isPendingInitialLayout { + isPendingInitialLayout = false camera.initialLayout() } } } - // MARK: - React Native properties @objc func setReactProjection(_ value: String?) { @@ -153,93 +152,96 @@ open class RCTMGLMapView : MapView { } } } - - + @objc func setReactAttributionEnabled(_ value: Bool) { mapView.ornaments.options.attributionButton.visibility = value ? .visible : .hidden } - + @objc func setReactAttributionPosition(_ position: [String: NSNumber]) { if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) { mapView.ornaments.options.attributionButton.position = ornamentOptions.position mapView.ornaments.options.attributionButton.margins = ornamentOptions.margins } } - + @objc func setReactLogoEnabled(_ value: Bool) { mapView.ornaments.options.logo.visibility = value ? .visible : .hidden } - + @objc func setReactLogoPosition(_ position: [String: NSNumber]) { if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) { mapView.ornaments.options.logo.position = ornamentOptions.position mapView.ornaments.options.logo.margins = ornamentOptions.margins } } - + @objc func setReactCompassEnabled(_ value: Bool) { compassEnabled = value refreshCompassVisibility() } - + @objc func setReactCompassFadeWhenNorth(_ value: Bool) { compassFadeWhenNorth = value refreshCompassVisibility() } - + private func refreshCompassVisibility() { var visibility: OrnamentVisibility = .hidden if compassEnabled { visibility = compassFadeWhenNorth ? .adaptive : .visible } mapView.ornaments.options.compass.visibility = visibility - + refreshCompassImage() } - + @objc func setReactCompassPosition(_ position: [String: NSNumber]) { if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) { mapView.ornaments.options.compass.position = ornamentOptions.position mapView.ornaments.options.compass.margins = ornamentOptions.margins } } - + func toOrnamentPositon(_ position: Int) -> OrnamentPosition { - enum MapboxGLPosition : Int { + enum MapboxGLPosition: Int { case topLeft = 0 case topRight = 1 case bottomLeft = 2 case bottomRight = 3 - }; - + } + let glPosition = MapboxGLPosition(rawValue: position) switch glPosition { case .topLeft: return .topLeading + case .bottomRight: return .bottomTrailing + case .topRight: return .topTrailing + case .bottomLeft: return .bottomLeading + case .none: return .topLeading } } - + @objc func setReactCompassViewPosition(_ position: NSInteger) { mapView.ornaments.options.compass.position = toOrnamentPositon(Int(truncating: NSNumber(value: position))) } - + @objc func setReactCompassViewMargins(_ margins: CGPoint) { - mapView.ornaments.options.compass.margins = margins; + mapView.ornaments.options.compass.margins = margins } @objc func setReactCompassImage(_ image: String) { compassImage = image.isEmpty ? nil : image refreshCompassImage() } - + private func refreshCompassImage() { if let compassImage = compassImage { onMapStyleLoaded { map in @@ -256,7 +258,7 @@ open class RCTMGLMapView : MapView { @objc func setReactScaleBarEnabled(_ value: Bool) { self.mapView.ornaments.options.scaleBar.visibility = value ? .visible : .hidden } - + @objc func setReactScaleBarPosition(_ position: [String: NSNumber]) { if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) { mapView.ornaments.options.scaleBar.position = ornamentOptions.position @@ -282,19 +284,19 @@ open class RCTMGLMapView : MapView { @objc func setReactPitchEnabled(_ value: Bool) { self.mapView.gestures.options.pitchEnabled = value } - + func refreshComponentsBeforeStyleChange() { componentsToRefreshOnStyleChange.forEach { $0.removeFromMap(self) } } - + func refreshComponentsAfterStyleChange(style: Style) { componentsToRefreshOnStyleChange.forEach { $0.addToMap(self, style: style) } } - + @objc func setReactStyleURL(_ value: String?) { var initialLoad = !self.styleLoaded if !initialLoad { refreshComponentsBeforeStyleChange() } @@ -308,12 +310,12 @@ open class RCTMGLMapView : MapView { } } if !initialLoad { - self.onNext(event: .styleLoaded) {_,_ in + self.onNext(event: .styleLoaded) {_, _ in self.refreshComponentsAfterStyleChange(style: self.mapboxMap.style) } } } - let event = RCTMGLEvent(type:.willStartLoadingMap, payload: nil); + let event = RCTMGLEvent(type: .willStartLoadingMap, payload: nil) self.fireEvent(event: event, callback: self.reactOnMapChange) } @@ -322,7 +324,7 @@ open class RCTMGLMapView : MapView { let right = position["right"] let top = position["top"] let bottom = position["bottom"] - + if let left = left, let top = top { return (OrnamentPosition.topLeading, CGPoint(x: Int(truncating: left), y: Int(truncating: top))) } else if let right = right, let top = top { @@ -332,13 +334,13 @@ open class RCTMGLMapView : MapView { } else if let bottom = bottom, let left = left { return (OrnamentPosition.bottomLeading, CGPoint(x: Int(truncating: left), y: Int(truncating: bottom))) } - + return nil } func _removeMapboxLongPressGestureRecognizer() { mapView.gestureRecognizers?.forEach { recognizer in - if (String(describing: type(of:recognizer)) == "MapboxLongPressGestureRecognizer") { + if String(describing: type(of: recognizer)) == "MapboxLongPressGestureRecognizer" { mapView.removeGestureRecognizer(recognizer) } } @@ -356,7 +358,7 @@ extension RCTMGLMapView { } eventListeners.append(eventListener) if eventListeners.count > 20 { - Logger.log(level:.warn, message: "RCTMGLMapView.onEvery, too much handler installed"); + Logger.log(level: .warn, message: "RCTMGLMapView.onEvery, too much handler installed") } } @@ -371,26 +373,26 @@ extension RCTMGLMapView { @objc func setReactOnMapChange(_ value: @escaping RCTBubblingEventBlock) { self.reactOnMapChange = value - self.onEvery(event: .cameraChanged, handler: { (self, cameraEvent) in + self.onEvery(event: .cameraChanged, handler: { (self, _) in self.wasGestureActive = self.isGestureActive if self.handleMapChangedEvents.contains(.regionIsChanging) { - let event = RCTMGLEvent(type:.regionIsChanging, payload: self.buildRegionObject()); + let event = RCTMGLEvent(type: .regionIsChanging, payload: self.buildRegionObject()) self.fireEvent(event: event, callback: self.reactOnMapChange) } else if self.handleMapChangedEvents.contains(.cameraChanged) { - let event = RCTMGLEvent(type:.cameraChanged, payload: self.buildStateObject()); + let event = RCTMGLEvent(type: .cameraChanged, payload: self.buildStateObject()) self.fireEvent(event: event, callback: self.reactOnMapChange) } }) - self.onEvery(event: .mapIdle, handler: { (self, cameraEvent) in + self.onEvery(event: .mapIdle, handler: { (self, _) in if self.handleMapChangedEvents.contains(.regionDidChange) { - let event = RCTMGLEvent(type:.regionDidChange, payload: self.buildRegionObject()); + let event = RCTMGLEvent(type: .regionDidChange, payload: self.buildRegionObject()) self.fireEvent(event: event, callback: self.reactOnMapChange) } else if self.handleMapChangedEvents.contains(.mapIdle) { - let event = RCTMGLEvent(type:.mapIdle, payload: self.buildStateObject()); + let event = RCTMGLEvent(type: .mapIdle, payload: self.buildStateObject()) self.fireEvent(event: event, callback: self.reactOnMapChange) } - + self.wasGestureActive = false }) } @@ -406,11 +408,11 @@ extension RCTMGLMapView { private func fireEvent(event: RCTMGLEvent, callback: @escaping RCTBubblingEventBlock) { callback(event.toJSON()) } - + private func buildStateObject() -> [String: [String: Any]] { let cameraOptions = CameraOptions(cameraState: cameraState) let bounds = mapView.mapboxMap.coordinateBounds(for: cameraOptions) - + return [ "properties": [ "center": Point(mapView.cameraState.center).coordinates.toArray(), @@ -418,26 +420,26 @@ extension RCTMGLMapView { "ne": bounds.northeast.toArray(), "sw": bounds.southwest.toArray() ], - "zoom" : Double(mapView.cameraState.zoom), + "zoom": Double(mapView.cameraState.zoom), "heading": Double(mapView.cameraState.bearing), - "pitch": Double(mapView.cameraState.pitch), + "pitch": Double(mapView.cameraState.pitch) ], "gestures": [ "isGestureActive": wasGestureActive ] ] } - + private func buildRegionObject() -> [String: Any] { let cameraOptions = CameraOptions(cameraState: cameraState) let bounds = mapView.mapboxMap.coordinateBounds(for: cameraOptions) - let boundsArray : JSONArray = [ - [.number(bounds.northeast.longitude),.number(bounds.northeast.latitude)], - [.number(bounds.southwest.longitude),.number(bounds.southwest.latitude)] + let boundsArray: JSONArray = [ + [.number(bounds.northeast.longitude), .number(bounds.northeast.latitude)], + [.number(bounds.southwest.longitude), .number(bounds.southwest.latitude)] ] var result = Feature( - geometry: .point(Point(mapView.cameraState.center)) + geometry: .point(Point(mapView.cameraState.center)) ) result.properties = [ "zoomLevel": .number(mapView.cameraState.zoom), @@ -445,17 +447,17 @@ extension RCTMGLMapView { "bearing": .number(mapView.cameraState.bearing), "pitch": .number(mapView.cameraState.pitch), "visibleBounds": .array(boundsArray), - "isUserInteraction": .boolean(wasGestureActive), + "isUserInteraction": .boolean(wasGestureActive) ] - return logged("buildRegionObject", errorResult: { ["error":["toJSON":$0.localizedDescription]] }) { + return logged("buildRegionObject", errorResult: { ["error": ["toJSON": $0.localizedDescription]] }) { try result.toJSON() } } - + public func setupEvents() { self.onEvery(event: .mapLoadingError, handler: { (self, event) in - let eventPayload : MapLoadingErrorPayload = event.payload - var payload : [String:String] = [ + let eventPayload: MapLoadingErrorPayload = event.payload + var payload: [String: String] = [ "error": eventPayload.error.errorDescription ?? eventPayload.error.localizedDescription ] if let tileId = eventPayload.tileId { @@ -464,7 +466,7 @@ extension RCTMGLMapView { if let sourceId = eventPayload.sourceId { payload["sourceId"] = sourceId } - let rctmglEvent = RCTMGLEvent(type: .mapLoadingError, payload: payload); + let rctmglEvent = RCTMGLEvent(type: .mapLoadingError, payload: payload) self.fireEvent(event: rctmglEvent, callback: self.reactOnMapChange) if let message = eventPayload.error.errorDescription { @@ -473,10 +475,10 @@ extension RCTMGLMapView { Logger.log(level: .error, message: "MapLoad error \(event)") } }) - + self.onEvery(event: .styleImageMissing) { (self, event) in let imageName = event.payload.id - + self.images.forEach { if $0.addMissingImageToStyle(style: self.mapboxMap.style, imageName: imageName) { return @@ -493,25 +495,25 @@ extension RCTMGLMapView { if event.payload.renderMode == .full { type = .didFinishRenderingFully } - let payload : [String:Any] = [ + let payload: [String: Any] = [ "renderMode": event.payload.renderMode.rawValue, "needsRepaint": event.payload.needsRepaint, "placementChanged": event.payload.placementChanged ] - let event = RCTMGLEvent(type: type, payload: payload); + let event = RCTMGLEvent(type: type, payload: payload) self.fireEvent(event: event, callback: self.reactOnMapChange) }) self.onNext(event: .mapLoaded, handler: { (self, event) in - let event = RCTMGLEvent(type:.didFinishLoadingMap, payload: nil); + let event = RCTMGLEvent(type: .didFinishLoadingMap, payload: nil) self.fireEvent(event: event, callback: self.reactOnMapChange) }) - + self.onEvery(event: .styleLoaded, handler: { (self, event) in self.onStyleLoadedComponents.forEach { (component) in component.addToMap(self, style: self.mapboxMap.style) } - + if !self.styleLoaded { self.styleLoaded = true if let mapboxMap = self.mapboxMap { @@ -521,7 +523,7 @@ extension RCTMGLMapView { } } - let event = RCTMGLEvent(type:.didFinishLoadingStyle, payload: nil) + let event = RCTMGLEvent(type: .didFinishLoadingStyle, payload: nil) self.fireEvent(event: event, callback: self.reactOnMapChange) }) } @@ -529,60 +531,58 @@ extension RCTMGLMapView { // MARK: - gestures -class IgnoreRCTMGLMakerViewGestureDelegate : NSObject, UIGestureRecognizerDelegate { +class IgnoreRCTMGLMakerViewGestureDelegate: NSObject, UIGestureRecognizerDelegate { var originalDelegate: UIGestureRecognizerDelegate? init(originalDelegate: UIGestureRecognizerDelegate?) { self.originalDelegate = originalDelegate } - + func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { return originalDelegate?.gestureRecognizerShouldBegin?(gestureRecognizer) ?? true } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { - return originalDelegate?.gestureRecognizer?(gestureRecognizer,shouldRecognizeSimultaneouslyWith: otherGestureRecognizer) ?? false + return originalDelegate?.gestureRecognizer?(gestureRecognizer, shouldRecognizeSimultaneouslyWith: otherGestureRecognizer) ?? false } - + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool { - return originalDelegate?.gestureRecognizer?(gestureRecognizer,shouldRequireFailureOf: otherGestureRecognizer) ?? false + return originalDelegate?.gestureRecognizer?(gestureRecognizer, shouldRequireFailureOf: otherGestureRecognizer) ?? false } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { - return originalDelegate?.gestureRecognizer?(gestureRecognizer,shouldBeRequiredToFailBy: otherGestureRecognizer) ?? false + return originalDelegate?.gestureRecognizer?(gestureRecognizer, shouldBeRequiredToFailBy: otherGestureRecognizer) ?? false } private func isMarkerViewSubview(_ view: UIView) -> Bool { - var current : UIView? = view + var current: UIView? = view while let act = current { - if (act is RCTMGLMarkerView) { + if act is RCTMGLMarkerView { return true } current = act.superview } return false } - + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if let view = touch.view, isMarkerViewSubview(view) { return false } - return originalDelegate?.gestureRecognizer?(gestureRecognizer,shouldReceive: touch) ?? true + return originalDelegate?.gestureRecognizer?(gestureRecognizer, shouldReceive: touch) ?? true } - + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive press: UIPress) -> Bool { - return originalDelegate?.gestureRecognizer?(gestureRecognizer,shouldReceive: press) ?? true + return originalDelegate?.gestureRecognizer?(gestureRecognizer, shouldReceive: press) ?? true } - @available(iOS 13.4, *) func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive event: UIEvent) -> Bool { - return originalDelegate?.gestureRecognizer?(gestureRecognizer,shouldReceive: event) ?? true + return originalDelegate?.gestureRecognizer?(gestureRecognizer, shouldReceive: event) ?? true } } extension RCTMGLMapView { - @objc func setReactOnPress(_ value: @escaping RCTBubblingEventBlock) { self.reactOnPress = value @@ -614,14 +614,14 @@ extension RCTMGLMapView: GestureManagerDelegate { private func doHandleTapInSources(sources: [RCTMGLInteractiveElement], tapPoint: CGPoint, hits: [String: [QueriedFeature]], touchedSources: [RCTMGLInteractiveElement], callback: @escaping (_ hits: [String: [QueriedFeature]], _ touchedSources: [RCTMGLInteractiveElement]) -> Void) { DispatchQueue.main.async { if let source = sources.first { - let hitbox = source.hitbox; - - let halfWidth = (hitbox["width"]?.doubleValue ?? RCTMGLInteractiveElement.hitboxDefault) / 2.0; - let halfHeight = (hitbox["height"]?.doubleValue ?? RCTMGLInteractiveElement.hitboxDefault) / 2.0; - - let top = tapPoint.y - halfHeight; - let left = tapPoint.x - halfWidth; - + let hitbox = source.hitbox + + let halfWidth = (hitbox["width"]?.doubleValue ?? RCTMGLInteractiveElement.hitboxDefault) / 2.0 + let halfHeight = (hitbox["height"]?.doubleValue ?? RCTMGLInteractiveElement.hitboxDefault) / 2.0 + + let top = tapPoint.y - halfHeight + let left = tapPoint.x - halfWidth + let hitboxRect = CGRect(x: left, y: top, width: halfWidth * 2.0, height: halfHeight * 2.0) let options = RenderedQueryOptions( @@ -629,12 +629,13 @@ extension RCTMGLMapView: GestureManagerDelegate { ) self.mapboxMap.queryRenderedFeatures(with: hitboxRect, options: options) { result in - + var newHits = hits - var newTouchedSources = touchedSources; + var newTouchedSources = touchedSources switch result { - case .failure(let error): + case .failure(let error): Logger.log(level: .error, message: "Error during handleTapInSources source.id=\(source.id ?? "n/a") error:\(error)") + case .success(let features): if !features.isEmpty { newHits[source.id] = features @@ -651,10 +652,10 @@ extension RCTMGLMapView: GestureManagerDelegate { } } } - + func highestZIndex(sources: [RCTMGLInteractiveElement]) -> RCTMGLInteractiveElement? { - var layersToSource : [String:RCTMGLInteractiveElement] = [:] - + var layersToSource: [String: RCTMGLInteractiveElement] = [:] + sources.forEach { source in source.getLayerIDs().forEach { layerId in if layersToSource[layerId] == nil { @@ -665,7 +666,7 @@ extension RCTMGLMapView: GestureManagerDelegate { let orderedLayers = mapboxMap.style.allLayerIdentifiers return orderedLayers.lazy.reversed().compactMap { layersToSource[$0.id] }.first ?? sources.first } - + @objc func doHandleTap(_ sender: UITapGestureRecognizer) { let tapPoint = sender.location(in: self) @@ -673,12 +674,11 @@ extension RCTMGLMapView: GestureManagerDelegate { DispatchQueue.main.async { let touchableSources = self.touchableSources() self.doHandleTapInSources(sources: touchableSources, tapPoint: tapPoint, hits: [:], touchedSources: []) { (hits, touchedSources) in - if let source = self.highestZIndex(sources: touchedSources), source.hasPressListener, let onPress = source.onPress { guard let hitFeatures = hits[source.id] else { - Logger.log(level:.error, message: "doHandleTap, no hits found when it should have") + Logger.log(level: .error, message: "doHandleTap, no hits found when it should have") return } let features = hitFeatures.compactMap { queriedFeature in @@ -690,25 +690,24 @@ extension RCTMGLMapView: GestureManagerDelegate { "features": features, "point": [ "x": Double(tapPoint.x), - "y": Double(tapPoint.y), + "y": Double(tapPoint.y) ], "coordinates": [ "latitude": Double(location.latitude), - "longitude": Double(location.longitude), + "longitude": Double(location.longitude) ] ] ) self.fireEvent(event: event, callback: onPress) - } else { if let reactOnPress = self.reactOnPress { let location = self.mapboxMap.coordinate(for: tapPoint) - var geojson = Feature(geometry: .point(Point(location))); + var geojson = Feature(geometry: .point(Point(location))) geojson.properties = [ "screenPointX": .number(Double(tapPoint.x)), "screenPointY": .number(Double(tapPoint.y)) ] - let event = RCTMGLEvent(type:.tap, payload: logged("reactOnPress") { try geojson.toJSON() }) + let event = RCTMGLEvent(type: .tap, payload: logged("reactOnPress") { try geojson.toJSON() }) self.fireEvent(event: event, callback: reactOnPress) } } @@ -716,7 +715,7 @@ extension RCTMGLMapView: GestureManagerDelegate { } } } - + @objc func doHandleLongPress(_ sender: UILongPressGestureRecognizer) { let position = sender.location(in: self) @@ -728,7 +727,7 @@ extension RCTMGLMapView: GestureManagerDelegate { source.draggable, let onDragStart = source.onDragStart { guard let hitFeatures = hits[source.id] else { - Logger.log(level:.error, message: "doHandleLongPress, no hits found when it should have") + Logger.log(level: .error, message: "doHandleLongPress, no hits found when it should have") return } let features = hitFeatures.compactMap { queriedFeature in @@ -740,27 +739,27 @@ extension RCTMGLMapView: GestureManagerDelegate { "features": features, "point": [ "x": Double(position.x), - "y": Double(position.y), + "y": Double(position.y) ], "coordinates": [ "latitude": Double(location.latitude), - "longitude": Double(location.longitude), + "longitude": Double(location.longitude) ] ] ) self.fireEvent(event: event, callback: onDragStart) - } else { - if let reactOnLongPress = self.reactOnLongPress, sender.state == .began { - let coordinate = self.mapboxMap.coordinate(for: position) - var geojson = Feature(geometry: .point(Point(coordinate))); - geojson.properties = [ - "screenPointX": .number(Double(position.x)), - "screenPointY": .number(Double(position.y)) - ] - let event = RCTMGLEvent(type:.longPress, payload: logged("doHandleLongPress") { try geojson.toJSON() }) - self.fireEvent(event: event, callback: reactOnLongPress) - } - } + } else { + if let reactOnLongPress = self.reactOnLongPress, sender.state == .began { + let coordinate = self.mapboxMap.coordinate(for: position) + var geojson = Feature(geometry: .point(Point(coordinate))) + geojson.properties = [ + "screenPointX": .number(Double(position.x)), + "screenPointY": .number(Double(position.y)) + ] + let event = RCTMGLEvent(type: .longPress, payload: logged("doHandleLongPress") { try geojson.toJSON() }) + self.fireEvent(event: event, callback: reactOnLongPress) + } + } } } } @@ -769,30 +768,28 @@ extension RCTMGLMapView: GestureManagerDelegate { public func gestureManager(_ gestureManager: GestureManager, didBegin gestureType: GestureType) { isGestureActive = true } - + public func gestureManager(_ gestureManager: GestureManager, didEnd gestureType: GestureType, willAnimate: Bool) { if !willAnimate { - isGestureActive = false; + isGestureActive = false } } - + public func gestureManager(_ gestureManager: GestureManager, didEndAnimatingFor gestureType: GestureType) { - isGestureActive = false; + isGestureActive = false } } -extension RCTMGLMapView -{ +extension RCTMGLMapView { @objc func takeSnap( - writeToDisk:Bool) -> URL - { - UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0); + writeToDisk: Bool) -> URL { + UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0) self.drawHierarchy(in: self.bounds, afterScreenUpdates: true) - let snapshot = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); + let snapshot = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() - return writeToDisk ? RNMBImageUtils.createTempFile(snapshot!) : RNMBImageUtils.createBase64(snapshot!) + return writeToDisk ? RNMBImageUtils.createTempFile(snapshot!) : RNMBImageUtils.createBase64(snapshot!) } } @@ -807,7 +804,7 @@ extension RCTMGLMapView { guard let mapboxMap = mapboxMap else { fatalError("mapboxMap is null") } - + if styleLoaded { block(mapboxMap) } else { @@ -817,9 +814,9 @@ extension RCTMGLMapView { } extension RCTMGLMapView { - func setSourceVisibility(_ visible: Bool, sourceId: String, sourceLayerId: String?) -> Void { + func setSourceVisibility(_ visible: Bool, sourceId: String, sourceLayerId: String?) { let style = self.mapboxMap.style - + style.allLayerIdentifiers.forEach { layerInfo in let layer = logged("setSourceVisibility.layer", info: { "\(layerInfo.id)" }) { try style.layer(withId: layerInfo.id) @@ -845,10 +842,10 @@ extension RCTMGLMapView { } } -class PointAnnotationManager : AnnotationInteractionDelegate { - weak var selected : RCTMGLPointAnnotation? = nil +class PointAnnotationManager: AnnotationInteractionDelegate { + weak var selected: RCTMGLPointAnnotation? private var draggedAnnotation: PointAnnotation? - + func annotationManager(_ manager: AnnotationManager, didDetectTappedAnnotations annotations: [Annotation]) { // We handle taps ourselfs // onTap(annotations: annotations) @@ -858,11 +855,10 @@ class PointAnnotationManager : AnnotationInteractionDelegate { guard annotations.count > 0 else { fatalError("didDetectTappedAnnotations: No annotations found") } - + for annotation in annotations { if let pointAnnotation = annotation as? PointAnnotation, let userInfo = pointAnnotation.userInfo { - if let rctmglPointAnnotation = userInfo[RCTMGLPointAnnotation.key] as? WeakRef { if let pt = rctmglPointAnnotation.object { let position = pt.superview?.convert(pt.layer.position, to: nil) @@ -873,7 +869,7 @@ class PointAnnotationManager : AnnotationInteractionDelegate { "screenPointX": .number(Double(position!.x)), "screenPointY": .number(Double(position!.y)) ] - let event = RCTMGLEvent(type:.tap, payload: logged("doHandleTap") { try geojson.toJSON() }) + let event = RCTMGLEvent(type: .tap, payload: logged("doHandleTap") { try geojson.toJSON() }) if let selected = selected { guard let onDeselected = pt.onDeselected else { return @@ -892,8 +888,8 @@ class PointAnnotationManager : AnnotationInteractionDelegate { } } } - - func handleTap(_ tap: UITapGestureRecognizer, noAnnotationFound: @escaping (UITapGestureRecognizer) -> Void) { + + func handleTap(_ tap: UITapGestureRecognizer, noAnnotationFound: @escaping (UITapGestureRecognizer) -> Void) { let layerId = manager.layerId guard let mapFeatureQueryable = mapView?.mapboxMap else { noAnnotationFound(tap) @@ -902,42 +898,40 @@ class PointAnnotationManager : AnnotationInteractionDelegate { let options = RenderedQueryOptions(layerIds: [layerId], filter: nil) mapFeatureQueryable.queryRenderedFeatures( with: tap.location(in: tap.view), - options: options) { [weak self] (result) in - - guard let self = self else { return } - - switch result { - - case .success(let queriedFeatures): + options: options) { [weak self] (result) in + guard let self = self else { return } - // Get the identifiers of all the queried features - let queriedFeatureIds: [String] = queriedFeatures.compactMap { - guard case let .string(featureId) = $0.feature.identifier else { - return nil - } - return featureId - } + switch result { + case .success(let queriedFeatures): - // Find if any `queriedFeatureIds` match an annotation's `id` - let tappedAnnotations = self.manager.annotations.filter { queriedFeatureIds.contains($0.id) } + // Get the identifiers of all the queried features + let queriedFeatureIds: [String] = queriedFeatures.compactMap { + guard case let .string(featureId) = $0.feature.identifier else { + return nil + } + return featureId + } - // If `tappedAnnotations` is not empty, call delegate - if !tappedAnnotations.isEmpty { - self.onTap(annotations: tappedAnnotations) - } else { - noAnnotationFound(tap) - } + // Find if any `queriedFeatureIds` match an annotation's `id` + let tappedAnnotations = self.manager.annotations.filter { queriedFeatureIds.contains($0.id) } - case .failure(let error): + // If `tappedAnnotations` is not empty, call delegate + if !tappedAnnotations.isEmpty { + self.onTap(annotations: tappedAnnotations) + } else { noAnnotationFound(tap) - Logger.log(level:.warn, message:"Failed to query map for annotations due to error: \(error)") } + + case .failure(let error): + noAnnotationFound(tap) + Logger.log(level: .warn, message: "Failed to query map for annotations due to error: \(error)") + } } } - - var manager : MapboxMaps.PointAnnotationManager - weak var mapView : MapView? = nil - + + var manager: MapboxMaps.PointAnnotationManager + weak var mapView: MapView? + init(annotations: AnnotationOrchestrator, mapView: MapView) { manager = annotations.makePointAnnotationManager(id: "rctmgl-mapview-point-annotations") manager.delegate = self @@ -948,11 +942,10 @@ class PointAnnotationManager : AnnotationInteractionDelegate { guard annotations.count > 0 else { fatalError("didDetectDraggedAnnotations: No annotations found") } - + for annotation in annotations { if let pointAnnotation = annotation as? PointAnnotation, let userInfo = pointAnnotation.userInfo { - if let rctmglPointAnnotation = userInfo[RCTMGLPointAnnotation.key] as? WeakRef { if let pt = rctmglPointAnnotation.object { let position = pt.superview?.convert(pt.layer.position, to: nil) @@ -962,25 +955,28 @@ class PointAnnotationManager : AnnotationInteractionDelegate { "screenPointX": .number(Double(position!.x)), "screenPointY": .number(Double(position!.y)) ] - let event = RCTMGLEvent(type:.longPress, payload: logged("doHandleLongPress") { try geojson.toJSON() }) - switch (dragState) { + let event = RCTMGLEvent(type: .longPress, payload: logged("doHandleLongPress") { try geojson.toJSON() }) + switch dragState { case .began: guard let onDragStart = pt.onDragStart else { return } onDragStart(event.toJSON()) + case .changed: guard let onDrag = pt.onDrag else { return } onDrag(event.toJSON()) return + case .ended: guard let onDragEnd = pt.onDragEnd else { return } onDragEnd(event.toJSON()) return + default: return } @@ -989,7 +985,7 @@ class PointAnnotationManager : AnnotationInteractionDelegate { } } } - + // Used for handling panning to detect annotation dragging func handleLongPress(_ sender: UILongPressGestureRecognizer, noAnnotationFound: @escaping (UILongPressGestureRecognizer) -> Void) { let layerId = manager.layerId @@ -1001,81 +997,83 @@ class PointAnnotationManager : AnnotationInteractionDelegate { guard let targetPoint = self.mapView?.mapboxMap.coordinate(for: sender.location(in: sender.view)) else { return } - switch sender.state { - case .began: - mapFeatureQueryable.queryRenderedFeatures( - with: sender.location(in: sender.view), - options: options) { [weak self] (result) in - - guard let self = self else { return } - switch result { - case .success(let queriedFeatures): - // Get the identifiers of all the queried features - let queriedFeatureIds: [String] = queriedFeatures.compactMap { - guard case let .string(featureId) = $0.feature.identifier else { - return nil - } - return featureId - } - - // Find if any `queriedFeatureIds` match an annotation's `id` - let draggedAnnotations = self.manager.annotations.filter { queriedFeatureIds.contains($0.id) } - let enabledAnnotations = draggedAnnotations.filter { ($0.userInfo?[RCTMGLPointAnnotation.key] as? WeakRef)?.object?.draggable ?? false } - // If `tappedAnnotations` is not empty, call delegate - if !enabledAnnotations.isEmpty { - self.draggedAnnotation = enabledAnnotations.first! - self.onDragHandler(self.manager, didDetectDraggedAnnotations: enabledAnnotations, dragState: .began, targetPoint: targetPoint) - } else { - noAnnotationFound(sender) - } - case .failure(let error): - noAnnotationFound(sender) - Logger.log(level:.warn, message:"Failed to query map for annotations due to error: \(error)") - } - } - - case .changed: - guard var annotation = self.draggedAnnotation else { - return + switch sender.state { + case .began: + mapFeatureQueryable.queryRenderedFeatures( + with: sender.location(in: sender.view), + options: options) { [weak self] (result) in + guard let self = self else { return } + switch result { + case .success(let queriedFeatures): + // Get the identifiers of all the queried features + let queriedFeatureIds: [String] = queriedFeatures.compactMap { + guard case let .string(featureId) = $0.feature.identifier else { + return nil + } + return featureId } - - self.onDragHandler(self.manager, didDetectDraggedAnnotations: [annotation], dragState: .changed, targetPoint: targetPoint) - let idx = self.manager.annotations.firstIndex { an in return an.id == annotation.id } - if let idx = idx { - self.manager.annotations[idx].point = Point(targetPoint) + // Find if any `queriedFeatureIds` match an annotation's `id` + let draggedAnnotations = self.manager.annotations.filter { queriedFeatureIds.contains($0.id) } + let enabledAnnotations = draggedAnnotations.filter { ($0.userInfo?[RCTMGLPointAnnotation.key] as? WeakRef)?.object?.draggable ?? false } + // If `tappedAnnotations` is not empty, call delegate + if !enabledAnnotations.isEmpty { + self.draggedAnnotation = enabledAnnotations.first! + self.onDragHandler(self.manager, didDetectDraggedAnnotations: enabledAnnotations, dragState: .began, targetPoint: targetPoint) + } else { + noAnnotationFound(sender) } - case .cancelled, .ended: - guard let annotation = self.draggedAnnotation else { - return + + case .failure(let error): + noAnnotationFound(sender) + Logger.log(level: .warn, message: "Failed to query map for annotations due to error: \(error)") } - // Optionally notify some other delegate to tell them the drag finished. - self.onDragHandler(self.manager, didDetectDraggedAnnotations: [annotation], dragState: .ended, targetPoint: targetPoint) - // Reset our global var containing the annotation currently being dragged - self.draggedAnnotation = nil + } + + case .changed: + guard var annotation = self.draggedAnnotation else { return - default: - return } + + self.onDragHandler(self.manager, didDetectDraggedAnnotations: [annotation], dragState: .changed, targetPoint: targetPoint) + + let idx = self.manager.annotations.firstIndex { an in return an.id == annotation.id } + if let idx = idx { + self.manager.annotations[idx].point = Point(targetPoint) + } + + case .cancelled, .ended: + guard let annotation = self.draggedAnnotation else { + return + } + // Optionally notify some other delegate to tell them the drag finished. + self.onDragHandler(self.manager, didDetectDraggedAnnotations: [annotation], dragState: .ended, targetPoint: targetPoint) + // Reset our global var containing the annotation currently being dragged + self.draggedAnnotation = nil + return + + default: + return + } } - + func remove(_ annotation: PointAnnotation) { manager.annotations.removeAll(where: {$0.id == annotation.id}) } - + func add(_ annotation: PointAnnotation) { manager.annotations.append(annotation) manager.syncSourceAndLayerIfNeeded() } - + func update(_ annotation: PointAnnotation) { let index = manager.annotations.firstIndex { $0.id == annotation.id } - + guard let index = index else { Logger.log(level: .warn, message: "RCTMGL - PointAnnotation.refresh: annotation not found") return } - + manager.annotations[index] = annotation manager.syncSourceAndLayerIfNeeded() } diff --git a/ios/RCTMGL-v10/RCTMGLMapViewManager.swift b/ios/RCTMGL-v10/RCTMGLMapViewManager.swift index 377d78e5a..89d9e2551 100644 --- a/ios/RCTMGL-v10/RCTMGLMapViewManager.swift +++ b/ios/RCTMGL-v10/RCTMGLMapViewManager.swift @@ -2,101 +2,99 @@ import MapboxMaps @objc(RCTMGLMapViewManager) class RCTMGLMapViewManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - func defaultFrame() -> CGRect { - return UIScreen.main.bounds - } - - override func view() -> UIView! { - let result = RCTMGLMapView(frame: self.defaultFrame()) - return result - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + func defaultFrame() -> CGRect { + return UIScreen.main.bounds + } + + override func view() -> UIView! { + let result = RCTMGLMapView(frame: self.defaultFrame()) + return result + } } // MARK: helpers extension RCTMGLMapViewManager { - func withMapView( - _ reactTag: NSNumber, - name: String, - rejecter: @escaping RCTPromiseRejectBlock, - fn: @escaping (_: RCTMGLMapView) -> Void) -> Void - { - self.bridge.uiManager.addUIBlock { (manager, viewRegistry) in - let view = viewRegistry![reactTag] - - guard let view = view, let view = view as? RCTMGLMapView else { - RCTMGLLogError("Invalid react tag, could not find RCTMGLMapView"); - rejecter(name, "Unknown find reactTag: \(reactTag)", nil) - return; - } - - fn(view) + func withMapView( + _ reactTag: NSNumber, + name: String, + rejecter: @escaping RCTPromiseRejectBlock, + fn: @escaping (_: RCTMGLMapView) -> Void) { + self.bridge.uiManager.addUIBlock { (_, viewRegistry) in + let view = viewRegistry![reactTag] + + guard let view = view, let view = view as? RCTMGLMapView else { + RCTMGLLogError("Invalid react tag, could not find RCTMGLMapView") + rejecter(name, "Unknown find reactTag: \(reactTag)", nil) + return } + + fn(view) } + } - func withMapboxMap( - _ reactTag: NSNumber, - name: String, - rejecter: @escaping RCTPromiseRejectBlock, - fn: @escaping (_: MapboxMap) -> Void) -> Void - { - withMapView(reactTag, name: name, rejecter: rejecter) { view in - guard let mapboxMap = view.mapboxMap else { - RCTMGLLogError("MapboxMap is not yet available"); - rejecter(name, "Map not loaded yet", nil) - return; - } - - fn(mapboxMap) + func withMapboxMap( + _ reactTag: NSNumber, + name: String, + rejecter: @escaping RCTPromiseRejectBlock, + fn: @escaping (_: MapboxMap) -> Void) { + withMapView(reactTag, name: name, rejecter: rejecter) { view in + guard let mapboxMap = view.mapboxMap else { + RCTMGLLogError("MapboxMap is not yet available") + rejecter(name, "Map not loaded yet", nil) + return } + + fn(mapboxMap) } + } } // MARK: - react methods extension RCTMGLMapViewManager { - @objc - func takeSnap(_ reactTag: NSNumber, - writeToDisk: Bool, - resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock - ) -> Void { - withMapView(reactTag, name:"takeSnap", rejecter: rejecter) { view in - let uri = view.takeSnap(writeToDisk: writeToDisk) - resolver(["uri": uri.absoluteString]) - } + @objc + func takeSnap(_ reactTag: NSNumber, + writeToDisk: Bool, + resolver: @escaping RCTPromiseResolveBlock, + rejecter: @escaping RCTPromiseRejectBlock + ) { + withMapView(reactTag, name: "takeSnap", rejecter: rejecter) { view in + let uri = view.takeSnap(writeToDisk: writeToDisk) + resolver(["uri": uri.absoluteString]) } - - @objc - func queryTerrainElevation(_ reactTag: NSNumber, - coordinates: [NSNumber], - resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock - ) -> Void { - withMapView(reactTag, name:"queryTerrainElevation", rejecter: rejecter) { view in - let result = view.queryTerrainElevation(coordinates: coordinates) - if let result = result { - resolver(["data": NSNumber(value: result)]) - } else { - resolver(nil) - } + } + + @objc + func queryTerrainElevation(_ reactTag: NSNumber, + coordinates: [NSNumber], + resolver: @escaping RCTPromiseResolveBlock, + rejecter: @escaping RCTPromiseRejectBlock + ) { + withMapView(reactTag, name: "queryTerrainElevation", rejecter: rejecter) { view in + let result = view.queryTerrainElevation(coordinates: coordinates) + if let result = result { + resolver(["data": NSNumber(value: result)]) + } else { + resolver(nil) } } - + } + @objc func setSourceVisibility(_ reactTag: NSNumber, - visible: Bool, - sourceId: String, - sourceLayerId: String?, - resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock) -> Void { - withMapView(reactTag, name:"setSourceVisibility", rejecter: rejecter) { view in - view.setSourceVisibility(visible, sourceId: sourceId, sourceLayerId:sourceLayerId) + visible: Bool, + sourceId: String, + sourceLayerId: String?, + resolver: @escaping RCTPromiseResolveBlock, + rejecter: @escaping RCTPromiseRejectBlock) { + withMapView(reactTag, name: "setSourceVisibility", rejecter: rejecter) { view in + view.setSourceVisibility(visible, sourceId: sourceId, sourceLayerId: sourceLayerId) resolver(nil) } } @@ -104,8 +102,8 @@ extension RCTMGLMapViewManager { @objc func getCenter(_ reactTag: NSNumber, resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock) -> Void { - withMapboxMap(reactTag, name:"getCenter", rejecter: rejecter) { mapboxMap in + rejecter: @escaping RCTPromiseRejectBlock) { + withMapboxMap(reactTag, name: "getCenter", rejecter: rejecter) { mapboxMap in resolver(["center": [ mapboxMap.cameraState.center.longitude, mapboxMap.cameraState.center.latitude @@ -119,10 +117,10 @@ extension RCTMGLMapViewManager { atPoint point: CGPoint, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { - withMapboxMap(reactTag, name:"getCoordinateFromView", rejecter: rejecter) { mapboxMap in - let coordinates = mapboxMap.coordinate(for: point) - resolver(["coordinateFromView": [coordinates.longitude, coordinates.latitude]]) - } + withMapboxMap(reactTag, name: "getCoordinateFromView", rejecter: rejecter) { mapboxMap in + let coordinates = mapboxMap.coordinate(for: point) + resolver(["coordinateFromView": [coordinates.longitude, coordinates.latitude]]) + } } @objc @@ -131,11 +129,11 @@ extension RCTMGLMapViewManager { atCoordinate coordinate: [NSNumber], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { - withMapboxMap(reactTag, name:"getPointInView", rejecter: rejecter) { mapboxMap in - let coordinate = CLLocationCoordinate2DMake(coordinate[1].doubleValue, coordinate[0].doubleValue) - let point = mapboxMap.point(for: coordinate) - resolver(["pointInView": [(point.x), (point.y)]]) - } + withMapboxMap(reactTag, name: "getPointInView", rejecter: rejecter) { mapboxMap in + let coordinate = CLLocationCoordinate2DMake(coordinate[1].doubleValue, coordinate[0].doubleValue) + let point = mapboxMap.point(for: coordinate) + resolver(["pointInView": [(point.x), (point.y)]]) + } } @objc @@ -144,11 +142,11 @@ extension RCTMGLMapViewManager { events: [String], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { - withMapView(reactTag, name:"setHandledMapChangedEvents", rejecter: rejecter) { mapView in + withMapView(reactTag, name: "setHandledMapChangedEvents", rejecter: rejecter) { mapView in mapView.handleMapChangedEvents = Set(events.compactMap { RCTMGLEvent.EventType(rawValue: $0) }) - resolver(nil); + resolver(nil) } } @@ -157,9 +155,9 @@ extension RCTMGLMapViewManager { _ reactTag: NSNumber, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { - withMapboxMap(reactTag, name:"getZoom", rejecter: rejecter) { mapboxMap in - resolver(["zoom": mapboxMap.cameraState.zoom]) - } + withMapboxMap(reactTag, name: "getZoom", rejecter: rejecter) { mapboxMap in + resolver(["zoom": mapboxMap.cameraState.zoom]) + } } @objc @@ -167,9 +165,9 @@ extension RCTMGLMapViewManager { _ reactTag: NSNumber, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { - withMapView(reactTag, name:"getVisibleBounds", rejecter: rejecter) { mapView in - resolver(["visibleBounds": mapView.mapboxMap.coordinateBounds(for: mapView.bounds).toArray()]) - } + withMapView(reactTag, name: "getVisibleBounds", rejecter: rejecter) { mapView in + resolver(["visibleBounds": mapView.mapboxMap.coordinateBounds(for: mapView.bounds).toArray()]) + } } } @@ -183,27 +181,28 @@ extension RCTMGLMapViewManager { withFilter filter: [Any]?, withLayerIDs layerIDs: [String]?, resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock) -> Void { - withMapboxMap(reactTag, name:"queryRenderedFeaturesAtPoint", rejecter: rejecter) { mapboxMap 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()) - - mapboxMap.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) - } + rejecter: @escaping RCTPromiseRejectBlock) { + withMapboxMap(reactTag, name: "queryRenderedFeaturesAtPoint", rejecter: rejecter) { mapboxMap 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()) + + mapboxMap.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 @@ -213,28 +212,29 @@ extension RCTMGLMapViewManager { withFilter filter: [Any]?, withLayerIDs layerIDs: [String]?, resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock) -> Void { - withMapView(reactTag, name:"queryRenderedFeaturesInRect", rejecter: rejecter) { mapView in - let top = bbox.isEmpty ? 0.0 : CGFloat(bbox[0].floatValue) - let right = bbox.isEmpty ? 0.0 : CGFloat(bbox[1].floatValue) - let bottom = bbox.isEmpty ? 0.0 : CGFloat(bbox[2].floatValue) - let left = bbox.isEmpty ? 0.0 : CGFloat(bbox[3].floatValue) - let rect = bbox.isEmpty ? CGRect(x: 0.0, y: 0.0, width: mapView.bounds.size.width, height: mapView.bounds.size.height) : CGRect(x: [left,right].min()!, y: [top,bottom].min()!, width: abs(right-left), height: abs(bottom-top)) - logged("queryRenderedFeaturesInRect.option", rejecter: rejecter) { - let options = try RenderedQueryOptions(layerIds: layerIDs?.isEmpty ?? true ? nil : layerIDs, filter: filter?.asExpression()) - mapView.mapboxMap.queryRenderedFeatures(with: rect, options: options) { result in - switch result { - case .success(let features): - resolver([ - "data": ["type": "FeatureCollection", "features": features.compactMap { queriedFeature in - logged("queryRenderedFeaturesInRect.queriedfeature.map") { try queriedFeature.feature.toJSON() } - }] - ]) - case .failure(let error): - rejecter("queryRenderedFeaturesInRect","failed to query features", error) - } + rejecter: @escaping RCTPromiseRejectBlock) { + withMapView(reactTag, name: "queryRenderedFeaturesInRect", rejecter: rejecter) { mapView in + let top = bbox.isEmpty ? 0.0 : CGFloat(bbox[0].floatValue) + let right = bbox.isEmpty ? 0.0 : CGFloat(bbox[1].floatValue) + let bottom = bbox.isEmpty ? 0.0 : CGFloat(bbox[2].floatValue) + let left = bbox.isEmpty ? 0.0 : CGFloat(bbox[3].floatValue) + let rect = bbox.isEmpty ? CGRect(x: 0.0, y: 0.0, width: mapView.bounds.size.width, height: mapView.bounds.size.height) : CGRect(x: [left, right].min()!, y: [top, bottom].min()!, width: abs(right - left), height: abs(bottom - top)) + logged("queryRenderedFeaturesInRect.option", rejecter: rejecter) { + let options = try RenderedQueryOptions(layerIds: layerIDs?.isEmpty ?? true ? nil : layerIDs, filter: filter?.asExpression()) + mapView.mapboxMap.queryRenderedFeatures(with: rect, options: options) { result in + switch result { + case .success(let features): + resolver([ + "data": ["type": "FeatureCollection", "features": features.compactMap { queriedFeature in + logged("queryRenderedFeaturesInRect.queriedfeature.map") { try queriedFeature.feature.toJSON() } + }] + ]) + + case .failure(let error): + rejecter("queryRenderedFeaturesInRect", "failed to query features", error) } } } - } + } + } } diff --git a/ios/RCTMGL-v10/RCTMGLMarkerView.swift b/ios/RCTMGL-v10/RCTMGLMarkerView.swift index 9585542cd..3570120f2 100644 --- a/ios/RCTMGL-v10/RCTMGLMarkerView.swift +++ b/ios/RCTMGL-v10/RCTMGLMarkerView.swift @@ -3,12 +3,12 @@ import UIKit /// dummy parent of RCTMGLMarkerView, so react-native changes visibility on RCTMGLMarkerView, /// and Mapbox changes visibility on RCTMGLMarkerViewParentViewAnnotation -class RCTMGLMarkerViewParentViewAnnotation : UIView { +class RCTMGLMarkerViewParentViewAnnotation: UIView { required init(marker: RCTMGLMarkerView) { super.init(frame: marker.bounds) insertSubview(marker, at: 0) } - + required init?(coder: NSCoder) { fatalError("not implented") } @@ -20,8 +20,8 @@ class RCTMGLMarkerViewParentViewAnnotation : UIView { func updateSize(_ size: CGSize, oldOffset: CGVector, newOffset: CGVector) { let actSize = self.frame.size if actSize.width != size.width || actSize.height != size.height { - let dx = ((size.width/2.0) - newOffset.dx) - ((actSize.width/2.0) - oldOffset.dx) - let dy = ((size.height/2.0) + newOffset.dy) - ((actSize.height/2.0) + oldOffset.dy) + let dx = ((size.width / 2.0) - newOffset.dx) - ((actSize.width / 2.0) - oldOffset.dx) + let dy = ((size.height / 2.0) + newOffset.dy) - ((actSize.height / 2.0) + oldOffset.dy) print(" => size=\(size) actSize=\(actSize) newOffset=\(newOffset) oldOffset=\(oldOffset) dx=\(dx) dy=\(dy)") var frame = self.frame frame = frame.offsetBy(dx: -dx, dy: -dy) @@ -33,41 +33,41 @@ class RCTMGLMarkerViewParentViewAnnotation : UIView { class RCTMGLMarkerView: UIView, RCTMGLMapComponent { // MARK: - Instance variables - + static let key = "RCTMGLMarkerView" let id: String = "marker-\(UUID().uuidString)" - + weak var map: RCTMGLMapView? weak var _annotationView: RCTMGLMarkerViewParentViewAnnotation? - + var didAddToMap = false - + @objc var coordinate: String? { didSet { update() } } - + @objc var anchor: [String: NSNumber]? { didSet { update() } } - - @objc var allowOverlap: Bool = false { + + @objc var allowOverlap = false { didSet { update() } } - - @objc var isSelected: Bool = false { + + @objc var isSelected = false { didSet { update() } } // MARK: - Derived variables - + var annotationManager: ViewAnnotationManager? { self.map?.viewAnnotations } @@ -77,17 +77,17 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent { Logger.log(level: .error, message: "[getPoint] No coordinates were set") return nil } - + guard let _data = _coordinate.data(using: .utf8) else { Logger.log(level: .error, message: "[getPoint] Cannot serialize coordinate") return nil } - + guard let _feature = try? JSONDecoder().decode(Feature.self, from: _data) else { Logger.log(level: .error, message: "[getPoint] Cannot parse serialized coordinate") return nil } - + guard let _geometry = _feature.geometry else { Logger.log(level: .error, message: "[getPoint] Invalid geometry") return nil @@ -111,9 +111,9 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent { func removeFromMap(_ map: RCTMGLMapView) { remove() } - + // MARK: - React methods - + override var isHidden: Bool { get { return super.isHidden @@ -122,11 +122,11 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent { super.isHidden = newValue } } - + override func reactSetFrame(_ frame: CGRect) { let prev = self.frame var next = frame - + let frameDidChange = !next.equalTo(prev) if frameDidChange { next = CGRect( @@ -139,39 +139,39 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent { super.reactSetFrame(next) if frameDidChange { - annotationView.updateSize(next.size, oldOffset:calcOffset(size: prev.size), newOffset: calcOffset(size: next.size)) + annotationView.updateSize(next.size, oldOffset: calcOffset(size: prev.size), newOffset: calcOffset(size: next.size)) } addOrUpdate() } - + override func insertReactSubview(_ subview: UIView, at atIndex: Int) { super.insertReactSubview(subview, at: atIndex) } - + override func removeReactSubview(_ subview: UIView) { super.removeReactSubview(subview) } - + func waitForStyleLoad() -> Bool { true } // MARK: - Create, update, and remove methods - private func addOrUpdate() { - if didAddToMap { - update() - } else { - add() - } + private func addOrUpdate() { + if didAddToMap { + update() + } else { + add() } - + } + /// Because the necessary data to add an annotation arrives from different sources at unpredictable times, we let the arrival of each value trigger an attempt to add the annotation, which we only do if all of the data exists, and the annotation not been added already. private func add() { if didAddToMap { return } - + guard let annotationManager = annotationManager, let _ = point else { return } @@ -189,11 +189,11 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent { if !didAddToMap { return } - + guard let annotationManager = annotationManager else { return } - + do { let options = getOptions() try annotationManager.update(annotationView, options: options) @@ -201,25 +201,25 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent { Logger.log(level: .error, message: "[MarkerView] Error updating annotation", error: error) } } - + private func remove() { annotationManager?.remove(annotationView) annotationView.remove(marker: self) self._annotationView = nil didAddToMap = false } - + // MARK: - Helper functions - + private func getOptions() -> ViewAnnotationOptions { var geometry: GeometryConvertible? if let point = point { geometry = Geometry.point(point) } - + let size = self.bounds.size let offset = calcOffset(size: size) - + let options = ViewAnnotationOptions( geometry: geometry, width: size.width, @@ -231,19 +231,19 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent { ) return options } - + private func calcOffset(size: CGSize) -> CGVector { guard let anchor = anchor, let anchorX = anchor["x"]?.CGFloat, let anchorY = anchor["y"]?.CGFloat else { return .zero } - + let x = (anchorX * 2 - 1) * (size.width / 2) * -1 let y = (anchorY * 2 - 1) * (size.height / 2) return CGVector(dx: x, dy: y) } - - var annotationView : RCTMGLMarkerViewParentViewAnnotation { + + var annotationView: RCTMGLMarkerViewParentViewAnnotation { if let result = _annotationView { return result } diff --git a/ios/RCTMGL-v10/RCTMGLMarkerViewManager.swift b/ios/RCTMGL-v10/RCTMGLMarkerViewManager.swift index a1218f179..885a3ad4b 100644 --- a/ios/RCTMGL-v10/RCTMGLMarkerViewManager.swift +++ b/ios/RCTMGL-v10/RCTMGLMarkerViewManager.swift @@ -2,12 +2,12 @@ import Foundation import MapboxMaps @objc(RCTMGLMarkerViewManager) -class RCTMGLMarkerViewManager : RCTViewManager { +class RCTMGLMarkerViewManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true } - + override func view() -> UIView! { return RCTMGLMarkerView() } diff --git a/ios/RCTMGL-v10/RCTMGLNativeUserLocation.swift b/ios/RCTMGL-v10/RCTMGLNativeUserLocation.swift index 90cfc5ca3..9c0844fbb 100644 --- a/ios/RCTMGL-v10/RCTMGLNativeUserLocation.swift +++ b/ios/RCTMGL-v10/RCTMGLNativeUserLocation.swift @@ -1,23 +1,23 @@ import MapboxMaps @objc -class RCTMGLNativeUserLocation : UIView, RCTMGLMapComponent { - weak var map : RCTMGLMapView! = nil - +class RCTMGLNativeUserLocation: UIView, RCTMGLMapComponent { + weak var map: RCTMGLMapView! = nil + let locationLayerId = "location-layer" - var locationLayer : LocationIndicatorLayer? = nil + var locationLayer: LocationIndicatorLayer? @objc - var iosShowsUserHeadingIndicator : Bool = false { + var iosShowsUserHeadingIndicator = false { didSet { if let map = self.map { _applySettings(map) } } } - + func _applySettings(_ map: RCTMGLMapView) { map.location.options.puckType = .puck2D(.makeDefault(showBearing: iosShowsUserHeadingIndicator)) - if (iosShowsUserHeadingIndicator) { + if iosShowsUserHeadingIndicator { map.location.options.puckBearingSource = .heading map.location.options.puckBearingEnabled = true } else { @@ -39,7 +39,7 @@ class RCTMGLNativeUserLocation : UIView, RCTMGLMapComponent { map.location.options.puckType = .none self.map = nil } - + func waitForStyleLoad() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLNativeUserLocationManager.swift b/ios/RCTMGL-v10/RCTMGLNativeUserLocationManager.swift index e9b9d3d4b..9b9a2569d 100644 --- a/ios/RCTMGL-v10/RCTMGLNativeUserLocationManager.swift +++ b/ios/RCTMGL-v10/RCTMGLNativeUserLocationManager.swift @@ -1,5 +1,5 @@ @objc(RCTMGLNativeUserLocationManager) -class RCTMGLNativeUserLocationManager : RCTViewManager { +class RCTMGLNativeUserLocationManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true diff --git a/ios/RCTMGL-v10/RCTMGLOfflineModule.swift b/ios/RCTMGL-v10/RCTMGLOfflineModule.swift index b75667099..ae3ac406d 100644 --- a/ios/RCTMGL-v10/RCTMGLOfflineModule.swift +++ b/ios/RCTMGL-v10/RCTMGLOfflineModule.swift @@ -11,51 +11,49 @@ extension Date { } } - - @objc(RCTMGLOfflineModule) class RCTMGLOfflineModule: RCTEventEmitter { var hasListeners = false - + static let RNMapboxInfoMetadataKey = "_rnmapbox" - enum Callbacks : String { + enum Callbacks: String { case error = "MapboOfflineRegionError" case progress = "MapboxOfflineRegionProgress" } - - enum State : String { + + enum State: String { case invalid case inactive case active case complete case unknown } - - lazy var offlineManager : OfflineManager = { + + lazy var offlineManager: OfflineManager = { return OfflineManager(resourceOptions: .init(accessToken: MGLModule.accessToken!)) }() - + lazy var offlineRegionManager: OfflineRegionManager = { return OfflineRegionManager(resourceOptions: .init(accessToken: MGLModule.accessToken!)) }() - lazy var tileStore : TileStore = { + lazy var tileStore: TileStore = { return TileStore.default }() - + struct TileRegionPack { - init(name: String, state: State = .unknown, progress: TileRegionLoadProgress? = nil, metadata: [String:Any]) { + init(name: String, state: State = .unknown, progress: TileRegionLoadProgress? = nil, metadata: [String: Any]) { self.name = name self.progress = progress self.metadata = metadata self.state = state - if let rnMetadata = metadata[RNMapboxInfoMetadataKey] as? [String:Any] { + if let rnMetadata = metadata[RNMapboxInfoMetadataKey] as? [String: Any] { if let styleURI = rnMetadata["styleURI"] as? String { self.styleURI = StyleURI(rawValue: styleURI) } - if let bounds = rnMetadata["bounds"] as? [String:Any] { + if let bounds = rnMetadata["bounds"] as? [String: Any] { self.bounds = logged("RCTMGLOfflineModule.TileRegionPack: cannot decode bounds") { let jsonData = try JSONSerialization.data(withJSONObject: bounds) return try JSONDecoder().decode(Geometry.self, from: jsonData) @@ -69,22 +67,22 @@ class RCTMGLOfflineModule: RCTEventEmitter { } } } - + init(name: String, state: State = .unknown, styleURI: StyleURI, bounds: Geometry, zoomRange: ClosedRange, - metadata: [String:Any]) { + metadata: [String: Any]) { self.name = name self.progress = nil self.cancelable = nil self.state = state - + self.styleURI = styleURI self.bounds = bounds self.zoomRange = zoomRange - + var metadata = metadata metadata[RNMapboxInfoMetadataKey] = [ "styleURI": styleURI.rawValue, @@ -95,20 +93,20 @@ class RCTMGLOfflineModule: RCTEventEmitter { } var name: String - var cancelable: Cancelable? = nil - var progress : TileRegionLoadProgress? = nil - var state : State = .inactive - var metadata : [String:Any] + var cancelable: Cancelable? + var progress: TileRegionLoadProgress? + var state: State = .inactive + var metadata: [String: Any] // Stored in metadata for resume functionality: - var bounds: Geometry? = nil - var zoomRange: ClosedRange? = nil - var styleURI: StyleURI? = nil - } - - lazy var tileRegionPacks : [String: TileRegionPack] = [:] - - var progressEventThrottle : ( + var bounds: Geometry? + var zoomRange: ClosedRange? + var styleURI: StyleURI? + } + + lazy var tileRegionPacks: [String: TileRegionPack] = [:] + + var progressEventThrottle: ( waitBetweenEvents: Double?, lastSentTimestamp: Double?, lastSentState: State? @@ -117,25 +115,25 @@ class RCTMGLOfflineModule: RCTEventEmitter { nil, nil ) - + @objc override func startObserving() { super.startObserving() hasListeners = true } - + @objc override func stopObserving() { super.stopObserving() hasListeners = false } - + @objc override static func requiresMainQueueSetup() -> Bool { return true } - + @objc override func constantsToExport() -> [AnyHashable: Any]! { @@ -147,24 +145,24 @@ class RCTMGLOfflineModule: RCTEventEmitter { func supportedEvents() -> [String] { return [Callbacks.error.rawValue, Callbacks.progress.rawValue] } - + // MARK: react methods - + @objc func createPack(_ options: NSDictionary, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { DispatchQueue.main.async { do { let metadataStr = options["metadata"] as! String - var metadata = try JSONSerialization.jsonObject(with: metadataStr.data(using: .utf8)!, options: []) as! [String:Any] + var metadata = try JSONSerialization.jsonObject(with: metadataStr.data(using: .utf8)!, options: []) as! [String: Any] metadata["styleURI"] = options["styleURL"] let id = metadata["name"] as! String - + let boundsStr = options["bounds"] as! String let boundsData = boundsStr.data(using: .utf8) var boundsFC = try JSONDecoder().decode(FeatureCollection.self, from: boundsData!) - + var bounds = self.convertPointPairToBounds(RCTMGLFeatureUtils.fcToGeomtry(boundsFC)) - + let actPack = RCTMGLOfflineModule.TileRegionPack( name: id, styleURI: StyleURI(rawValue: options["styleURL"] as! String)!, @@ -174,17 +172,17 @@ class RCTMGLOfflineModule: RCTEventEmitter { ) self.tileRegionPacks[id] = actPack self.startLoading(pack: actPack) - + resolver([ "bounds": boundsStr, - "metadata": String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8) + "metadata": String(data: try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8) ]) } catch { rejecter("createPack", error.localizedDescription, error) } } } - + @objc func getPackStatus(_ name: String, resolver: @escaping RCTPromiseResolveBlock, @@ -193,26 +191,26 @@ class RCTMGLOfflineModule: RCTEventEmitter { rejecter("RCTMGLOfflineModule.getPackStatus", "pack \(name) not found", nil) return } - + tileStore.tileRegionMetadata(forId: name) { result in switch result { case .success(let metadata): var pack = TileRegionPack( name: name, - metadata: logged("RCTMGLOfflineModule.getPackStatus") { metadata as? [String:Any] } ?? [:] + metadata: logged("RCTMGLOfflineModule.getPackStatus") { metadata as? [String: Any] } ?? [:] ) self.tileRegionPacks[name] = pack resolver(self._makeRegionStatusPayload(pack: pack)) + case .failure(let error): - Logger.log(level:.error, message: "Unable to fetch metadata for \(name)") + Logger.log(level: .error, message: "Unable to fetch metadata for \(name)") rejecter("RCTMGLOfflineModule.getPackStatus", error.localizedDescription, error) } } } - + @objc - func resumePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) - { + func resumePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) { if let pack = tileRegionPacks[name] { startLoading(pack: pack) resolver(nil) @@ -220,10 +218,9 @@ class RCTMGLOfflineModule: RCTEventEmitter { rejecter("resumePackDownload", "Unknown offline pack: \(name)", nil) } } - + @objc - func pausePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) - { + func pausePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) { if let pack = tileRegionPacks[name] { if let cancelable = pack.cancelable { cancelable.cancel() @@ -236,40 +233,38 @@ class RCTMGLOfflineModule: RCTEventEmitter { rejecter("pausePackDownload", "Unknown offline region: \(name)", nil) } } - + @objc func setTileCountLimit(_ limit: NSNumber) { self.offlineRegionManager.setOfflineMapboxTileCountLimitForLimit(limit.uint64Value) } - - + @objc func deletePack(_ name: String, resolver: RCTPromiseResolveBlock, - rejecter: RCTPromiseRejectBlock) - { + rejecter: RCTPromiseRejectBlock) { guard let pack = tileRegionPacks[name] else { return resolver(nil) } - + guard pack.state != .invalid else { return rejecter("deletePack", "Pack: \(name) has already been deleted", nil) } - + tileStore.removeTileRegion(forId: name) tileRegionPacks[name]!.state = .invalid resolver(nil) } - + @objc - func migrateOfflineCache(_ resolve : @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + func migrateOfflineCache(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { // Old and new cache file paths let srcURL = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("/Library/Application Support/com.mapbox.examples/.mapbox/cache.db") - + let destURL = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("/Library/Application Support/.mapbox/map_data/map_data.db") - + let fileManager = FileManager.default - + do { try fileManager.createDirectory(at: destURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil) try fileManager.moveItem(at: srcURL, to: destURL) @@ -278,7 +273,7 @@ class RCTMGLOfflineModule: RCTEventEmitter { reject("migrateOfflineCache", error.localizedDescription, error) } } - + @objc func resetDatabase(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { self.tileStore.allTileRegions { result in @@ -291,38 +286,41 @@ class RCTMGLOfflineModule: RCTEventEmitter { switch result { case .success(let packs): packs.forEach { pack in - if let url = logged("RCTMGLOfflineModule.resetDatabase invalid styleURI",fn: { return URL(string: pack.styleURI) }), + if let url = logged("RCTMGLOfflineModule.resetDatabase invalid styleURI", fn: { return URL(string: pack.styleURI) }), let styleUri = logged("RCTMGLOfflineModule.resetDatabase invalid styleURI2", fn: { return StyleURI(url: url) }) { self.offlineManager.removeStylePack(for: styleUri) } } resolve(nil) + case .failure(let error): - Logger.log(level:.error, message: "RCTMGLOfflineModule.resetDatabase/allStylePacks \(error.localizedDescription) \(error)") + Logger.log(level: .error, message: "RCTMGLOfflineModule.resetDatabase/allStylePacks \(error.localizedDescription) \(error)") reject("RCTMGLOfflineModule.resetDatabase/allStylePacks", error.localizedDescription, error) } } + case .failure(let error): - Logger.log(level:.error, message: "RCTMGLOfflineModule.resetDatabase/allTileRegions \(error.localizedDescription) \(error)") + Logger.log(level: .error, message: "RCTMGLOfflineModule.resetDatabase/allTileRegions \(error.localizedDescription) \(error)") reject("RCTMGLOfflineModule.resetDatabase/allTileRegions", error.localizedDescription, error) } } } - + @objc - func getPacks(_ resolve : @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { + func getPacks(_ resolve: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { DispatchQueue.main.async { self.tileStore.allTileRegions { result in switch result { case .success(let regions): self.convertRegionsToJSON(regions: regions, resolve: resolve, rejecter: rejecter) + case .failure(let error): rejecter("TileStoreError", error.localizedDescription, error) } } } } - + func startLoading(pack: TileRegionPack) { let id = pack.name let metadata = pack.metadata @@ -338,16 +336,16 @@ class RCTMGLOfflineModule: RCTEventEmitter { RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no styleURI in pack") return } - + let stylePackLoadOptions = StylePackLoadOptions(glyphsRasterizationMode: .ideographsRasterizedLocally, metadata: pack.metadata) - + let descriptorOptions = TilesetDescriptorOptions( styleURI: styleURI, zoomRange: zoomRange, stylePackOptions: stylePackLoadOptions ) let tilesetDescriptor = self.offlineManager.createTilesetDescriptor(for: descriptorOptions) - + let loadOptions = TileRegionLoadOptions( geometry: bounds, // RCTMGLFeatureUtils.geometryToGeometry(bounds), descriptors: [tilesetDescriptor], @@ -355,8 +353,8 @@ class RCTMGLOfflineModule: RCTEventEmitter { acceptExpired: true, networkRestriction: .none, averageBytesPerSecond: nil) - - var lastProgress : TileRegionLoadProgress? = nil + + var lastProgress: TileRegionLoadProgress? let task = self.tileStore.loadTileRegion(forId: id, loadOptions: loadOptions!, progress: { progress in lastProgress = progress @@ -375,6 +373,7 @@ class RCTMGLOfflineModule: RCTEventEmitter { } self.tileRegionPacks[id]!.state = .complete } + case .failure(let error): DispatchQueue.main.async { self.tileRegionPacks[id]!.state = .inactive @@ -384,13 +383,13 @@ class RCTMGLOfflineModule: RCTEventEmitter { } self.tileRegionPacks[id]!.cancelable = task } - + func convertRegionsToJSON(regions: [TileRegion], resolve: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) { let taskGroup = DispatchGroup() - - var geomteryResults : [String: (Result,TileRegion)] = [:] - var metadataResults : [String: Result] = [:] - + + var geomteryResults: [String: (Result, TileRegion)] = [:] + var metadataResults: [String: Result] = [:] + for region in regions { taskGroup.enter() taskGroup.enter() @@ -398,43 +397,46 @@ class RCTMGLOfflineModule: RCTEventEmitter { geomteryResults[region.id] = (result, region) taskGroup.leave() } - + tileStore.tileRegionMetadata(forId: region.id) { (result) in metadataResults[region.id] = result taskGroup.leave() } } - + taskGroup.notify(queue: .main) { - let firstError = geomteryResults.first { (key,result_and_region) in + let firstError = geomteryResults.first { (_, result_and_region) in switch result_and_region.0 { case .failure: return true + case .success: return false } } - + if let firstError = firstError { switch firstError.value.0 { case .failure(let error): rejecter("convertRegionsToJSON", error.localizedDescription, error) return + case .success: fatalError("convertRegionsToJson:Expected failure but was success") } } - - let results = geomteryResults.map { (id, result) -> (String, (Geometry,TileRegion, [String:Any]?)) in + + let results = geomteryResults.map { (id, result) -> (String, (Geometry, TileRegion, [String: Any]?)) in switch result.0 { - case .failure(_): + case .failure: fatalError("convertRegionsToJson:Expected success but was failure") + case .success(let geometry): - return (id, (geometry,result.1,(try? metadataResults[id]?.get()) as? [String:Any])) + return (id, (geometry, result.1, (try? metadataResults[id]?.get()) as? [String: Any])) } } - - resolve(results.map { (id, geometry_region_metadata) -> [String:Any] in + + resolve(results.map { (_, geometry_region_metadata) -> [String: Any] in let (geometry, region, metadata) = geometry_region_metadata let ret = self.convertRegionToJSON(region: region, geometry: geometry, metadata: metadata) var pack = self.tileRegionPacks[region.id] ?? TileRegionPack( @@ -443,38 +445,38 @@ class RCTMGLOfflineModule: RCTEventEmitter { progress: self.toProgress(region: region), metadata: logged("RCTMGLOfflineModule.getPacks metadata is null") { metadata } ?? [:] ) - - if ((region.hasCompleted())) { + + if (region.hasCompleted()) { pack.state = .complete } - + self.tileRegionPacks[region.id] = pack - + return ret }) } } - - func convertRegionToJSON(region: TileRegion, geometry: Geometry, metadata: [String:Any]?) -> [String:Any] { + + func convertRegionToJSON(region: TileRegion, geometry: Geometry, metadata: [String: Any]?) -> [String: Any] { let bb = RCTMGLFeatureUtils.boundingBox(geometry: geometry) - + if let bb = bb { let jsonBounds = [ bb.northEast.longitude, bb.northEast.latitude, bb.southWest.longitude, bb.southWest.latitude ] - + let completed = (region.completedResourceCount == region.requiredResourceCount) - var metadata : [String:Any] = metadata ?? [:] + var metadata: [String: Any] = metadata ?? [:] metadata["name"] = region.id - - var result : [String:Any] = [ + + var result: [String: Any] = [ "requiredResourceCount": region.requiredResourceCount, "completedResourceCount": region.completedResourceCount, "completedResourceSize": region.completedResourceSize, "state": completed ? State.complete.rawValue : State.unknown.rawValue, - "metadata": String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8), + "metadata": String(data: try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8), "bounds": jsonBounds ] @@ -486,15 +488,14 @@ class RCTMGLOfflineModule: RCTEventEmitter { if let expires = region.expires { result["expires"] = expires.toJSONString() } - } return [:] } - + func toProgress(region: TileRegion) -> TileRegionLoadProgress? { return TileRegionLoadProgress(completedResourceCount: region.completedResourceCount, completedResourceSize: region.completedResourceSize, erroredResourceCount: 0, requiredResourceCount: region.requiredResourceCount, loadedResourceCount: 0, loadedResourceSize: 0) } - + func convertPointPairToBounds(_ bounds: Geometry) -> Geometry { guard case .geometryCollection(let gc) = bounds else { return bounds @@ -520,16 +521,16 @@ class RCTMGLOfflineModule: RCTEventEmitter { ] ])) } - - func _sendEvent(_ name:String, event: RCTMGLEvent) { + + func _sendEvent(_ name: String, event: RCTMGLEvent) { if !hasListeners { return } self.sendEvent(withName: name, body: event.toJSON()) } - func _makeRegionStatusPayload(_ name:String, progress: TileRegionLoadProgress?, state: State, metadata:[String:Any]?) -> [String:Any?] { - var result : [String:Any?] = [:] + func _makeRegionStatusPayload(_ name: String, progress: TileRegionLoadProgress?, state: State, metadata: [String: Any]?) -> [String: Any?] { + var result: [String: Any?] = [:] if let progress = progress { result = [ "state": (progress.hasCompleted()) ? State.complete.rawValue : state.rawValue, @@ -554,22 +555,22 @@ class RCTMGLOfflineModule: RCTEventEmitter { } return result } - - func _makeRegionStatusPayload(pack: TileRegionPack) -> [String:Any?] { + + func _makeRegionStatusPayload(pack: TileRegionPack) -> [String: Any?] { return _makeRegionStatusPayload(pack.name, progress: pack.progress, state: pack.state, metadata: pack.metadata) } - + func makeProgressEvent(_ name: String, progress: TileRegionLoadProgress, state: State) -> RCTMGLEvent { RCTMGLEvent(type: .offlineProgress, payload: self._makeRegionStatusPayload(name, progress: progress, state: state, metadata: nil)) } - - func offlinePackProgressDidChange(progress: TileRegionLoadProgress, metadata: [String:Any], state: State) { + + func offlinePackProgressDidChange(progress: TileRegionLoadProgress, metadata: [String: Any], state: State) { if self.shouldSendProgressEvent(progress: progress, state: state) { let event = makeProgressEvent(metadata["name"] as! String, progress: progress, state: state) self._sendEvent(Callbacks.progress.rawValue, event: event) } } - + func offlinePackDidReceiveError(name: String, error: Error) { let event = RCTMGLEvent(type: .offlineError, payload: ["name": name, "message": error.localizedDescription]) self._sendEvent(Callbacks.error.rawValue, event: event) @@ -582,36 +583,34 @@ extension RCTMGLOfflineModule { func setProgressEventThrottle(_ throttleValue: NSNumber) { progressEventThrottle.waitBetweenEvents = throttleValue.doubleValue } - - func shouldSendProgressEvent(progress: TileRegionLoadProgress, state: State) -> Bool - { + func shouldSendProgressEvent(progress: TileRegionLoadProgress, state: State) -> Bool { let currentTimestamp: Double = CACurrentMediaTime() * 1000.0 - + guard let lastSentState = progressEventThrottle.lastSentState, lastSentState == state else { progressEventThrottle.lastSentState = state progressEventThrottle.lastSentTimestamp = currentTimestamp return true } - + guard let waitBetweenEvents = progressEventThrottle.waitBetweenEvents, let lastSentTimestamp = progressEventThrottle.lastSentTimestamp else { progressEventThrottle.lastSentTimestamp = currentTimestamp - return true; + return true } - - if (currentTimestamp - lastSentTimestamp > waitBetweenEvents) { + + if currentTimestamp - lastSentTimestamp > waitBetweenEvents { progressEventThrottle.lastSentTimestamp = currentTimestamp - return true; + return true } - - return false; + + return false } } extension TileRegionLoadProgress { func toPercentage() -> Float { - return Float(100.0) * Float(completedResourceCount) / Float(requiredResourceCount); + return Float(100.0) * Float(completedResourceCount) / Float(requiredResourceCount) } func hasCompleted() -> Bool { return (completedResourceCount == requiredResourceCount) diff --git a/ios/RCTMGL-v10/RCTMGLPointAnnotation.swift b/ios/RCTMGL-v10/RCTMGLPointAnnotation.swift index 83922cae3..178e348c2 100644 --- a/ios/RCTMGL-v10/RCTMGLPointAnnotation.swift +++ b/ios/RCTMGL-v10/RCTMGLPointAnnotation.swift @@ -1,50 +1,49 @@ import MapboxMaps - final class WeakRef { weak var object: T? - + init(_ object: T) { self.object = object } } -class RCTMGLPointAnnotation : RCTMGLInteractiveElement { +class RCTMGLPointAnnotation: RCTMGLInteractiveElement { static let key = "RCTMGLPointAnnotation" - static var gid = 0; - - lazy var annotation : PointAnnotation = { + static var gid = 0 + + lazy var annotation: PointAnnotation = { var result = PointAnnotation(coordinate: CLLocationCoordinate2D()) result.isDraggable = false // we implement our own drag logic - result.userInfo = [RCTMGLPointAnnotation.key:WeakRef(self)] + result.userInfo = [RCTMGLPointAnnotation.key: WeakRef(self)] return result }() var added = false - weak var callout: RCTMGLCallout? = nil - var calloutId : String? - var image : UIImage? = nil - var reactSubviews : [UIView] = [] - - @objc var onDeselected: RCTBubblingEventBlock? = nil - @objc var onDrag: RCTBubblingEventBlock? = nil - @objc var onDragEnd: RCTBubblingEventBlock? = nil - @objc var onSelected: RCTBubblingEventBlock? = nil - - @objc var coordinate : String? { + weak var callout: RCTMGLCallout? + var calloutId: String? + var image: UIImage? + var reactSubviews: [UIView] = [] + + @objc var onDeselected: RCTBubblingEventBlock? + @objc var onDrag: RCTBubblingEventBlock? + @objc var onDragEnd: RCTBubblingEventBlock? + @objc var onSelected: RCTBubblingEventBlock? + + @objc var coordinate: String? { didSet { _updateCoordinate() } } - - @objc var anchor: [String:NSNumber] = [:] { + + @objc var anchor: [String: NSNumber] = [:] { didSet { update { annotation in _updateAnchor(&annotation) } } } - + func _updateAnchor(_ annotation: inout PointAnnotation) { if !anchor.isEmpty { if let image = annotation.image { @@ -63,21 +62,21 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement { annotation.point = point } } - + func point() -> Point? { guard let coordinate = coordinate else { return nil } - + guard let data = coordinate.data(using: .utf8) else { return nil } - + guard let feature = try? JSONDecoder().decode(Feature.self, from: data) else { return nil } - - guard let geometry : Geometry = feature.geometry else { + + guard let geometry: Geometry = feature.geometry else { return nil } @@ -87,35 +86,35 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement { return point } - + func changeImage(_ image: UIImage, initial: Bool = false) { self.image = image update { annotation in - let name = "rnview-\(gid())-\(annotation.id)" - annotation.image = PointAnnotation.Image(image: image , name: name) + let name = "rnview-\(gid())-\(annotation.id)" + annotation.image = PointAnnotation.Image(image: image, name: name) _updateAnchor(&annotation) } } - + func setAnnotationImage(inital: Bool = false) { if let image = _createViewSnapshot() { changeImage(image, initial: inital) } } - + func gid() -> Int { RCTMGLPointAnnotation.gid = RCTMGLPointAnnotation.gid + 1 return RCTMGLPointAnnotation.gid } - + @objc func refresh() { if let image = _createViewSnapshot() { changeImage(image) } } - + func _createViewSnapshot() -> UIImage? { let useDummyImage = false if useDummyImage { @@ -123,9 +122,9 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement { let renderer = UIGraphicsImageRenderer(size: size) let image = renderer.image { context in UIColor.darkGray.setStroke() - context.stroke(CGRect(x: 0, y:0, width: 32, height: 32)) - UIColor(red: 158/255, green: 215/255, blue: 245/255, alpha: 1).setFill() - context.fill(CGRect(x: 2, y: 2, width: 30, height: 30)) + context.stroke(CGRect(x: 0, y: 0, width: 32, height: 32)) + UIColor(red: 158 / 255, green: 215 / 255, blue: 245 / 255, alpha: 1).setFill() + context.fill(CGRect(x: 2, y: 2, width: 30, height: 30)) } return image } @@ -134,34 +133,33 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement { } return _createViewSnapshot(view: reactSubviews[0]) } - + func _createViewSnapshot(view: UIView) -> UIImage? { guard view.bounds.size.width > 0 && view.bounds.size.height > 0 else { return nil } - + let roundUp = 4 - + let adjustedSize = CGSize( - width: ((Int(view.bounds.size.width)+roundUp-1)/roundUp)*roundUp, - height: ((Int(view.bounds.size.height)+roundUp-1)/roundUp)*roundUp + width: ((Int(view.bounds.size.width) + roundUp - 1) / roundUp) * roundUp, + height: ((Int(view.bounds.size.height) + roundUp - 1) / roundUp) * roundUp ) - + let renderer = UIGraphicsImageRenderer(size: adjustedSize) let image = renderer.image { context in view.layer.render(in: context.cgContext) } return image } - + func onSelect() { if let callout = callout, let calloutImage = _createViewSnapshot(view: callout), let point = point() { - var calloutPtAnnotation = PointAnnotation(point: point) calloutId = calloutPtAnnotation.id - let name = "rnviewcallout-\(gid())-\(calloutPtAnnotation.id)" + let name = "rnviewcallout-\(gid())-\(calloutPtAnnotation.id)" calloutPtAnnotation.image = PointAnnotation.Image(image: calloutImage, name: name) if let size = image?.size { calloutPtAnnotation.iconOffset = [0, -size.height] @@ -169,13 +167,13 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement { self.map?.calloutAnnotationManager.annotations.append(calloutPtAnnotation) } } - + func onDeselect() { self.map?.calloutAnnotationManager.annotations.removeAll { $0.id == calloutId } } - + @objc override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { if let callout = subview as? RCTMGLCallout { @@ -203,9 +201,9 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement { reactSubviews.removeAll(where: { $0 == subview }) } } - + // MARK: - RCTMGLMapComponent - + override func addToMap(_ map: RCTMGLMapView, style: Style) { super.addToMap(map, style: style) self.map = map @@ -216,9 +214,9 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement { removeIfAdded() self.map = nil } - + // MARK: - RCTMGLInteractiveElement - + override func getLayerIDs() -> [String] { return [] } @@ -233,20 +231,20 @@ extension RCTMGLPointAnnotation { added = false } } - + @discardableResult func addIfPossible() -> Bool { if !added && annotation.point.coordinates.isValid() && (logged("PointAnnotation: missing id attribute") { return id }) != nil, - let pointAnnotationManager = map?.pointAnnotationManager { + let pointAnnotationManager = map?.pointAnnotationManager { pointAnnotationManager.add(annotation) added = true return true } return false } - + func update(callback: (_ annotation: inout PointAnnotation) -> Void) { callback(&annotation) if let pointAnnotationManager = map?.pointAnnotationManager { @@ -258,4 +256,3 @@ extension RCTMGLPointAnnotation { } } } - diff --git a/ios/RCTMGL-v10/RCTMGLPointAnnotationManager.swift b/ios/RCTMGL-v10/RCTMGLPointAnnotationManager.swift index 5164059f5..9dcf7c2c5 100644 --- a/ios/RCTMGL-v10/RCTMGLPointAnnotationManager.swift +++ b/ios/RCTMGL-v10/RCTMGLPointAnnotationManager.swift @@ -2,23 +2,22 @@ import Foundation import MapboxMaps @objc(RCTMGLPointAnnotationManager) -class RCTMGLPointAnnotationManager : RCTViewManager { +class RCTMGLPointAnnotationManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true } - + override func view() -> UIView! { return RCTMGLPointAnnotation() } @objc func refresh(_ reactTag: NSNumber, - resolver: RCTPromiseResolveBlock, - rejecter: RCTPromiseRejectBlock - ) - { - self.bridge.uiManager.addUIBlock { (manager, viewRegistry) in + resolver: RCTPromiseResolveBlock, + rejecter: RCTPromiseRejectBlock + ) { + self.bridge.uiManager.addUIBlock { (_, viewRegistry) in guard let view = viewRegistry?[reactTag] else { Logger.log(level: .error, message: "View with tag: \(reactTag) not found") return @@ -27,7 +26,7 @@ class RCTMGLPointAnnotationManager : RCTViewManager { Logger.log(level: .error, message: "View \(view) is not RCTMGLPointAnnotation") return } - + view.refresh() } } diff --git a/ios/RCTMGL-v10/RCTMGLRasterDemSource.swift b/ios/RCTMGL-v10/RCTMGLRasterDemSource.swift index 0c66fddfe..0f5663f96 100644 --- a/ios/RCTMGL-v10/RCTMGLRasterDemSource.swift +++ b/ios/RCTMGL-v10/RCTMGLRasterDemSource.swift @@ -1,35 +1,34 @@ import MapboxMaps @objc -class RCTMGLRasterDemSource : RCTMGLSource { +class RCTMGLRasterDemSource: RCTMGLSource { typealias SourceType = RasterDemSource - + @objc - var url: String? = nil - + var url: String? + @objc - var tileUrlTemplates: [String]? = nil - + var tileUrlTemplates: [String]? + @objc - var tileSize : NSNumber? = nil - + var tileSize: NSNumber? + @objc - var maxZoomLevel : NSNumber? = nil - + var maxZoomLevel: NSNumber? + @objc - var minZoomLevel : NSNumber? = nil + var minZoomLevel: NSNumber? @objc static func requiresMainQueueSetup() -> Bool { return true } - + override func sourceType() -> Source.Type { return SourceType.self } - override func makeSource() -> Source - { + override func makeSource() -> Source { var result = SourceType() if let url = url { result.url = url @@ -39,19 +38,18 @@ class RCTMGLRasterDemSource : RCTMGLSource { Logger.log(level: .error, message: "RCTMGLRasterDemSource should have either url or tileUrlTemplates ") return result } - + if let tileSize = tileSize { result.tileSize = tileSize.doubleValue } - + if let maxZoomLevel = maxZoomLevel { result.maxzoom = maxZoomLevel.doubleValue } if let minZoomLevel = minZoomLevel { result.minzoom = minZoomLevel.doubleValue - } + } return result - } + } } - diff --git a/ios/RCTMGL-v10/RCTMGLRasterLayer.swift b/ios/RCTMGL-v10/RCTMGLRasterLayer.swift index 6cceddfe9..86f06ec77 100644 --- a/ios/RCTMGL-v10/RCTMGLRasterLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLRasterLayer.swift @@ -11,26 +11,26 @@ class RCTMGLRasterLayer: RCTMGLLayer { return layer } - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: RasterLayer.self) { (layer : inout RasterLayer) in + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: RasterLayer.self) { (layer: inout RasterLayer) in if let styleLayer = self.styleLayer as? RasterLayer { layer = styleLayer } } } - + override func addStyles() { - if let style : Style = self.style, + if let style: Style = self.style, let reactStyle = reactStyle { - let styler = RCTMGLStyle(style: self.style!) + let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge - + if var styleLayer = self.styleLayer as? LayerType { styler.rasterLayer( layer: &styleLayer, reactStyle: reactStyle, oldReactStyle: oldReatStyle, - applyUpdater:{ (updater) in logged("RCTMGLRasterLayer.updateLayer") { + applyUpdater: { (updater) in logged("RCTMGLRasterLayer.updateLayer") { try style.updateLayer(withId: self.id, type: LayerType.self) { (layer: inout LayerType) in updater(&layer) } }}, isValid: { return self.isAddedToMap() } @@ -41,7 +41,7 @@ class RCTMGLRasterLayer: RCTMGLLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLRasterLayerManager.swift b/ios/RCTMGL-v10/RCTMGLRasterLayerManager.swift index e7800029b..a1a6def7c 100644 --- a/ios/RCTMGL-v10/RCTMGLRasterLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLRasterLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLRasterLayerManager) class RCTMGLRasterLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLRasterLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLRasterLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLRasterSource.swift b/ios/RCTMGL-v10/RCTMGLRasterSource.swift index 2f9261ac7..6891838e4 100644 --- a/ios/RCTMGL-v10/RCTMGLRasterSource.swift +++ b/ios/RCTMGL-v10/RCTMGLRasterSource.swift @@ -1,51 +1,49 @@ import MapboxMaps @objc -class RCTMGLRasterSource : RCTMGLSource { +class RCTMGLRasterSource: RCTMGLSource { typealias SourceType = RasterSource - @objc var url: String? = nil - - @objc var tileUrlTemplates: [String]? = nil - + @objc var url: String? + + @objc var tileUrlTemplates: [String]? + @objc var minZoomLevel: NSNumber? @objc var maxZoomLevel: NSNumber? @objc var tileSize: NSNumber? - - @objc var tms: Bool = false - + + @objc var tms = false + @objc var attribution: String? - override func makeSource() -> Source - { + override func makeSource() -> Source { var result = RasterSource() if let url = url { result.url = url } else { result.tiles = tileUrlTemplates } - + if let tileSize = tileSize { result.tileSize = tileSize.doubleValue } - + if let minZoomLevel = minZoomLevel { result.minzoom = minZoomLevel.doubleValue } - + if let maxZoomLevel = maxZoomLevel { result.maxzoom = maxZoomLevel.doubleValue } - + if tms { result.scheme = .tms } - + if let attribution = attribution { result.attribution = attribution } - + return result } - } diff --git a/ios/RCTMGL-v10/RCTMGLRasterSourceManager.swift b/ios/RCTMGL-v10/RCTMGLRasterSourceManager.swift index 3149cfcc9..00639f7b5 100644 --- a/ios/RCTMGL-v10/RCTMGLRasterSourceManager.swift +++ b/ios/RCTMGL-v10/RCTMGLRasterSourceManager.swift @@ -2,12 +2,12 @@ import Foundation import MapboxMaps @objc(RCTMGLRasterSourceManager) -class RCTMGLRasterSourceManager : RCTViewManager { +class RCTMGLRasterSourceManager: RCTViewManager { @objc override static func requiresMainQueueSetup() -> Bool { return true } - + override func view() -> UIView! { return RCTMGLRasterSource() } diff --git a/ios/RCTMGL-v10/RCTMGLShapeSource.swift b/ios/RCTMGL-v10/RCTMGLShapeSource.swift index 5f7b4a9fa..8ed402ac4 100644 --- a/ios/RCTMGL-v10/RCTMGLShapeSource.swift +++ b/ios/RCTMGL-v10/RCTMGLShapeSource.swift @@ -2,13 +2,13 @@ import MapboxMaps import Turf @objc -class RCTMGLShapeSource : RCTMGLSource { - @objc var url : String? +class RCTMGLShapeSource: RCTMGLSource { + @objc var url: String? - @objc var shape : String? { + @objc var shape: String? { didSet { logged("RCTMGLShapeSource.updateShape") { - let obj : GeoJSONObject = try parse(shape) + let obj: GeoJSONObject = try parse(shape) doUpdate { (style) in logged("RCTMGLShapeSource.setShape") { @@ -18,10 +18,10 @@ class RCTMGLShapeSource : RCTMGLSource { } } } - - @objc var cluster : NSNumber? - @objc var clusterRadius : NSNumber? - @objc var clusterMaxZoomLevel : NSNumber? { + + @objc var cluster: NSNumber? + @objc var clusterRadius: NSNumber? + @objc var clusterMaxZoomLevel: NSNumber? { didSet { logged("RCTMGLShapeSource.clusterMaxZoomLevel") { if let number = clusterMaxZoomLevel?.doubleValue { @@ -34,21 +34,20 @@ class RCTMGLShapeSource : RCTMGLSource { } } } - @objc var clusterProperties : [String: [Any]]?; - - @objc var maxZoomLevel : NSNumber? - @objc var buffer : NSNumber? - @objc var tolerance : NSNumber? - @objc var lineMetrics : NSNumber? - + @objc var clusterProperties: [String: [Any]]? + + @objc var maxZoomLevel: NSNumber? + @objc var buffer: NSNumber? + @objc var tolerance: NSNumber? + @objc var lineMetrics: NSNumber? + override func sourceType() -> Source.Type { return GeoJSONSource.self } - override func makeSource() -> Source - { - var result = GeoJSONSource() - + override func makeSource() -> Source { + var result = GeoJSONSource() + if let shape = shape { do { result.data = try parse(shape) @@ -57,66 +56,66 @@ class RCTMGLShapeSource : RCTMGLSource { result.data = emptyShape() } } - + if let url = url { result.data = .url(URL(string: url)!) } - + if let cluster = cluster { result.cluster = cluster.boolValue } - + if let clusterRadius = clusterRadius { result.clusterRadius = clusterRadius.doubleValue } - + if let clusterMaxZoomLevel = clusterMaxZoomLevel { result.clusterMaxZoom = clusterMaxZoomLevel.doubleValue } - + do { if let clusterProperties = clusterProperties { - result.clusterProperties = try clusterProperties.mapValues { (params : [Any]) in + result.clusterProperties = try clusterProperties.mapValues { (params: [Any]) in let data = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted) let decodedExpression = try JSONDecoder().decode(Expression.self, from: data) - + return decodedExpression } } } catch { Logger.log(level: .error, message: "RCTMGLShapeSource.parsing clusterProperties failed", error: error) } - + if let maxZoomLevel = maxZoomLevel { result.maxzoom = maxZoomLevel.doubleValue } - + if let buffer = buffer { result.buffer = buffer.doubleValue } - + if let tolerance = tolerance { result.tolerance = tolerance.doubleValue } - + if let lineMetrics = lineMetrics { result.lineMetrics = lineMetrics.boolValue } - + return result } - func doUpdate(_ update:(Style) -> Void) { + func doUpdate(_ update: (Style) -> Void) { guard let map = self.map, let _ = self.source, map.mapboxMap.style.sourceExists(withId: id) else { return } - + let style = map.mapboxMap.style update(style) } - + func updateSource(property: String, value: Any) { doUpdate { style in try! style.setSourceProperty(for: id, property: property, value: value) @@ -126,8 +125,7 @@ class RCTMGLShapeSource : RCTMGLSource { // MARK: - parse(shape) -extension RCTMGLShapeSource -{ +extension RCTMGLShapeSource { func parse(_ shape: String) throws -> GeoJSONSourceData { guard let data = shape.data(using: .utf8) else { throw RCTMGLError.parseError("shape is not utf8") @@ -145,7 +143,7 @@ extension RCTMGLShapeSource } } } - + func parse(_ shape: String) throws -> Feature { guard let data = shape.data(using: .utf8) else { throw RCTMGLError.parseError("shape is not utf8") @@ -157,17 +155,21 @@ extension RCTMGLShapeSource guard let shape = shape else { return emptyGeoJSONObject() } - let data : GeoJSONSourceData = try parse(shape) + let data: GeoJSONSourceData = try parse(shape) switch data { case .empty: return emptyGeoJSONObject() + case .feature(let feature): return .feature(feature) + case .featureCollection(let featureColleciton): return .featureCollection(featureColleciton) + case .geometry(let geometry): return .geometry(geometry) - case .url(_): + + case .url: throw RCTMGLError.parseError("url as shape is not supported when updating a ShapeSource") } } @@ -177,11 +179,11 @@ extension RCTMGLShapeSource } func emptyShape() -> GeoJSONSourceData { - return GeoJSONSourceData.featureCollection(FeatureCollection(features:[])) + return GeoJSONSourceData.featureCollection(FeatureCollection(features: [])) } func emptyFeatureCollection() -> FeatureCollection { - return FeatureCollection(features:[]) + return FeatureCollection(features: []) } func parseAsJSONObject(shape: String?) -> Any? { @@ -201,21 +203,19 @@ extension RCTMGLShapeSource // MARK: - getClusterExpansionZoom/getClusterLeaves -extension RCTMGLShapeSource -{ +extension RCTMGLShapeSource { func getClusterExpansionZoom( _ featureJSON: String, - completion: @escaping (Result) -> Void) - { + completion: @escaping (Result) -> Void) { guard let mapView = map?.mapView else { completion(.failure(RCTMGLError.failed("getClusterExpansionZoom: no mapView"))) return } - logged("RCTMGLShapeSource.getClusterExpansionZoom", rejecter: { (_,_,error) in + logged("RCTMGLShapeSource.getClusterExpansionZoom", rejecter: { (_, _, error) in completion(.failure(error!)) }) { - let cluster : Feature = try parse(featureJSON); + let cluster: Feature = try parse(featureJSON) mapView.mapboxMap.queryFeatureExtension(for: self.id, feature: cluster, extension: "supercluster", extensionField: "expansion-zoom") { result in switch result { @@ -224,34 +224,35 @@ extension RCTMGLShapeSource completion(.failure(RCTMGLError.failed("getClusterExpansionZoom: not a number"))) return } - + completion(.success(value.intValue)) + case .failure(let error): completion(.failure(error)) } } } } - + func getClusterLeaves(_ featureJSON: String, - number: uint, - offset: uint, - completion: @escaping (Result) -> Void) - { + number: uint, + offset: uint, + completion: @escaping (Result) -> Void) { guard let mapView = map?.mapView else { completion(.failure(RCTMGLError.failed("getClusterLeaves: no mapView"))) return } - - logged("RCTMGLShapeSource.getClusterLeaves", rejecter: { (_,_,error) in + + logged("RCTMGLShapeSource.getClusterLeaves", rejecter: { (_, _, error) in completion(.failure(error!)) }) { - let cluster : Feature = try parse(featureJSON); - mapView.mapboxMap.queryFeatureExtension(for: self.id, feature: cluster, extension: "supercluster", extensionField: "leaves", args: ["limit": UInt64(number),"offset": UInt64(offset)]) { + let cluster: Feature = try parse(featureJSON) + mapView.mapboxMap.queryFeatureExtension(for: self.id, feature: cluster, extension: "supercluster", extensionField: "leaves", args: ["limit": UInt64(number), "offset": UInt64(offset)]) { result in switch result { case .success(let features): completion(.success(features)) + case .failure(let error): completion(.failure(error)) } @@ -265,15 +266,16 @@ extension RCTMGLShapeSource return } - logged("RCTMGLShapeSource.getClusterChildren", rejecter: { (_,_,error) in + logged("RCTMGLShapeSource.getClusterChildren", rejecter: { (_, _, error) in completion(.failure(error!)) }) { - let cluster : Feature = try parse(featureJSON); + let cluster: Feature = try parse(featureJSON) mapView.mapboxMap.queryFeatureExtension(for: self.id, feature: cluster, extension: "supercluster", extensionField: "children") { result in switch result { case .success(let features): completion(.success(features)) + case .failure(let error): completion(.failure(error)) } diff --git a/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift b/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift index 882cfc731..e2200b2f7 100644 --- a/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift +++ b/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift @@ -14,18 +14,17 @@ class RCTMGLShapeSourceManager: RCTViewManager { extension RCTMGLShapeSourceManager { func withShapeSource( - _ reactTag: NSNumber, - name: String, - rejecter: @escaping RCTPromiseRejectBlock, - fn: @escaping (_: RCTMGLShapeSource) -> Void) -> Void - { - self.bridge.uiManager.addUIBlock { (manager, viewRegistry) in + _ reactTag: NSNumber, + name: String, + rejecter: @escaping RCTPromiseRejectBlock, + fn: @escaping (_: RCTMGLShapeSource) -> Void) { + self.bridge.uiManager.addUIBlock { (_, viewRegistry) in let view = viewRegistry![reactTag] guard let shapeSource = view! as? RCTMGLShapeSource else { - RCTMGLLogError("Invalid react tag, could not find RCTMGLShapeSource"); + RCTMGLLogError("Invalid react tag, could not find RCTMGLShapeSource") rejecter(name, "Unknown find reactTag: \(reactTag)", nil) - return; + return } fn(shapeSource) @@ -40,62 +39,63 @@ extension RCTMGLShapeSourceManager { _ reactTag: NSNumber, featureJSON: String, resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock) -> Void - { - self.withShapeSource(reactTag, name:"getCluster ExpansionZoom", rejecter: rejecter) { shapeSource in + rejecter: @escaping RCTPromiseRejectBlock) { + self.withShapeSource(reactTag, name: "getCluster ExpansionZoom", rejecter: rejecter) { shapeSource in shapeSource.getClusterExpansionZoom(featureJSON) { result in switch result { case .success(let zoom): resolver([ "data": NSNumber(value: zoom) ]) + case .failure(let error): rejecter(error.localizedDescription, "Error.getClusterExpansionZoom", error) } } } } - + @objc func getClusterLeaves( _ reactTag: NSNumber, featureJSON: String, number: uint, offset: uint, resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock) -> Void - { - self.withShapeSource(reactTag, name:"getClusterLeaves", rejecter: rejecter) { shapeSource in + rejecter: @escaping RCTPromiseRejectBlock) { + self.withShapeSource(reactTag, name: "getClusterLeaves", rejecter: rejecter) { shapeSource in shapeSource.getClusterLeaves(featureJSON, number: number, offset: offset) { result in switch result { case .success(let features): logged("getClusterLeaves", rejecter: rejecter) { - let featuresJSON : Any = try features.features.toJSON() + let featuresJSON: Any = try features.features.toJSON() resolver([ - "data": ["type":"FeatureCollection", "features": featuresJSON] + "data": ["type": "FeatureCollection", "features": featuresJSON] ]) } + case .failure(let error): rejecter(error.localizedDescription, "Error.getClusterLeaves", error) } } } } - + @objc func getClusterChildren( _ reactTag: NSNumber, featureJSON: String, resolver: @escaping RCTPromiseResolveBlock, - rejecter: @escaping RCTPromiseRejectBlock) -> Void { - self.withShapeSource(reactTag, name:"getClusterChildren", rejecter: rejecter) { shapeSource in + rejecter: @escaping RCTPromiseRejectBlock) { + self.withShapeSource(reactTag, name: "getClusterChildren", rejecter: rejecter) { shapeSource in shapeSource.getClusterChildren(featureJSON) { result in switch result { case .success(let features): logged("getClusterChildren", rejecter: rejecter) { - let featuresJSON : Any = try features.features.toJSON() + let featuresJSON: Any = try features.features.toJSON() resolver([ - "data": ["type":"FeatureCollection", "features": featuresJSON] + "data": ["type": "FeatureCollection", "features": featuresJSON] ]) } + case .failure(let error): rejecter(error.localizedDescription, "Error.getClusterChildren", error) } @@ -103,4 +103,3 @@ extension RCTMGLShapeSourceManager { } } } - diff --git a/ios/RCTMGL-v10/RCTMGLSingletonLayer.swift b/ios/RCTMGL-v10/RCTMGLSingletonLayer.swift index 9704bc346..f047afe52 100644 --- a/ios/RCTMGL-v10/RCTMGLSingletonLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLSingletonLayer.swift @@ -2,13 +2,13 @@ import MapboxMaps /// RCTMGLSingletonLayer is absract superclass for Light, Atmosphere, Terrain @objc -class RCTMGLSingletonLayer : UIView { - weak var bridge : RCTBridge? = nil - weak var map : RCTMGLMapView? = nil - var style: Style? = nil - - var oldReactStyle: [String:Any]? - @objc var reactStyle : Dictionary? = nil { +class RCTMGLSingletonLayer: UIView { + weak var bridge: RCTBridge? + weak var map: RCTMGLMapView? + var style: Style? + + var oldReactStyle: [String: Any]? + @objc var reactStyle: [String: Any]? { willSet { oldReactStyle = reactStyle } @@ -24,26 +24,26 @@ class RCTMGLSingletonLayer : UIView { addStyles() update() } - + /// apply the changes made to our copy to the map style func update() { if let style = style, - let map = map { + let map = map { self.update(map, style) } } - + func update(_ map: RCTMGLMapView, _ style: Style) { logged("LayerLike \(self)") { try apply(style: style) } } - + /// add reactStyle to the layer like component func addStyles() { fatalError("Subclasses should overrride") } - + /// apply changes in layer like component to the map func apply(style: Style) throws { fatalError("Subclasses should overrride") diff --git a/ios/RCTMGL-v10/RCTMGLSkyLayer.swift b/ios/RCTMGL-v10/RCTMGLSkyLayer.swift index 949467ca4..a119c584f 100644 --- a/ios/RCTMGL-v10/RCTMGLSkyLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLSkyLayer.swift @@ -13,22 +13,21 @@ class RCTMGLSkyLayer: RCTMGLLayer { return LayerType.self } - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout LayerType) in + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout LayerType) in if let styleLayer = self.styleLayer as? LayerType { layer = styleLayer } } } - + override func addStyles() { - if let style : Style = self.style { - let styler = RCTMGLStyle(style: self.style!) + if let style: Style = self.style { + let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge - + if var styleLayer = self.styleLayer as? LayerType, let reactStyle = self.reactStyle { - styler.skyLayer( layer: &styleLayer, reactStyle: reactStyle, @@ -44,7 +43,7 @@ class RCTMGLSkyLayer: RCTMGLLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLSkyLayerManager.swift b/ios/RCTMGL-v10/RCTMGLSkyLayerManager.swift index 18fc721ab..5d7de8acf 100644 --- a/ios/RCTMGL-v10/RCTMGLSkyLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLSkyLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLSkyLayerManager) class RCTMGLSkyLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLSkyLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLSkyLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLSource.swift b/ios/RCTMGL-v10/RCTMGLSource.swift index a83518387..6b3482414 100644 --- a/ios/RCTMGL-v10/RCTMGLSource.swift +++ b/ios/RCTMGL-v10/RCTMGLSource.swift @@ -1,16 +1,16 @@ @_spi(Experimental) import MapboxMaps @objc -class RCTMGLSource : RCTMGLInteractiveElement { +class RCTMGLSource: RCTMGLInteractiveElement { var layers: [RCTMGLSourceConsumer] = [] var components: [RCTMGLMapComponent] = [] - var source : Source? = nil + var source: Source? - var ownsSource : Bool = false + var ownsSource = false + + @objc var existing = false - @objc var existing: Bool = false - override func getLayerIDs() -> [String] { layers.compactMap { if let layer = $0 as? RCTMGLLayer { @@ -24,11 +24,11 @@ class RCTMGLSource : RCTMGLInteractiveElement { func makeSource() -> Source { fatalError("Subclasses should override makeSource") } - + func sourceType() -> Source.Type { fatalError("Subclasses should override makeSource") } - + // MARK: - UIView+React @objc override func insertReactSubview(_ subview: UIView!, at atIndex: Int) { @@ -45,9 +45,9 @@ class RCTMGLSource : RCTMGLInteractiveElement { } super.insertReactSubview(subview, at: atIndex) } - + @objc override func removeReactSubview(_ subview: UIView!) { - if let layer : RCTMGLSourceConsumer = subview as? RCTMGLSourceConsumer { + if let layer: RCTMGLSourceConsumer = subview as? RCTMGLSourceConsumer { if let map = map { layer.removeFromMap(map, style: map.mapboxMap.style) } @@ -60,23 +60,23 @@ class RCTMGLSource : RCTMGLInteractiveElement { } super.removeReactSubview(subview) } - + @objc override func didUpdateReactSubviews() { // do nothing to prevent inserting layers to UIView hierarchy } - + // MARK: - RCTMGLInteractiveElement - + override func addToMap(_ map: RCTMGLMapView, style: Style) { self.map = map if style.sourceExists(withId: self.id) { - if (!existing) { + if !existing { Logger.log(level: .warn, message: "Warning source with id:\(optional: id) referred to existing source but `existing` attibute was missing. https://github.com/rnmapbox/maps/wiki/Deprecated-ExistingSourceLayer") } self.source = try! style.source(withId: self.id) } else { - if (existing) { + if existing { Logger.log(level: .warn, message: "Warning source with id:\(optional: id) marked as existing, but could not find in style, source identifiers: \(style.allSourceIdentifiers.map { [$0.id, $0.type.rawValue] })") } let source = self.makeSource() diff --git a/ios/RCTMGL-v10/RCTMGLStyleValue.swift b/ios/RCTMGL-v10/RCTMGLStyleValue.swift index 7ae505bf9..da2504522 100644 --- a/ios/RCTMGL-v10/RCTMGLStyleValue.swift +++ b/ios/RCTMGL-v10/RCTMGLStyleValue.swift @@ -2,7 +2,7 @@ import MapboxMaps import Foundation func deg2rad(_ number: Double) -> Double { - return number * .pi / 180 + return number * .pi / 180 } enum StyleConversionError: Error { @@ -11,52 +11,51 @@ enum StyleConversionError: Error { class RCTMGLStyleValue { var value: Any - var styleType: String? = nil - var styleValue: [String:Any]? = nil - var styleObject: Any? = nil - - + var styleType: String? + var styleValue: [String: Any]? + var styleObject: Any? + init(value: Any) { self.value = value - - if let dict = value as? [String:Any] { + + if let dict = value as? [String: Any] { guard let styleType = dict["styletype"] as? String else { fatalError("StyleType should be string in \(dict)") } self.styleType = styleType - guard let styleValue = dict["stylevalue"] as? [String:Any] else { + guard let styleValue = dict["stylevalue"] as? [String: Any] else { fatalError("StyleValue should be dict in \(dict)") } self.styleValue = styleValue self.styleObject = parse(rawStyleValue: styleValue) } } - - static func make(_ reactStyleValue: Any) ->RCTMGLStyleValue { + + static func make(_ reactStyleValue: Any) -> RCTMGLStyleValue { return RCTMGLStyleValue(value: reactStyleValue) } - + func isVisible() -> Value { return mglStyleValueEnum() } - + func getTransition() -> StyleTransition { - guard let dict = styleObject as? [String:Any] else { - Logger.log(level:.error, message: "Invalid transition value: \(optional: styleObject)") + guard let dict = styleObject as? [String: Any] else { + Logger.log(level: .error, message: "Invalid transition value: \(optional: styleObject)") return StyleTransition(duration: 0.0, delay: 0.0) } let duration = (dict["duration"] as? NSNumber) let delay = (dict["delay"] as? NSNumber) if delay == nil && duration == nil { - Logger.log(level:.error, message: "Invalid transition value: \(optional: styleObject) no duration or delay") + Logger.log(level: .error, message: "Invalid transition value: \(optional: styleObject) no duration or delay") } - let millisecondsToSeconds = 1.0/1000.0; + let millisecondsToSeconds = 1.0 / 1000.0 return StyleTransition(duration: millisecondsToSeconds * (duration?.doubleValue ?? 0.0), delay: millisecondsToSeconds * (delay?.doubleValue ?? 0.0)) } - + func getImageScale() -> Double { - if let dict = styleObject as? [String:Any] { + if let dict = styleObject as? [String: Any] { if let scale = dict["scale"] as? NSNumber { return scale.doubleValue } else { @@ -65,13 +64,12 @@ class RCTMGLStyleValue { } return 1.0 } - - func parse(rawStyleValue: [String:Any]) -> Any - { + + func parse(rawStyleValue: [String: Any]) -> Any { guard let type = rawStyleValue["type"] as? String else { fatalError("type is not a string in \(rawStyleValue)") } - + let value = rawStyleValue["value"] if type == "string" { guard let string = value as? String else { @@ -89,10 +87,10 @@ class RCTMGLStyleValue { } return bool } else if type == "hashmap" { - guard let array = value as? [[[String:Any]]] else { + guard let array = value as? [[[String: Any]]] else { fatalError("value is not a array in \(rawStyleValue)") } - var dict : [String:Any] = [:] + var dict: [String: Any] = [:] for kv in array { guard let key = parse(rawStyleValue: kv[0]) as? String else { fatalError("key \(kv[0]) is not string in \(rawStyleValue)") @@ -102,10 +100,10 @@ class RCTMGLStyleValue { } return dict } else if type == "array" { - guard let rawArray = value as? [[String:Any]] else { + guard let rawArray = value as? [[String: Any]] else { fatalError("value is not a array in \(rawStyleValue)") } - var convertedArray:[Any] = [] + var convertedArray: [Any] = [] for i in rawArray { convertedArray.append(parse(rawStyleValue: i)) } @@ -114,49 +112,46 @@ class RCTMGLStyleValue { fatalError("unepxected type: \(type)") } } - - static func convert(_ from:[String: Any]) -> Any { + + static func convert(_ from: [String: Any]) -> Any { guard let type = from["type"] as? String else { fatalError("Type should be string but was \(optional: from["type"])") } if type == "array" { - guard let values = from["value"] as? [[String:Any]] else { + guard let values = from["value"] as? [[String: Any]] else { fatalError("Value for array should be array of dicts") } return values.map { convert($0) } - } - else if type == "string" { + } else if type == "string" { guard let value = from["value"] as? String else { fatalError("Value for string should be String") } - + return value - } - else if type == "hashmap" { + } else if type == "hashmap" { guard let values = from["value"] as? [[Any]] else { fatalError("Value for hashmap should be array of array") } - - let result = values.map { items -> (String,Any) in + + let result = values.map { items -> (String, Any) in var key = items[0] let value = items[1] - if let keyd = key as? [String:String], - keyd["type"] == "string", - let value = keyd["value"] { + if let keyd = key as? [String: String], + keyd["type"] == "string", + let value = keyd["value"] { key = value } guard let key = key as? String else { fatalError("First item should be a string key") } - guard let value = value as? [String:Any] else { + guard let value = value as? [String: Any] else { fatalError("Value should be an array of dicts") } - return (key,convert(value)) + return (key, convert(value)) } - return Dictionary(uniqueKeysWithValues: result) - } - else if type == "number" { + return [String: Any](uniqueKeysWithValues: result) + } else if type == "number" { guard let value = from["value"] else { fatalError("Value for number should not be nil") } @@ -176,11 +171,11 @@ class RCTMGLStyleValue { fatalError("Unexpected type \(type)") } } - + func mglStyleValueNumber() -> Value { - if let value = value as? Dictionary { - let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) - + if let value = value as? [String: Any] { + let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) + if let num = value as? NSNumber { return Value.constant(Double(num.doubleValue)) } else if let num = value as? Double { @@ -194,7 +189,7 @@ class RCTMGLStyleValue { let decodedExpression = try JSONDecoder().decode(Expression.self, from: data) return Value.expression(decodedExpression) } catch { - Logger.log(level:.error, message: "mglStyleValueNumber: Cannot parse \(value) as expression") + Logger.log(level: .error, message: "mglStyleValueNumber: Cannot parse \(value) as expression") return Value.constant(0.0) } } @@ -204,13 +199,13 @@ class RCTMGLStyleValue { } func mglStyleValueNumberRaw() -> Double { - guard let value = value as? Dictionary else { + guard let value = value as? [String: Any] else { Logger.log(level: .error, message: "Invalid value for number: \(value) retuning 0.0") return 0.0 } - - let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) - + + let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) + if let num = valueObj as? NSNumber { return num.doubleValue } else if let num = valueObj as? Double { @@ -225,23 +220,23 @@ class RCTMGLStyleValue { } func uicolor(_ rgbValue: Int) -> UIColor { - return UIColor( - red: CGFloat((Float((rgbValue & 0xff0000) >> 16)) / 255.0), - green: CGFloat((Float((rgbValue & 0x00ff00) >> 8)) / 255.0), - blue: CGFloat((Float((rgbValue & 0x0000ff) >> 0)) / 255.0), - alpha: CGFloat((rgbValue & 0xFF000000) >> 24) / 0xFF) + return UIColor( + red: CGFloat((Float((rgbValue & 0xff0000) >> 16)) / 255.0), + green: CGFloat((Float((rgbValue & 0x00ff00) >> 8)) / 255.0), + blue: CGFloat((Float((rgbValue & 0x0000ff) >> 0)) / 255.0), + alpha: CGFloat((rgbValue & 0xFF000000) >> 24) / 0xFF) } func mglStyleValueColor() -> Value { - //return Value.constant(ColorRepresentable(color: UIColor.black)) - if let value = value as? Dictionary { - let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) - + // return Value.constant(ColorRepresentable(color: UIColor.black)) + if let value = value as? [String: Any] { + let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) + if let num = value as? Int { let uicolor = uicolor(num) return Value.constant(StyleColor(uicolor)) } - + let data = try! JSONSerialization.data(withJSONObject: value, options: .prettyPrinted) let decodedExpression = try! JSONDecoder().decode(Expression.self, from: data) @@ -250,7 +245,7 @@ class RCTMGLStyleValue { return Value.constant(StyleColor(UIColor.red)) } } - + func asExpression(json: [Any]) -> Expression { let data = try! JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) let decodedExpression = try! JSONDecoder().decode(Expression.self, from: data) @@ -258,11 +253,11 @@ class RCTMGLStyleValue { } func mglStyleValueColorRaw() -> StyleColor { - guard let value = value as? Dictionary else { + guard let value = value as? [String: Any] else { Logger.log(level: .error, message: "Invalid value for color: \(value) retuning red") return StyleColor(UIColor.red) } - let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) + let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) if let num = value as? Int { let uicolor = uicolor(num) @@ -272,15 +267,15 @@ class RCTMGLStyleValue { return StyleColor(UIColor.red) } } - + func mglStyleValueBoolean() -> Value { - guard let value = value as? Dictionary else { + guard let value = value as? [String: Any] else { Logger.log(level: .error, message: "Invalid value for boolean: \(value)") return Value.constant(true) } - - let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) - + + let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) + if let valueObj = valueObj as? NSNumber { return .constant(valueObj.boolValue) } else { @@ -294,15 +289,15 @@ class RCTMGLStyleValue { } } } - + func mglStyleValueArrayNumber() -> Value<[Double]> { - guard let value = value as? Dictionary else { + guard let value = value as? [String: Any] else { Logger.log(level: .error, message: "Invalid value for array number: \(value)") - return Value.constant([1.0,1.0]) + return Value.constant([1.0, 1.0]) } - - let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) - + + let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) + if let valueObj = valueObj as? [NSNumber] { return .constant(valueObj.map { $0.doubleValue }) } else { @@ -312,19 +307,19 @@ class RCTMGLStyleValue { return .expression(decodedExpression) } catch { Logger.log(level: .error, message: "Invalid value for array number: \(value) error: \(error) setting dummy value") - return .constant([1.0,1.0]) + return .constant([1.0, 1.0]) } } } - + func mglStyleValueArrayString() -> Value<[String]> { - guard let value = value as? Dictionary else { + guard let value = value as? [String: Any] else { Logger.log(level: .error, message: "Invalid value for array of strings: \(value)") return Value.constant([""]) } - let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) - + let valueObj = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) + if let valueObj = valueObj as? [String] { return .constant(valueObj) } else { @@ -341,11 +336,11 @@ class RCTMGLStyleValue { } } } - + func mglStyleValueResolvedImage() -> Value { if let exprJSON = styleObject as? [Any] { return Value.expression(asExpression(json: exprJSON)) - } else if let dict = styleObject as? [String:Any], + } else if let dict = styleObject as? [String: Any], let uri = dict["uri"] as? String { return Value.constant(.name(uri)) } else if let value = styleObject as? String { @@ -362,31 +357,31 @@ class RCTMGLStyleValue { func mglStyleValueLineCap() -> Value { return mglStyleValueEnum() } - - func mglStyleValueEnum() -> Value where Enum.RawValue == String { - if let value = value as? Dictionary { - let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) + + func mglStyleValueEnum() -> Value where Enum.RawValue == String { + if let value = value as? [String: Any] { + let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) return Value.constant(Enum(rawValue: value as! String)!) } else { - Logger.log(level: .error, message:"Invalid value for enum: \(value) returning something") + Logger.log(level: .error, message: "Invalid value for enum: \(value) returning something") return Value.constant(Enum(rawValue: value as! String)!) } } - func mglStyleEnum() -> Enum where Enum.RawValue == String { - if let value = value as? Dictionary { - let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) + func mglStyleEnum() -> Enum where Enum.RawValue == String { + if let value = value as? [String: Any] { + let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) return Enum(rawValue: value as! String)! } else { - Logger.log(level: .error, message:"Invalid value for enum: \(value) returning something") + Logger.log(level: .error, message: "Invalid value for enum: \(value) returning something") return Enum(rawValue: value as! String)! } } - + func mglStyleValueArrayTextWritingMode() -> Value<[TextWritingMode]> { return Value.constant([]) } - + func mglStyleValueAnchorRaw() -> Anchor { return mglStyleEnum() } @@ -397,7 +392,7 @@ class RCTMGLStyleValue { } return false } - + func setImage( bridge: RCTBridge, style: Style, @@ -407,14 +402,14 @@ class RCTMGLStyleValue { setImageOnLayerLater: @escaping (_: RCTMGLStyleValue) -> Void, // called in case we need to set the image later just after downloaded name: String ) { - if (!shouldAddImage()) { + if !shouldAddImage() { setImageOnLayer(self) } else { let imageURI = getImageURI() - - if let oldRawValue = oldValue as? [String:Any] { - if let oldRawValue = oldRawValue["stylevalue"] as? [String:Any] { - if let oldValue = parse(rawStyleValue: oldRawValue) as? [String:Any] { + + if let oldRawValue = oldValue as? [String: Any] { + if let oldRawValue = oldRawValue["stylevalue"] as? [String: Any] { + if let oldValue = parse(rawStyleValue: oldRawValue) as? [String: Any] { if getImageURI(oldValue) == imageURI { setImageOnLayer(self) return @@ -423,12 +418,12 @@ class RCTMGLStyleValue { } } - RCTMGLUtils.fetchImage(bridge, url:imageURI, scale:getImageScale(), callback:{ (error, image) in + RCTMGLUtils.fetchImage(bridge, url: imageURI, scale: getImageScale(), callback: { (error, image) in if let image = image { DispatchQueue.main.sync { - if (isLayerStillValid()) { + if isLayerStillValid() { logged("\(name).addImage") { - try style.addImage(image, id:imageURI!, stretchX: [], stretchY: []); + try style.addImage(image, id: imageURI!, stretchX: [], stretchY: []) setImageOnLayerLater(self) } } @@ -436,31 +431,31 @@ class RCTMGLStyleValue { } else { Logger.log(level: .error, message: "Error during fetchImage: \(optional: error)") } - }); + }) } } - - func getImageURI(_ dict: [String:Any]) -> String? { + + func getImageURI(_ dict: [String: Any]) -> String? { if let uri = dict["uri"] as? String { return uri } else { return nil } } - + func getImageURI() -> String? { - if let dict = styleObject as? [String:Any] { + if let dict = styleObject as? [String: Any] { return getImageURI(dict) } else if let uri = styleObject as? String { return uri } return nil } - + func mglStyleValueArrayTextVariableAnchor() -> Value<[TextAnchor]> { return Value.constant([.left]) } - + func getSphericalPosition() -> [Double] { if let array = styleObject as? [NSNumber] { var result = array.map { $0.doubleValue } @@ -471,15 +466,15 @@ class RCTMGLStyleValue { Logger.log(level: .error, message: "Expected array of numbers as position received: \(optional: styleObject)") return [] } - + func mglStyleValueFormatted() -> Value { - if let value = value as? Dictionary { - let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String:Any]) - + if let value = value as? [String: Any] { + let value = RCTMGLStyleValue.convert(value["stylevalue"] as! [String: Any]) + if let string = value as? String { return Value.constant(string) } - + let data = try! JSONSerialization.data(withJSONObject: value, options: .prettyPrinted) let decodedExpression = try! JSONDecoder().decode(Expression.self, from: data) @@ -488,11 +483,11 @@ class RCTMGLStyleValue { fatalError("mglStyleValueFormatted - Unpexected value: \(value)") } } - + func mglStyleValueLineJoin() -> Value { return mglStyleValueEnum() } - + func mglStyleValueLineTranslateAnchor() -> Value { return mglStyleValueEnum() } diff --git a/ios/RCTMGL-v10/RCTMGLSymbolLayer.swift b/ios/RCTMGL-v10/RCTMGLSymbolLayer.swift index 7cf5ecdab..18cafea95 100644 --- a/ios/RCTMGL-v10/RCTMGLSymbolLayer.swift +++ b/ios/RCTMGL-v10/RCTMGLSymbolLayer.swift @@ -2,11 +2,10 @@ import MapboxMaps @objc(RCTMGLSymbolLayer) class RCTMGLSymbolLayer: RCTMGLVectorLayer { - typealias LayerType = SymbolLayer override func makeLayer(style: Style) throws -> Layer { - let _ : VectorSource = try self.layerWithSourceID(in: style) + let _: VectorSource = try self.layerWithSourceID(in: style) var layer = LayerType(id: self.id!) layer.sourceLayer = self.sourceLayerID layer.source = sourceID @@ -17,19 +16,19 @@ class RCTMGLSymbolLayer: RCTMGLVectorLayer { return LayerType.self } - override func apply(style : Style) throws { - try style.updateLayer(withId: id, type: LayerType.self) { (layer : inout SymbolLayer) in + override func apply(style: Style) throws { + try style.updateLayer(withId: id, type: LayerType.self) { (layer: inout SymbolLayer) in if var styleLayer = self.styleLayer as? LayerType { layer = styleLayer } } } - + override func addStyles() { - if let style : Style = self.style { - let styler = RCTMGLStyle(style: self.style!) + if let style: Style = self.style { + let styler = RCTMGLStyle(style: self.style!) styler.bridge = self.bridge - + if var styleLayer = self.styleLayer as? LayerType, let reactStyle = self.reactStyle { styler.symbolLayer( @@ -47,7 +46,7 @@ class RCTMGLSymbolLayer: RCTMGLVectorLayer { } } } - + func isAddedToMap() -> Bool { return true } diff --git a/ios/RCTMGL-v10/RCTMGLSymbolLayerManager.swift b/ios/RCTMGL-v10/RCTMGLSymbolLayerManager.swift index 7ffe59baf..fb493ed7e 100644 --- a/ios/RCTMGL-v10/RCTMGLSymbolLayerManager.swift +++ b/ios/RCTMGL-v10/RCTMGLSymbolLayerManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLSymbolLayerManager) class RCTMGLSymbolLayerManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let layer = RCTMGLSymbolLayer() - layer.bridge = self.bridge - return layer - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let layer = RCTMGLSymbolLayer() + layer.bridge = self.bridge + return layer + } } diff --git a/ios/RCTMGL-v10/RCTMGLTerrain.swift b/ios/RCTMGL-v10/RCTMGLTerrain.swift index 5a6cd25b2..f8491f437 100644 --- a/ios/RCTMGL-v10/RCTMGLTerrain.swift +++ b/ios/RCTMGL-v10/RCTMGLTerrain.swift @@ -1,9 +1,9 @@ import MapboxMaps @objc -class RCTMGLTerrain : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceConsumer { - var terrain : Terrain? = nil - +class RCTMGLTerrain: RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceConsumer { + var terrain: Terrain? + func makeTerrain() -> Terrain { guard let sourceID = sourceID else { Logger.log(level: .error, message: "Terrain should have a sourceID") @@ -12,49 +12,49 @@ class RCTMGLTerrain : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceCons return Terrain(sourceId: sourceID) } - + func addToMap(_ map: RCTMGLMapView, style: Style) { self.map = map self.style = style - + let terrain = self.makeTerrain() self.terrain = terrain addStylesAndUpdate() } - + func removeFromMap(_ map: RCTMGLMapView) { self.map = nil - + guard let mapboxMap = map.mapboxMap else { return } - + let style = mapboxMap.style removeFromMap(map, style: style) } - + func waitForStyleLoad() -> Bool { return true } - + func removeFromMap(_ map: RCTMGLMapView, style: Style) { logged("RCTMGLTerrain.removeFromMap") { style.removeTerrain() } } - @objc var sourceID: String? = nil { + @objc var sourceID: String? { didSet { guard let sourceID = sourceID else { Logger.log(level: .error, message: "RCTMGLTerrain cannot set source to nil") return } - + terrain?.source = sourceID self.update() } } - + override func addStylesAndUpdate() { guard terrain != nil else { return @@ -62,19 +62,19 @@ class RCTMGLTerrain : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceCons super.addStylesAndUpdate() } - + override func addStyles() { - if let style : Style = self.style, + if let style: Style = self.style, let reactStyle = reactStyle { let styler = RCTMGLStyle(style: style) styler.bridge = self.bridge - + if var terrain = terrain { styler.terrainLayer( layer: &terrain, reactStyle: reactStyle, oldReactStyle: oldReactStyle, - applyUpdater: { (updater) in fatalError("Terrain: TODO - implement apply updater")}, + applyUpdater: { (_) in fatalError("Terrain: TODO - implement apply updater")}, isValid: { fatalError("Terrain: TODO - no isValid") } ) self.terrain = terrain @@ -83,8 +83,8 @@ class RCTMGLTerrain : RCTMGLSingletonLayer, RCTMGLMapComponent, RCTMGLSourceCons } } } - - override func apply(style : Style) throws { + + override func apply(style: Style) throws { if let terrain = terrain { try style.setTerrain(terrain) } diff --git a/ios/RCTMGL-v10/RCTMGLTerrainManager.swift b/ios/RCTMGL-v10/RCTMGLTerrainManager.swift index 306198d60..313996efb 100644 --- a/ios/RCTMGL-v10/RCTMGLTerrainManager.swift +++ b/ios/RCTMGL-v10/RCTMGLTerrainManager.swift @@ -1,13 +1,13 @@ @objc(RCTMGLTerrainManager) class RCTMGLTerrainManager: RCTViewManager { - @objc - override static func requiresMainQueueSetup() -> Bool { - return true - } - - override func view() -> UIView! { - let terrain = RCTMGLTerrain() - terrain.bridge = self.bridge - return terrain - } + @objc + override static func requiresMainQueueSetup() -> Bool { + return true + } + + override func view() -> UIView! { + let terrain = RCTMGLTerrain() + terrain.bridge = self.bridge + return terrain + } } diff --git a/ios/RCTMGL-v10/RCTMGLTileSource.swift b/ios/RCTMGL-v10/RCTMGLTileSource.swift index 55e2daa84..9601d27e7 100644 --- a/ios/RCTMGL-v10/RCTMGLTileSource.swift +++ b/ios/RCTMGL-v10/RCTMGLTileSource.swift @@ -1,5 +1,4 @@ @objc -class RCTMGLTileSource : RCTMGLSource { - @objc var url: String? = nil - +class RCTMGLTileSource: RCTMGLSource { + @objc var url: String? } diff --git a/ios/RCTMGL-v10/RCTMGLUtils.swift b/ios/RCTMGL-v10/RCTMGLUtils.swift index 5c5df4e5c..29b35b4fa 100644 --- a/ios/RCTMGL-v10/RCTMGLUtils.swift +++ b/ios/RCTMGL-v10/RCTMGLUtils.swift @@ -1,35 +1,35 @@ import MapboxMaps class RCTMGLUtils { - static func fetchImage(_ bridge: RCTBridge, url: String?, scale:Double, callback: @escaping (_ error: Error?, _ image: UIImage?) -> Void) { + static func fetchImage(_ bridge: RCTBridge, url: String?, scale: Double, callback: @escaping (_ error: Error?, _ image: UIImage?) -> Void) { guard let url = url else { fatalError("FetchImage called with nil as url") } RCTMGLImageQueue.sharedInstance.addImage(url, scale: scale, bridge: bridge, handler: callback) } - - static func fetchImages(_ bridge: RCTBridge, style: Style, objects: [String:Any], forceUpdate: Bool, callback: @escaping ()->Void) { + + static func fetchImages(_ bridge: RCTBridge, style: Style, objects: [String: Any], forceUpdate: Bool, callback: @escaping () -> Void) { guard !objects.isEmpty else { callback() return } - + let imageNames = objects.keys var imagesToLoad: Int = imageNames.count - + let imageLoadedBlock = { () in - imagesToLoad = imagesToLoad - 1; + imagesToLoad = imagesToLoad - 1 if imagesToLoad == 0 { callback() } } - + for imageName in imageNames { let foundImage: UIImage? = forceUpdate ? nil : style.image(withId: imageName) - - if (forceUpdate || foundImage == nil) { + + if forceUpdate || foundImage == nil { let image = objects[imageName] - if let image = image as? [String:Any] { + if let image = image as? [String: Any] { let scale = (image["scale"] as? NSNumber)?.floatValue ?? 1.0 let sdf = (image["sdf"] as? NSNumber)?.boolValue ?? false let imageStretchX = image["stretchX"] as? [[NSNumber]] @@ -37,18 +37,17 @@ class RCTMGLUtils { let imageStretchY = image["stretchY"] as? [[NSNumber]] let stretchY: [ImageStretches] = imageStretchY != nil ? RCTMGLImages.convert(stretch: imageStretchY!, scale: scale) : [] let content: ImageContent? = RCTMGLImages.convert(content: image["content"] as? [NSNumber], scale: scale) - - RCTMGLImageQueue.sharedInstance.addImage(objects[imageName], scale: Double(scale), bridge:bridge) { - (error,image) in + + RCTMGLImageQueue.sharedInstance.addImage(objects[imageName], scale: Double(scale), bridge: bridge) { + (error, image) in if image == nil { RCTMGLLogWarn("Failed to fetch image: \(imageName) error:\(error)") - } - else { + } else { DispatchQueue.main.async { if let image = image { logged("RCTMGLUtils.fetchImage-\(imageName)") { print("width=\(image.size.width) height=\(image.size.height) scale=\(image.scale) scale2=\(scale)") - try style.addImage(image, id: imageName, sdf:sdf, stretchX: stretchX, stretchY: stretchY, content: content) + try style.addImage(image, id: imageName, sdf: sdf, stretchX: stretchX, stretchY: stretchY, content: content) imageLoadedBlock() } } diff --git a/ios/RCTMGL-v10/RCTMGLVectorSource.swift b/ios/RCTMGL-v10/RCTMGLVectorSource.swift index 97a539e5d..5442b2324 100644 --- a/ios/RCTMGL-v10/RCTMGLVectorSource.swift +++ b/ios/RCTMGL-v10/RCTMGLVectorSource.swift @@ -1,20 +1,18 @@ import MapboxMaps @objc -class RCTMGLVectorSource : RCTMGLTileSource { - +class RCTMGLVectorSource: RCTMGLTileSource { @objc var attribution: String? @objc var maxZoomLevel: NSNumber? @objc var minZoomLevel: NSNumber? @objc var tileUrlTemplates: [String] = [] - @objc var tms: Bool = false - + @objc var tms = false + override func sourceType() -> Source.Type { return VectorSource.self } - override func makeSource() -> Source - { + override func makeSource() -> Source { var result = VectorSource() if let url = url { result.url = url @@ -35,23 +33,20 @@ class RCTMGLVectorSource : RCTMGLTileSource { } return result } - - - + /* - - (nullable MGLSource*)makeSource -{ - if (self.url != nil) { - return [[MGLVectorTileSource alloc] initWithIdentifier:self.id configurationURL:[NSURL URLWithString:self.url]]; - } - return [[MGLVectorTileSource alloc] initWithIdentifier:self.id tileURLTemplates:self.tileUrlTemplates options:[self getOptions]]; -} + - (nullable MGLSource*)makeSource + { + if (self.url != nil) { + return [[MGLVectorTileSource alloc] initWithIdentifier:self.id configurationURL:[NSURL URLWithString:self.url]]; + } + return [[MGLVectorTileSource alloc] initWithIdentifier:self.id tileURLTemplates:self.tileUrlTemplates options:[self getOptions]]; + } -- (nonnull NSArray> *)featuresInSourceLayersWithIdentifiers:(nonnull NSSet *)sourceLayerIdentifiers predicate:(nullable NSPredicate *)predicate -{ - MGLVectorTileSource* vectorSource = (MGLVectorTileSource*)self.source; - - return [vectorSource featuresInSourceLayersWithIdentifiers:sourceLayerIdentifiers predicate: predicate]; -}*/ + - (nonnull NSArray> *)featuresInSourceLayersWithIdentifiers:(nonnull NSSet *)sourceLayerIdentifiers predicate:(nullable NSPredicate *)predicate + { + MGLVectorTileSource* vectorSource = (MGLVectorTileSource*)self.source; + return [vectorSource featuresInSourceLayersWithIdentifiers:sourceLayerIdentifiers predicate: predicate]; + }*/ } diff --git a/ios/RCTMGL-v10/RCTMGLVectorSourceManager.swift b/ios/RCTMGL-v10/RCTMGLVectorSourceManager.swift index 11c5c5a37..22c881dba 100644 --- a/ios/RCTMGL-v10/RCTMGLVectorSourceManager.swift +++ b/ios/RCTMGL-v10/RCTMGLVectorSourceManager.swift @@ -4,7 +4,7 @@ class RCTMGLVectorSourceManager: RCTViewManager { override static func requiresMainQueueSetup() -> Bool { return true } - + @objc override func view() -> UIView { return RCTMGLVectorSource() } diff --git a/ios/RCTMGL-v10/RNMBImageUtils.swift b/ios/RCTMGL-v10/RNMBImageUtils.swift index 3407b1230..b55fd8d77 100644 --- a/ios/RCTMGL-v10/RNMBImageUtils.swift +++ b/ios/RCTMGL-v10/RNMBImageUtils.swift @@ -2,19 +2,18 @@ class RNMBImageUtils { static func createTempFile(_ image: UIImage) -> URL { let fileID = UUID().uuidString let pathComponent = "Documents/rctmgl-snapshot-\(fileID).png" - + let filePath = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent(pathComponent) - + let data = image.pngData() try! data?.write(to: filePath, options: [.atomic]) return filePath } - + static func createBase64(_ image: UIImage) -> URL { let data = image.pngData() - let b64string : String = data!.base64EncodedString(options: [.endLineWithCarriageReturn]) + let b64string: String = data!.base64EncodedString(options: [.endLineWithCarriageReturn]) let result = "data:image/png;base64,\(b64string)" return URL(string: result)! } } -