Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More SymbolLayer properties + sourceLayerIdentifier support + zoom levels + local image support #42

Merged
merged 8 commits into from
Jul 31, 2024

Conversation

hactar
Copy link
Collaborator

@hactar hactar commented Jul 22, 2024

Sorry for conglomerate of different changes - these were missing features we needed for a testflight release.

  • Added multiple properties to the SymbolLayer so one can set more of the text attributes that were missing.
  • Added support for specifying zoom levels. It works, but there was some zoom level code already, so please verify that what I added is as intended.
  • Added support for dynamic images on the SymbolLayer. It is similar to the code you had, but uses "keyPath" instead of "attribute" to access the feature property.
  • Added sourceLayerIdentifier (https://maplibre.org/maplibre-native/ios/latest/documentation/maplibre/mlnvectorstylelayer/sourcelayeridentifier), needed to be able to access a specific source layer combined with MLNSource.

Here is a screenshot from our app, using all these features (notice the text, halos, dynamic images created locally from sf symbols, etc - all this is loaded from a source in the style json):

349133201-b2f45437-2ad3-4cae-9817-3cdb3af06e46

Tests do not pass, I will update the PR once #41 is merged.

Package.swift Outdated Show resolved Hide resolved
@@ -161,3 +161,13 @@ public extension StyleLayer {
modified(self) { $0.insertionPosition = .belowOthers }
}
}

public extension StyleLayerDefinition {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review if this how you picture its usage, as I see other zoom level code in this spm already, but didn't find a way to access it from the MapView view builder.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Archdoog on our review call: "I think he is on to something fantastic" 😂 We definitely missed exposing this idiomatically in the high-level StyleLayerDefinition!

Capturing another random thought: it might make sense to split this file up since it's now got a bunch of random crap in it :) Especially for things like modifiers which might not be as obvious/discoverable. (Can do this later.)

Comment on lines -44 to +58
fileprivate var iconImageName: NSExpression?
public var iconImageName: NSExpression?

private var iconImages = [UIImage]()
public var iconImages = [UIImage]()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made these two public, because this allows devs to make their own extensions for the SymbolStyleLayer. For example, we created a helper extension for ourselves like this, but needed these properties exposed to do so:

public extension SymbolStyleLayer {

    func iconImage(mappings: [AnyHashable: UIImage], default defaultImage: UIImage) -> Self {
        return modified(self) { it in

            let expression1 = NSExpression(forKeyPath: "ios_category_icon_name")
            let expression2 = NSExpression(forKeyPath: "ios_category_icon_color")

            // Create an NSExpression that concatenates the two key paths
            let attributeExpression = expression1.mgl_appending(expression2)
            let mappingExpressions = mappings.mapValues { image in
                NSExpression(forConstantValue: image.sha256())
            }
            let mappingDictionary = NSDictionary(dictionary: mappingExpressions)
            let defaultExpression = NSExpression(forConstantValue: defaultImage.sha256())

            // swiftlint:disable force_cast
            it.iconImageName = NSExpression(
                forMLNMatchingKey: attributeExpression,
                in: mappingDictionary as! [NSExpression: NSExpression],
                default: defaultExpression
            )
            // swiftlint:enable force_cast
            it.iconImages = mappings.values + [defaultImage]
        }
    }

}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Thanks for the detailed example clarifying the use case!

Copy link
Collaborator

@ianthetechie ianthetechie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome; thanks as always!

Final bit of feedback: could you implement the example that shows dynamic icon selection? There's a first pass which is currently commented out at the bottom of Examples/Layers.swift.

@@ -161,3 +161,13 @@ public extension StyleLayer {
modified(self) { $0.insertionPosition = .belowOthers }
}
}

public extension StyleLayerDefinition {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Archdoog on our review call: "I think he is on to something fantastic" 😂 We definitely missed exposing this idiomatically in the high-level StyleLayerDefinition!

Capturing another random thought: it might make sense to split this file up since it's now got a bunch of random crap in it :) Especially for things like modifiers which might not be as obvious/discoverable. (Can do this later.)

Comment on lines -44 to +58
fileprivate var iconImageName: NSExpression?
public var iconImageName: NSExpression?

private var iconImages = [UIImage]()
public var iconImages = [UIImage]()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Thanks for the detailed example clarifying the use case!

Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift Outdated Show resolved Hide resolved
@hactar
Copy link
Collaborator Author

hactar commented Jul 25, 2024

So I tried adding the example to the the example layers file, but for some reason it crashes in the Preview here (and only here). If I create an app project and add the same code, there is no crash and the code works both in preview mode and in the app.

I have no idea why this may be, I'm blaming it on the package not being a real app, but I have no proof for this. I have attached a screenshot of this working, as well as a demo app to this comment. Maybe someone else knows whats going on, or else we just don't provide an un-commented in example...

MapLibreDSLThing.zip

Screenshot 2024-07-25 at 11 50 22

@hactar hactar requested a review from ianthetechie July 25, 2024 09:56
@ianthetechie
Copy link
Collaborator

🤯 whoa! What on earth?? Previews are weird, yeah, but.... okay. That's interesting. That also probably explains why, after trying several different things a few weeks ago, I never got anything that worked for image matching! I was only ever testing in the previews.

I'll take a look, but I believe that means this is probably mergeable as-is and we'll have to raise an issue upstream after collecting some more details on the crash.

@ianthetechie ianthetechie merged commit e958f2e into maplibre:main Jul 31, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants