From 4d69cd5a5f699aa39e298f4c06012c67b3261035 Mon Sep 17 00:00:00 2001 From: PW Date: Fri, 26 Apr 2024 12:16:30 +0200 Subject: [PATCH 1/4] adding clustering support and some text support --- Package.resolved | 14 +++--- Package.swift | 2 +- .../MapLibreSwiftDSL/ShapeDataBuilder.swift | 11 +++-- .../Style Layers/Circle.swift | 9 +++- .../MapLibreSwiftDSL/Style Layers/Line.swift | 6 ++- .../Style Layers/Style Layer.swift | 26 ++++++++++ .../Style Layers/Symbol.swift | 22 ++++++--- Sources/MapLibreSwiftUI/Examples/Layers.swift | 48 +++++++++++++++++++ 8 files changed, 117 insertions(+), 21 deletions(-) diff --git a/Package.resolved b/Package.resolved index 816bfbd..25e0fc2 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,17 +5,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/maplibre/maplibre-gl-native-distribution.git", "state" : { - "revision" : "92505cfbad5c5ed6a93e0f3cd70872aaa98a12ac", - "version" : "6.2.0" + "revision" : "6d0071977ed1f2380c739715f82ac650f99b0824", + "version" : "6.4.0" } }, { "identity" : "maplibre-swift-macros", "kind" : "remoteSourceControl", - "location" : "https://github.com/stadiamaps/maplibre-swift-macros.git", + "location" : "https://github.com/hactar/maplibre-swift-macros.git", "state" : { - "revision" : "9f15cbb11d2b5248ead47aecae5be8a1d4d5f463", - "version" : "0.0.2" + "branch" : "public-expression", + "revision" : "8cc58a6ed5911d88e610f76e50facb2c34a7b306" } }, { @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "5b0c434778f2c1a4c9b5ebdb8682b28e84dd69bd", - "version" : "1.15.4" + "revision" : "625ccca8570773dd84a34ee51a81aa2bc5a4f97a", + "version" : "1.16.0" } }, { diff --git a/Package.swift b/Package.swift index bc273c8..8ff2696 100644 --- a/Package.swift +++ b/Package.swift @@ -22,7 +22,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/maplibre/maplibre-gl-native-distribution.git", from: "6.1.0"), - .package(url: "https://github.com/stadiamaps/maplibre-swift-macros.git", from: "0.0.2"), + .package(url: "https://github.com/hactar/maplibre-swift-macros.git", branch: "public-expression"), // Testing .package(url: "https://github.com/Kolos65/Mockable.git", exact: "0.0.3"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.15.3"), diff --git a/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift b/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift index ea5b3b0..0d7dee3 100644 --- a/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift +++ b/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift @@ -21,22 +21,25 @@ public enum ShapeData { public struct ShapeSource: Source { public let identifier: String + public let options: [MLNShapeSourceOption : Any]? let data: ShapeData - public init(identifier: String, @ShapeDataBuilder _ makeShapeDate: () -> ShapeData) { + public init(identifier: String, options: [MLNShapeSourceOption : Any]? = nil, @ShapeDataBuilder _ makeShapeDate: () -> ShapeData) { self.identifier = identifier + self.options = options data = makeShapeDate() + } public func makeMGLSource() -> MLNSource { // TODO: Options! These should be represented via modifiers like .clustered() switch data { case let .geoJSONURL(url): - MLNShapeSource(identifier: identifier, url: url) + MLNShapeSource(identifier: identifier, url: url, options: options) case let .shapes(shapes): - MLNShapeSource(identifier: identifier, shapes: shapes) + MLNShapeSource(identifier: identifier, shapes: shapes, options: options) case let .features(features): - MLNShapeSource(identifier: identifier, features: features) + MLNShapeSource(identifier: identifier, features: features, options: options) } } } diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift b/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift index f835f98..1154fee 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift @@ -7,7 +7,8 @@ import MapLibreSwiftMacros @MLNStyleProperty("color", supportsInterpolation: false) @MLNStyleProperty("strokeWidth", supportsInterpolation: true) @MLNStyleProperty("strokeColor", supportsInterpolation: false) -public struct CircleStyleLayer: SourceBoundStyleLayerDefinition { +public struct CircleStyleLayer: SourceBoundVectorStyleLayerDefinition { + public let identifier: String public var insertionPosition: LayerInsertionPosition = .aboveOthers public var isVisible: Bool = true @@ -15,6 +16,7 @@ public struct CircleStyleLayer: SourceBoundStyleLayerDefinition { public var minimumZoomLevel: Float? = nil public var source: StyleLayerSource + public var predicate: NSPredicate? public init(identifier: String, source: Source) { self.identifier = identifier @@ -33,6 +35,8 @@ public struct CircleStyleLayer: SourceBoundStyleLayerDefinition { } // MARK: - Modifiers + + } private struct CircleStyleLayerInternal: StyleLayer { @@ -74,6 +78,9 @@ private struct CircleStyleLayerInternal: StyleLayer { result.circleStrokeWidth = definition.strokeWidth result.circleStrokeColor = definition.strokeColor + result.predicate = definition.predicate + + return result } } diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Line.swift b/Sources/MapLibreSwiftDSL/Style Layers/Line.swift index 93cd143..d97173a 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Line.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Line.swift @@ -8,7 +8,7 @@ import MapLibreSwiftMacros @MLNRawRepresentableStyleProperty("lineCap") @MLNRawRepresentableStyleProperty("lineJoin") @MLNStyleProperty("lineWidth", supportsInterpolation: true) -public struct LineStyleLayer: SourceBoundStyleLayerDefinition { +public struct LineStyleLayer: SourceBoundVectorStyleLayerDefinition { public let identifier: String public var insertionPosition: LayerInsertionPosition = .aboveOthers public var isVisible: Bool = true @@ -16,6 +16,7 @@ public struct LineStyleLayer: SourceBoundStyleLayerDefinition { public var minimumZoomLevel: Float? = nil public var source: StyleLayerSource + public var predicate: NSPredicate? public init(identifier: String, source: Source) { self.identifier = identifier @@ -71,6 +72,9 @@ private struct LineStyleLayerInternal: StyleLayer { result.lineCap = definition.lineCap result.lineWidth = definition.lineWidth result.lineJoin = definition.lineJoin + + result.predicate = definition.predicate + return result } diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift index 6dda066..891908b 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift @@ -77,6 +77,32 @@ public protocol SourceBoundStyleLayerDefinition: StyleLayerDefinition { var source: StyleLayerSource { get set } } + +/// Based on MLNVectorStyleLayer +public protocol SourceBoundVectorStyleLayerDefinition: SourceBoundStyleLayerDefinition { + /** + The style layer’s predicate. + + Use the style layer’s predicate to include only the features in the source + layer that satisfy a condition that you define. + + See the *Predicates and Expressions* + guide for details about the predicate syntax supported by this class. + */ + var predicate: NSPredicate? { get set } + + func predicate(_ predicate: NSPredicate) -> Self +} + +extension SourceBoundVectorStyleLayerDefinition { + public func predicate(_ predicate: NSPredicate) -> Self { + modified(self) { it in + it.predicate = predicate + } + } +} + + extension SourceBoundStyleLayerDefinition { func addSource(to style: MLNStyle) -> MLNSource { let tmpSource: MLNSource diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift b/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift index 3319251..13029fa 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift @@ -5,8 +5,12 @@ import MapLibreSwiftMacros @MLNStyleProperty("iconRotation", supportsInterpolation: true) @MLNStyleProperty("iconColor", supportsInterpolation: true) +@MLNStyleProperty("textColor", supportsInterpolation: true) +@MLNStyleProperty("textFontSize", supportsInterpolation: true) +@MLNStyleProperty("text", supportsInterpolation: false) +@MLNStyleProperty("iconAllowsOverlap", supportsInterpolation: false) -public struct SymbolStyleLayer: SourceBoundStyleLayerDefinition { +public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition { public let identifier: String public var insertionPosition: LayerInsertionPosition = .aboveOthers public var isVisible: Bool = true @@ -14,6 +18,7 @@ public struct SymbolStyleLayer: SourceBoundStyleLayerDefinition { public var minimumZoomLevel: Float? = nil public var source: StyleLayerSource + public var predicate: NSPredicate? public init(identifier: String, source: Source) { self.identifier = identifier @@ -61,12 +66,6 @@ public struct SymbolStyleLayer: SourceBoundStyleLayerDefinition { // it.iconImages = mappings.values + [defaultImage] // } // } - - public func iconRotation(expression: NSExpression) -> Self { - modified(self) { it in - it.iconRotation = expression - } - } } private struct SymbolStyleLayerInternal: StyleLayer { @@ -105,6 +104,15 @@ private struct SymbolStyleLayerInternal: StyleLayer { result.iconImageName = definition.iconImageName result.iconRotation = definition.iconRotation result.iconColor = definition.iconColor + result.text = definition.text + result.textColor = definition.textColor + result.textFontSize = definition.textFontSize + + result.iconAllowsOverlap = definition.iconAllowsOverlap + + result.predicate = definition.predicate + + return result } diff --git a/Sources/MapLibreSwiftUI/Examples/Layers.swift b/Sources/MapLibreSwiftUI/Examples/Layers.swift index 4c464ef..d3984f2 100644 --- a/Sources/MapLibreSwiftUI/Examples/Layers.swift +++ b/Sources/MapLibreSwiftUI/Examples/Layers.swift @@ -21,6 +21,18 @@ let pointSource = ShapeSource(identifier: "points") { } } +@MainActor +let clustered = ShapeSource(identifier: "points", options: [.clustered: true, .clusterRadius: 44]) { + // Uses the DSL to quickly construct point features inline + MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.2082, longitude: 16.3719)) + + MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.3082, longitude: 16.3719)) + + MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.2082, longitude: 16.9719)) + + MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.0082, longitude: 17.9719)) +} + #Preview("Rose Tint") { MapView(styleURL: demoTilesURL) { // Silly example: a background layer on top of everything to create a tint effect @@ -76,6 +88,42 @@ let pointSource = ShapeSource(identifier: "points") { .ignoresSafeArea(.all) } +#Preview("Clustered Circles with Symbols") { + @State var camera = MapViewCamera.center(CLLocationCoordinate2D(latitude: 48.2082, longitude: 16.3719), zoom: 5, direction: 0) + return MapView(styleURL: demoTilesURL, camera: $camera) { + // Clusters pins when they would touch + + // Cluster == YES shows only those pins that are clustered, using .text + CircleStyleLayer(identifier: "simple-circles-clusters", source: clustered) + .radius(16) + .color(.systemRed) + .strokeWidth(2) + .strokeColor(.white) + .predicate(NSPredicate(format: "cluster == YES")) + + SymbolStyleLayer(identifier: "simple-symbols-clusters", source: clustered) + .textColor(.white) + .text(expression: NSExpression(format: "CAST(point_count, 'NSString')")) + .predicate(NSPredicate(format: "cluster == YES")) + + + // Cluster != YES shows only those pins that are not clustered, using an icon + CircleStyleLayer(identifier: "simple-circles-non-clusters", source: clustered) + .radius(16) + .color(.systemRed) + .strokeWidth(2) + .strokeColor(.white) + .predicate(NSPredicate(format: "cluster != YES")) + + SymbolStyleLayer(identifier: "simple-symbols-non-clusters", source: clustered) + .iconImage(UIImage(systemName: "mappin")!.withRenderingMode(.alwaysTemplate)) + .iconColor(.white) + .predicate(NSPredicate(format: "cluster != YES")) + + } + .ignoresSafeArea(.all) +} + // TODO: Fixme // #Preview("Multiple Symbol Icons") { // MapView(styleURL: demoTilesURL) { From 486013d093a7cf976959902da3dffde96a38b202 Mon Sep 17 00:00:00 2001 From: PW Date: Mon, 29 Apr 2024 17:05:50 +0200 Subject: [PATCH 2/4] linting --- .../MapLibreSwiftDSL/ShapeDataBuilder.swift | 9 ++++-- .../Style Layers/Circle.swift | 4 --- .../MapLibreSwiftDSL/Style Layers/Line.swift | 3 +- .../Style Layers/Style Layer.swift | 12 ++++---- .../Style Layers/Symbol.swift | 6 ++-- Sources/MapLibreSwiftUI/Examples/Layers.swift | 30 ++++++++++--------- 6 files changed, 30 insertions(+), 34 deletions(-) diff --git a/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift b/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift index 0d7dee3..84c6eb4 100644 --- a/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift +++ b/Sources/MapLibreSwiftDSL/ShapeDataBuilder.swift @@ -21,14 +21,17 @@ public enum ShapeData { public struct ShapeSource: Source { public let identifier: String - public let options: [MLNShapeSourceOption : Any]? + public let options: [MLNShapeSourceOption: Any]? let data: ShapeData - public init(identifier: String, options: [MLNShapeSourceOption : Any]? = nil, @ShapeDataBuilder _ makeShapeDate: () -> ShapeData) { + public init( + identifier: String, + options: [MLNShapeSourceOption: Any]? = nil, + @ShapeDataBuilder _ makeShapeDate: () -> ShapeData + ) { self.identifier = identifier self.options = options data = makeShapeDate() - } public func makeMGLSource() -> MLNSource { diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift b/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift index 1154fee..02d49fa 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift @@ -8,7 +8,6 @@ import MapLibreSwiftMacros @MLNStyleProperty("strokeWidth", supportsInterpolation: true) @MLNStyleProperty("strokeColor", supportsInterpolation: false) public struct CircleStyleLayer: SourceBoundVectorStyleLayerDefinition { - public let identifier: String public var insertionPosition: LayerInsertionPosition = .aboveOthers public var isVisible: Bool = true @@ -35,8 +34,6 @@ public struct CircleStyleLayer: SourceBoundVectorStyleLayerDefinition { } // MARK: - Modifiers - - } private struct CircleStyleLayerInternal: StyleLayer { @@ -80,7 +77,6 @@ private struct CircleStyleLayerInternal: StyleLayer { result.predicate = definition.predicate - return result } } diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Line.swift b/Sources/MapLibreSwiftDSL/Style Layers/Line.swift index d97173a..c6d65cb 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Line.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Line.swift @@ -72,9 +72,8 @@ private struct LineStyleLayerInternal: StyleLayer { result.lineCap = definition.lineCap result.lineWidth = definition.lineWidth result.lineJoin = definition.lineJoin - + result.predicate = definition.predicate - return result } diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift index 891908b..4bd921c 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift @@ -77,32 +77,30 @@ public protocol SourceBoundStyleLayerDefinition: StyleLayerDefinition { var source: StyleLayerSource { get set } } - /// Based on MLNVectorStyleLayer public protocol SourceBoundVectorStyleLayerDefinition: SourceBoundStyleLayerDefinition { /** The style layer’s predicate. - + Use the style layer’s predicate to include only the features in the source layer that satisfy a condition that you define. - + See the *Predicates and Expressions* guide for details about the predicate syntax supported by this class. */ var predicate: NSPredicate? { get set } - + func predicate(_ predicate: NSPredicate) -> Self } -extension SourceBoundVectorStyleLayerDefinition { - public func predicate(_ predicate: NSPredicate) -> Self { +public extension SourceBoundVectorStyleLayerDefinition { + func predicate(_ predicate: NSPredicate) -> Self { modified(self) { it in it.predicate = predicate } } } - extension SourceBoundStyleLayerDefinition { func addSource(to style: MLNStyle) -> MLNSource { let tmpSource: MLNSource diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift b/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift index 13029fa..45338cf 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift @@ -107,12 +107,10 @@ private struct SymbolStyleLayerInternal: StyleLayer { result.text = definition.text result.textColor = definition.textColor result.textFontSize = definition.textFontSize - + result.iconAllowsOverlap = definition.iconAllowsOverlap - - result.predicate = definition.predicate - + result.predicate = definition.predicate return result } diff --git a/Sources/MapLibreSwiftUI/Examples/Layers.swift b/Sources/MapLibreSwiftUI/Examples/Layers.swift index d3984f2..05b7013 100644 --- a/Sources/MapLibreSwiftUI/Examples/Layers.swift +++ b/Sources/MapLibreSwiftUI/Examples/Layers.swift @@ -25,11 +25,11 @@ let pointSource = ShapeSource(identifier: "points") { let clustered = ShapeSource(identifier: "points", options: [.clustered: true, .clusterRadius: 44]) { // Uses the DSL to quickly construct point features inline MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.2082, longitude: 16.3719)) - + MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.3082, longitude: 16.3719)) - + MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.2082, longitude: 16.9719)) - + MLNPointFeature(coordinate: CLLocationCoordinate2D(latitude: 48.0082, longitude: 17.9719)) } @@ -89,10 +89,14 @@ let clustered = ShapeSource(identifier: "points", options: [.clustered: true, .c } #Preview("Clustered Circles with Symbols") { - @State var camera = MapViewCamera.center(CLLocationCoordinate2D(latitude: 48.2082, longitude: 16.3719), zoom: 5, direction: 0) + @State var camera = MapViewCamera.center( + CLLocationCoordinate2D(latitude: 48.2082, longitude: 16.3719), + zoom: 5, + direction: 0 + ) return MapView(styleURL: demoTilesURL, camera: $camera) { // Clusters pins when they would touch - + // Cluster == YES shows only those pins that are clustered, using .text CircleStyleLayer(identifier: "simple-circles-clusters", source: clustered) .radius(16) @@ -100,13 +104,12 @@ let clustered = ShapeSource(identifier: "points", options: [.clustered: true, .c .strokeWidth(2) .strokeColor(.white) .predicate(NSPredicate(format: "cluster == YES")) - + SymbolStyleLayer(identifier: "simple-symbols-clusters", source: clustered) .textColor(.white) .text(expression: NSExpression(format: "CAST(point_count, 'NSString')")) .predicate(NSPredicate(format: "cluster == YES")) - - + // Cluster != YES shows only those pins that are not clustered, using an icon CircleStyleLayer(identifier: "simple-circles-non-clusters", source: clustered) .radius(16) @@ -114,12 +117,11 @@ let clustered = ShapeSource(identifier: "points", options: [.clustered: true, .c .strokeWidth(2) .strokeColor(.white) .predicate(NSPredicate(format: "cluster != YES")) - - SymbolStyleLayer(identifier: "simple-symbols-non-clusters", source: clustered) - .iconImage(UIImage(systemName: "mappin")!.withRenderingMode(.alwaysTemplate)) - .iconColor(.white) - .predicate(NSPredicate(format: "cluster != YES")) - + + SymbolStyleLayer(identifier: "simple-symbols-non-clusters", source: clustered) + .iconImage(UIImage(systemName: "mappin")!.withRenderingMode(.alwaysTemplate)) + .iconColor(.white) + .predicate(NSPredicate(format: "cluster != YES")) } .ignoresSafeArea(.all) } From 73df215db354868835ce96851285721c56ce0309 Mon Sep 17 00:00:00 2001 From: Ian Wagner Date: Fri, 3 May 2024 15:23:23 +0900 Subject: [PATCH 3/4] Point to latest macro package --- Package.resolved | 6 +++--- Package.swift | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Package.resolved b/Package.resolved index 25e0fc2..8b80b5a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -12,10 +12,10 @@ { "identity" : "maplibre-swift-macros", "kind" : "remoteSourceControl", - "location" : "https://github.com/hactar/maplibre-swift-macros.git", + "location" : "https://github.com/stadiamaps/maplibre-swift-macros.git", "state" : { - "branch" : "public-expression", - "revision" : "8cc58a6ed5911d88e610f76e50facb2c34a7b306" + "revision" : "d52adbcbfaf96bd0723a156bd838826916ff7a69", + "version" : "0.0.3" } }, { diff --git a/Package.swift b/Package.swift index 8ff2696..06a554e 100644 --- a/Package.swift +++ b/Package.swift @@ -8,7 +8,7 @@ let package = Package( name: "MapLibreSwiftUI", platforms: [ .iOS(.v15), - .macOS(.v11), + .macOS(.v12), ], products: [ .library( @@ -21,8 +21,8 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/maplibre/maplibre-gl-native-distribution.git", from: "6.1.0"), - .package(url: "https://github.com/hactar/maplibre-swift-macros.git", branch: "public-expression"), + .package(url: "https://github.com/maplibre/maplibre-gl-native-distribution.git", from: "6.4.0"), + .package(url: "https://github.com/stadiamaps/maplibre-swift-macros.git", from: "0.0.3"), // Testing .package(url: "https://github.com/Kolos65/Mockable.git", exact: "0.0.3"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.15.3"), From 9fa5dc6e733dda51ad25c5e417fbd6b7e9c918ce Mon Sep 17 00:00:00 2001 From: Ian Wagner Date: Fri, 3 May 2024 15:23:47 +0900 Subject: [PATCH 4/4] Add link to referenced guide --- Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift index 4bd921c..814f754 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift @@ -86,7 +86,8 @@ public protocol SourceBoundVectorStyleLayerDefinition: SourceBoundStyleLayerDefi layer that satisfy a condition that you define. See the *Predicates and Expressions* - guide for details about the predicate syntax supported by this class. + guide for details about the predicate syntax supported by this class: + https://maplibre.org/maplibre-native/ios/api/predicates-and-expressions.html */ var predicate: NSPredicate? { get set }