-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add features initializer to MGLGeoJSONSource #6524
Conversation
@ituaijagbone, thanks for your PR! By analyzing this pull request, we identified @incanus, @1ec5 and @boundsj to be potential reviewers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're on the right track. Here are a few preliminary comments.
|
||
NSMutableArray *coordinates = [NSMutableArray array]; | ||
|
||
for (int index = 0; index < self.pointCount; index++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int might not be large enough for the number of coordinates that may be in this polyline. Use the same type as pointCount.
@@ -131,6 +131,9 @@ extern NSString * const MGLGeoJSONToleranceOption; | |||
*/ | |||
- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier URL:(NSURL *)url options:(NS_DICTIONARY_OF(NSString *, id) *)options NS_DESIGNATED_INITIALIZER; | |||
|
|||
|
|||
- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier Features:(NS_ARRAY_OF(id<MGLFeature>) *)features options:(nullable NS_DICTIONARY_OF(NSString *, id) *)options NS_DESIGNATED_INITIALIZER; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: lowercase the Features parameter.
NSString *string = [[NSString alloc] initWithData:self.geoJSONData encoding:NSUTF8StringEncoding]; | ||
const auto geojson = mapbox::geojson::parse(string.UTF8String).get<mapbox::geojson::feature_collection>(); | ||
source->setGeoJSON(geojson); | ||
_features = MGLFeaturesFromMBGLFeatures(geojson); | ||
} else { | ||
|
||
NSMutableArray<NS_DICTIONARY_OF(NSString *, id) *> *featuresArray = [NSMutableArray array]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the macros consistently: either change NSMutableArray to NS_MUTABLE_ARRAY_OF, or change NS_DICTIONARY_OF to NSDictionary.
@"features":featuresArray}; | ||
|
||
NSError *error; | ||
NSData *featuresJSONData = [NSJSONSerialization dataWithJSONObject:featureCollection options:NSJSONWritingPrettyPrinted error:&error]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty printing is good for debugging purposes, but it'll need to be removed before merging because it increases memory consumption.
- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary { | ||
// TODO: MGLPolygonFeature | ||
|
||
NS_MUTABLE_ARRAY_OF(NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *) *coordinates = [NSMutableArray array]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These macros (or the lightweight generics syntax) are useful in headers and method signatures, but they’re totally optional inside method implementations. As you can see, they’re a bit unwieldy, so there’s no shame in leaving them out inside the method.
return geometries; | ||
} | ||
|
||
- (void)addTypeAndCoordinatesFrom:(id<MGLFeature>)feature to:(NS_MUTABLE_ARRAY_OF(NS_DICTIONARY_OF(NSString *, id) *)**)geometries { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a questionable refactoring. First of all, since the array is mutable, you can simply pass a pointer to it rather than a double-pointer. Secondly, if all the classes that implement MGLFeature have a -featureDictionary
method, it would be cleaner to declare that method on MGLFeature. That way, -geometryCollection:
can simply call feature.featureDictionary
without caring which specific class feature
happens to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes You are right. Calling -featureDictionary should work directly. Thank you.
} | ||
|
||
- (NS_MUTABLE_ARRAY_OF(NS_DICTIONARY_OF(NSString *, id) *) *)geometryCollection:(NS_ARRAY_OF(MGLShape *) *)shapes { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MGLShapeCollectionFeature already knows about its shapes, so there’s no need to pass it in here. Just use self.shapes
inside the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 087f013
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Seems like we will need to regenerate the layer code to get the tests passing again now that the GeoJSON source method signatures have been updated.
@@ -23,11 +24,23 @@ @implementation MGLPointFeature | |||
|
|||
@synthesize identifier; | |||
@synthesize attributes; | |||
// synthesize the feature dictionary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd fine to remove this comment
|
||
- (id)attributeForKey:(NSString *)key { | ||
return self.attributes[key]; | ||
} | ||
|
||
- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary { | ||
return @{@"type":@"Feature", | ||
@"properties":(self.attributes) ? self.attributes : [NSDictionary dictionary], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit this could be an empty NSDictionary literal
@@ -70,6 +104,24 @@ - (id)attributeForKey:(NSString *)key { | |||
return self.attributes[key]; | |||
} | |||
|
|||
- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary { | |||
// TODO: MGLMultiPointFeature | |||
NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *coordinates = [NSMutableArray array]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I definitely prefer, inside method implementations, to just write NSMutableArray *coordinates
(+1 to #6524 (comment))
options for the source as specified by the | ||
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson">the | ||
style specification</a>. | ||
|
||
@param sourceIdentifier A string that uniquely identifies the source. | ||
@param URL An HTTP(S) URL, absolute file URL, or local file URL relative to the | ||
current application’s resource bundle. | ||
@param features An array of features that conform to the MGLFeature protocol. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It'd be nice to surround MGLFeature in back ticks so that the generated documentation highlights the word like MGLFeature
|
||
|
||
- (void)testMGLGeoJSONSourceWithPolygonFeatures { | ||
// TODO: Create feature |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit remove the scaffolding comments
@"features":featuresArray}; | ||
|
||
NSError *error; | ||
NSData *featuresJSONData = [NSJSONSerialization dataWithJSONObject:featureCollection options:0 error:&error]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#6524 (comment) suggested removing the pretty printing. Noting also that this will be refactored away in a future commit where we eventually just set mbgl::GeoJSON{ featureCollection }
and avoid the trip to create JSON data.
We should probably wait for #6588 to land before continuing with this because of the the duplicate work and conflicts in |
#6588 has landed. As expected, there are a number of conflicts, but they should be straightforward to resolve. |
e073b10
to
113c1dd
Compare
48ff580
to
44f88ab
Compare
@incanus @1ec5 @frederoni please feel free to have another look at this when you have a chance. I'm not sure why the CI builds started failing today but it does not seem to be related to any changes in this PR. Note the comment in 70962eb. I'm up for suggestions about where / how to share the |
|
||
@implementation MGLFeatureUtility | ||
|
||
// TODO: This is copied from NSExpression+MGLAdditions. Where should a shared implementation go? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about stuffing the value in an NSExpression and calling the existing category method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3770a036d68a4bcca7ffa91a4ff11036262d491a
- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary { | ||
return @{@"type": @"Feature", | ||
@"properties": (self.attributes) ? self.attributes : @{}, | ||
@"geometry" :@{@"type":@"Point", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: funky spacing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3770a036d68a4bcca7ffa91a4ff11036262d491a
return { }; | ||
} | ||
|
||
+ (mbgl::PropertyMap)propertyMapForDictionary:(NSDictionary *)dictionary propertyMap:(mbgl::PropertyMap *)propertyMap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass C++ objects around by reference rather than as pointers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3770a036d68a4bcca7ffa91a4ff11036262d491a
if ([dictionary[key] isKindOfClass:[NSDictionary class]]) { | ||
std::unordered_map<std::string, mbgl::Value> unorderedMap; | ||
[self propertyMapForDictionary:dictionary[key] propertyMap:&unorderedMap]; | ||
(*propertyMap)[[key cStringUsingEncoding:NSUTF8StringEncoding]] = unorderedMap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use .UTF8String.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3770a036d68a4bcca7ffa91a4ff11036262d491a
|
||
+ (mbgl::Feature)mbglFeatureWithPropertyMapForFeature:(mbgl::Feature)feature mglAttributes:(NSDictionary *)attributes { | ||
mbgl::PropertyMap propertyMap; | ||
[MGLFeatureUtility propertyMapForDictionary:attributes propertyMap:&propertyMap]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be more convenient for NSDictionary to know how to turn itself into a PropertyMap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3770a036d68a4bcca7ffa91a4ff11036262d491a
|
||
- (mbgl::Feature)mbglFeature { | ||
[NSException raise:@"Method unavailable" format:@"%s is not available on %@. Please use a concrete subclass of %@", __PRETTY_FUNCTION__, [self class], [self class]]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MGLShapeCollectionFeature is a concrete class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3a6be23e3a922e739b6e7b1687d5630621bb7ba6
or polygon. | ||
The `MGLMultiPoint` class is used to define shapes composed of multiple points. | ||
You can use the method and properties of this class to access information about | ||
the specific points associated with a line or polygon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mention that this class also doubles as a superclass of MGLPolyline and MGLPolygon, despite being a distinct geometry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3a6be23e3a922e739b6e7b1687d5630621bb7ba6
@param coords The array of coordinates defining the shape. The data in this | ||
array is copied to the new object. | ||
@param count The number of items in the `coords` array. | ||
@return A new MultiPoint object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: lowercase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3a6be23e3a922e739b6e7b1687d5630621bb7ba6
@implementation MGLPolygon (MGLAdditions) | ||
|
||
- (NS_ARRAY_OF(id) *)mgl_coordinates { | ||
NS_MUTABLE_ARRAY_OF(NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *) *coordinates = [NSMutableArray array]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really unwieldy. Just use an unqualified mutable array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also initialize it with a capacity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3770a036d68a4bcca7ffa91a4ff11036262d491a
@@ -166,6 +166,7 @@ | |||
404C26E71D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; }; | |||
404C26E81D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; }; | |||
4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */; }; | |||
40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bunch of these files are missing from the macOS project.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4268576d1e5dc05514ebf412a6b9723ab4623b93
Since yesterday afternoon, I'm still getting |
|
||
#import <mbgl/util/geometry.hpp> | ||
#import <mapbox/geometry/feature.hpp> | ||
|
||
@interface MGLFeatureUtility: NSObject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class doesn't seem to be adding much. The lone function can be a standalone C++ function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 206af31
- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary { | ||
return @{@"type": @"Feature", | ||
@"properties": (self.attributes) ? self.attributes : @{}, | ||
@"geometry": @{@"type": @"Point", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The non-feature direct subclasses of MGLShape should have geoJSONDictionary methods that encapsulate these geometry structures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once that happens, the bodies of most of these featureDictionary methods can be factored out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took this I idea and ran with it a bit in ad4e54d
} | ||
} | ||
|
||
return [geometries copy]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+[NSArray arrayWithArray:] creates a non-mutable array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is intentional. The method says that it returns a non-mutable array even though it uses a mutable array internally to create the collection
(NSArray *)geometryCollection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, I figured -[NSMutableArray copy]
returns an NSMutableArray, but it returns an NSArray. Carry on.
return [self propertyMapWithPropertyMap:propertyMap dictionary:self]; | ||
} | ||
|
||
- (mbgl::PropertyMap)propertyMapWithPropertyMap:(mbgl::PropertyMap &)propertyMap dictionary:(NSDictionary *)dictionary { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing in the property map by non-const reference is similar to an inout C parameter: you're actually mutating the map that's being passed in. So there's no need to return anything. In fact, this method could be renamed to "populatePropertyMap" or somesuch. But if an empty property map is always passed in, why not create it locally instead of accepting it as a parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the intent is to convert a dictionary into a property map, this could be a category method on NSDictionary that takes no parameters and returns a property map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was fixed in bc1dda3. Note thatpropertyMapWithDictionary:
and vectorForArray:
(name change in 95d548b) still take NSDictionary
s and NSArray
s so that the entire dictionary can be traversed (recursively) including if any node is a dictionary or array. The (mbgl::PropertyMap)mbgl_propertyMap
method already exists and is the only public method of the category. It is intended to take no parameters and return a property map.
return propertyMap; | ||
} | ||
|
||
- (std::vector<mbgl::Value>)vectorForNSArray:(NSArray *)array vector:(std::vector<mbgl::Value> &)vector { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, this would be a category method on NSArray that returns a vector of values, and the method name would be something like mgl_valueVector.
3a6be23
to
206af31
Compare
The dictionary includes the required geometry and properties dictionaries along | ||
with an "id" key and value if the underlying `MGLFeature` has an identifier. | ||
*/ | ||
- (NS_DICTIONARY_OF(NSString *, id) *)geoJSONFeatureDictionary; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The word “feature” in this method name is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0c317fa
@@ -91,6 +91,15 @@ NS_ASSUME_NONNULL_BEGIN | |||
*/ | |||
- (nullable id)attributeForKey:(NSString *)key; | |||
|
|||
/** | |||
Returns a dictionary that can be serialized as a GeoJSON Feature representation | |||
of the `MGLFeature` subclass. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pedantry: it’s a representation of an instance of the class, not of the class itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0c317fa
Returns a dictionary that can be serialized as a GeoJSON Feature representation | ||
of the `MGLFeature` subclass. | ||
|
||
The dictionary includes the required geometry and properties dictionaries along |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dictionary includes a
geometry
key corresponding to the receiver’s underlying geometry data, aproperties
key corresponding to the receiver’sattributes
property, and anid
key corresponding to the receiver’sidentifier
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0c317fa
@@ -42,6 +50,14 @@ - (id)attributeForKey:(NSString *)key { | |||
return self.attributes[key]; | |||
} | |||
|
|||
- (NSDictionary *)geoJSONFeatureDictionary { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename -geoJSONGeometryDictionary
to -geoJSONDictionary
and -geoJSONFeatureDictionary
to geoJSONDictionary
. Then this method can call super’s implementation and wrap it in NSDictionaryFeatureForGeometry()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0c317fa
NSMutableDictionary *feature = [@{@"type": @"Feature", | ||
@"properties": (attributes) ?: [NSNull null], | ||
@"geometry": geometry} mutableCopy]; | ||
if (identifier) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the if
statement is unnecessary; it’s perfectly fine to set to nil
using subscript notation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remove that conditional, I get a runtime exception when [NSExpression expressionForConstantValue:identifier];
is called. I'm using NSExpression for the conversion of the id to the mbgl variant .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, I wouldn't've expected foo[@"bar"] = nil
to do anything other than remove the "bar" key from foo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I was in mbglFeature()
not NSDictionaryFeatureForGeometry()
. Fixed in acf792b
return [self propertyMapWithDictionary:self]; | ||
} | ||
|
||
- (mbgl::PropertyMap)propertyMapWithDictionary:(NSDictionary *)dictionary { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the dictionary
parameter and use self
instead. Below, call the method recursively on dictionary[key]
rather than on self
. Then rename this method to -mgl_propertyMap
(not -mbgl_propertyMap
– MGL is the class prefix for this target).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0c317fa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And 3909852
} else if ([number compare:@(0)] == NSOrderedAscending) { | ||
return mbglValue.get<int64_t>(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we throw an exception if we encounter an unknown type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this and decided to not throw an exception when I added it yesterday.
The reason is that the first thing mgl_featureIdentifier
does is call mgl_convertedValueWithValue
which will throw an exception if there is an unknown type. mgl_featureIdentifier
exists only to be able to get the correct raw value from mbgl::Value
returned by mgl_convertedValueWithValue
and the only reason we are doing any of this here is to share the conversion logic that happens to currently live in the NSExpression
category.
I think you could make the case that we should catch an exception thrown by mgl_convertedValueWithValue
and re-raise it with a different message (instead of the Can’t convert %s:%@ to mbgl::Value
) that a developer will see if they send an invalid value for the id
/ identifier
. However, I was thinking that it might make sense to wait and refactor this if we introduce a category method on NSObject as you've suggested in conversation. It is a bit weird at the moment though.
return propertyMap; | ||
} | ||
|
||
- (std::vector<mbgl::Value>)vectorForArray:(NSArray *)array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this parameter too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 61f4d69
std::vector<mbgl::Value> vector; | ||
vector.reserve(array.count); | ||
for (id value in array) { | ||
if ([value isKindOfClass:[NSArray class]]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we refactor this so that any object knows how to "valueize" itself, we'll be able to remove these conditionals too.
XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry); | ||
} | ||
|
||
- (void)testShapeCollectionFeatureFeatureGeoJSONDictionary { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: feature feature! 🍕
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍕 - 1 in 184c475
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there!
@@ -157,6 +157,9 @@ | |||
35E79F201D41266300957B9E /* MGLStyleLayer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */; }; | |||
35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */; }; | |||
36F1153D1D46080700878E1A /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 36F1153B1D46080700878E1A /* libmbgl-core.a */; }; | |||
400533011DB0862B0069F638 /* NSArray+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 400532FF1DB0862B0069F638 /* NSArray+MGLAdditions.h */; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These files are missing from macos.xcodeproj. Also, NSArray+MGLAdditions.mm appears to be in Sources twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix macos. I used the standard mechanism in xcode for adding files. I guess I'll manually edit the file but seems strange that I need to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is common. I think every impl file is in there twice and often headers are too. Look just below:
404C26E21D89B877000AA13D /* MGLTileSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 404C26E31D89B877000AA13D /* MGLTileSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 404C26E41D89B877000AA13D /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSet.mm */; }; 404C26E51D89B877000AA13D /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSet.mm */; };
Maybe this is a bug related to adding to both static and dynamic targets?
I'm not going to touch this in this PR. Let's open a new issue to clean this up if we need to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to macos in c4ea541
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you’re right, I thought I was looking at the project structure but I was looking at target membership instead.
Regarding the macOS side, adding a file to ios.xcodeproj won’t automatically add it to macos.xcodeproj. I realize it’s a bit inconvenient. #5942 was an attempt at merging the two projects so that you always get presented with all three targets when adding a file. Unfortunately it slowed down the index too much for comfort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's fine. I just forgot
This adds a features initializer to MGLGeoJSONSource. The initializer takes shapes and converts them to JSON representation before passing to core. This also adds methods to the MGLShape concrete subclasses so that they can represent themselves in NSDictionary form suitable for transforming to JSON (GeoJSON).
c4ea541
to
ac22db1
Compare
Noting that although the Qt and Node builds show that they were unsuccessful they actually passed if you click through to bitrise. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whew!
MGLShape subclasses can now return NSDictionaries that represent the shapes' GeoJSON geometries. MGLFeature classes can now return NSDictionaries that represent the features as GeoJSON features. This makes it trivial to serialize iOS and macOS shapes and features into GeoJSON. MGLFeature instances can also return a representation of themselves as an mbgl::Feature. This capability is used in a refactoring of the implementations of MGLGeoJSONSource to more efficiently transform MGLFeatures into mbgl::Features so they can be fed directly into mbgl::GeoJSONSource without having to round trip through NSJSONSerialization. The MGLFeature identifier is converted into the mbgl::identifier type based on the type of the identifier. The MGLFeature attributes are recursively converted into an mbgl::PropertyMap and each value is converted into one of the types that the PropertyMap's Value variant supports.
ac22db1
to
6ffe51b
Compare
fixes #6302