diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
index 389b8ab67..b593ff70e 100644
--- a/platform/darwin/src/MGLFeature.h
+++ b/platform/darwin/src/MGLFeature.h
@@ -89,10 +89,6 @@ NS_ASSUME_NONNULL_BEGIN
tile source.
*/
@interface MGLPointFeature : MGLPointAnnotation
-
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
-
@end
/**
@@ -100,10 +96,6 @@ NS_ASSUME_NONNULL_BEGIN
tile source.
*/
@interface MGLPolylineFeature : MGLPolyline
-
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
-
@end
/**
@@ -111,10 +103,6 @@ NS_ASSUME_NONNULL_BEGIN
tile source.
*/
@interface MGLPolygonFeature : MGLPolygon
-
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
-
@end
/**
@@ -122,10 +110,6 @@ NS_ASSUME_NONNULL_BEGIN
tile source.
*/
@interface MGLMultiPointFeature : MGLMultiPoint
-
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
-
@end
/**
@@ -133,10 +117,6 @@ NS_ASSUME_NONNULL_BEGIN
tile source.
*/
@interface MGLMultiPolylineFeature : MGLMultiPolyline
-
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
-
@end
/**
@@ -144,10 +124,6 @@ NS_ASSUME_NONNULL_BEGIN
tile source.
*/
@interface MGLMultiPolygonFeature : MGLMultiPolygon
-
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
-
@end
/**
@@ -155,10 +131,6 @@ NS_ASSUME_NONNULL_BEGIN
tile source.
*/
@interface MGLShapeCollectionFeature : MGLShapeCollection
-
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
-
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
index 68c57a193..3e60b2061 100644
--- a/platform/darwin/src/MGLFeature.mm
+++ b/platform/darwin/src/MGLFeature.mm
@@ -6,10 +6,116 @@
#import "MGLMultiPoint_Private.h"
+@protocol MGLFeaturePrivate
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+@interface MGLPointFeature ()
+@end
+
+@implementation MGLPointFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLPolylineFeature ()
+@end
+
+@implementation MGLPolylineFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLPolygonFeature ()
+@end
+
+@implementation MGLPolygonFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLMultiPointFeature ()
+@end
+
+@implementation MGLMultiPointFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLMultiPolylineFeature ()
+@end
+
+@implementation MGLMultiPolylineFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLMultiPolygonFeature ()
+@end
+
+@implementation MGLMultiPolygonFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLShapeCollectionFeature ()
+@end
+
+@implementation MGLShapeCollectionFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+/**
+ Recursively transforms a C++ type into the corresponding Foundation type.
+ */
class PropertyValueEvaluator {
public:
- PropertyValueEvaluator() {}
-
id operator()(const std::nullptr_t &) const {
return [NSNull null];
}
@@ -37,10 +143,9 @@ public:
id operator()(const std::vector &values) const {
std::vector objects;
objects.reserve(values.size());
- std::transform(values.begin(), values.end(), std::back_inserter(objects), ^id (const mbgl::Value &value) {
- PropertyValueEvaluator evaluator;
- return mbgl::Value::visit(value, evaluator);
- });
+ for (const auto &v : values) {
+ objects.push_back(mbgl::Value::visit(v, *this));
+ }
return [NSArray arrayWithObjects:&objects[0] count:objects.size()];
}
@@ -51,49 +156,34 @@ public:
objects.reserve(items.size());
for (auto &item : items) {
keys.push_back(@(item.first.c_str()));
- PropertyValueEvaluator evaluator;
- objects.push_back(mbgl::Value::visit(item.second, evaluator));
+ objects.push_back(mbgl::Value::visit(item.second, *this));
}
return [NSDictionary dictionaryWithObjects:&objects[0] forKeys:&keys[0] count:keys.size()];
}
};
+/**
+ Transforms an `mbgl::geometry::geometry` type into an instance of the
+ corresponding Objective-C geometry class.
+ */
template
class GeometryEvaluator {
public:
- GeometryEvaluator()
- : attributes([NSMutableDictionary dictionary]) {}
-
- GeometryEvaluator(const mbgl::Feature &feature)
- : tag(feature.id ? @(*feature.id) : nullptr),
- attributes([NSMutableDictionary dictionaryWithCapacity:feature.properties.size()]) {
- for (auto &pair : feature.properties) {
- auto &value = pair.second;
- PropertyValueEvaluator evaluator;
- attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator);
- }
- }
-
- MGLShape * operator()(const mapbox::geometry::point &geometry) const {
+ MGLShape * operator()(const mapbox::geometry::point &geometry) const {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
feature.coordinate = coordinateFromPoint(geometry);
- feature.identifier = tag;
- feature.attributes = attributes;
return feature;
}
- MGLShape * operator()(const mapbox::geometry::line_string &geometry) const {
+ MGLShape * operator()(const mapbox::geometry::line_string &geometry) const {
std::vector coordinates;
coordinates.reserve(geometry.size());
std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPoint);
- MGLPolylineFeature *feature = [[MGLPolylineFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [[MGLPolylineFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
}
- MGLShape * operator()(const mapbox::geometry::polygon &geometry) const {
+ MGLShape * operator()(const mapbox::geometry::polygon &geometry) const {
// TODO: MGLPolygon doesn’t support holes, so what to do?
auto &linearRing = geometry.front();
@@ -101,24 +191,18 @@ public:
coordinates.reserve(linearRing.size());
std::transform(linearRing.begin(), linearRing.end(), std::back_inserter(coordinates), coordinateFromPoint);
- MGLPolygonFeature *feature = [[MGLPolygonFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [[MGLPolygonFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
}
- MGLShape * operator()(const mapbox::geometry::multi_point &geometry) const {
+ MGLShape * operator()(const mapbox::geometry::multi_point &geometry) const {
std::vector coordinates;
coordinates.reserve(geometry.size());
std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPoint);
- MGLMultiPointFeature *feature = [[MGLMultiPointFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [[MGLMultiPointFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
}
- MGLShape * operator()(const mapbox::geometry::multi_line_string &geometry) const {
+ MGLShape * operator()(const mapbox::geometry::multi_line_string &geometry) const {
NSMutableArray *polylines = [NSMutableArray arrayWithCapacity:geometry.size()];
for (auto &lineString : geometry) {
std::vector coordinates;
@@ -129,13 +213,10 @@ public:
[polylines addObject:polyline];
}
- MGLMultiPolylineFeature *feature = [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
}
- MGLShape * operator()(const mapbox::geometry::multi_polygon &geometry) const {
+ MGLShape * operator()(const mapbox::geometry::multi_polygon &geometry) const {
NSMutableArray *polygons = [NSMutableArray arrayWithCapacity:geometry.size()];
for (auto &polygon : geometry) {
// TODO: MGLPolygon doesn’t support holes, so what to do?
@@ -149,29 +230,21 @@ public:
[polygons addObject:polygonObject];
}
- MGLMultiPolygonFeature *feature = [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
}
- MGLShape * operator()(const mapbox::geometry::geometry_collection &collection) const {
+ MGLShape * operator()(const mapbox::geometry::geometry_collection &collection) const {
NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()];
for (auto &geometry : collection) {
+ // This is very much like the transformation that happens in MGLFeaturesFromMBGLFeatures(), but these are raw geometries with no associated feature IDs or attributes.
GeometryEvaluator evaluator;
- id feature = mapbox::geometry::geometry::visit(geometry, evaluator);
- [shapes addObject:feature];
+ MGLShape *shape = mapbox::geometry::geometry::visit(geometry, evaluator);
+ [shapes addObject:shape];
}
- MGLShapeCollectionFeature *feature = [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes];
}
private:
- NSNumber *tag = nullptr;
- NS_MUTABLE_DICTIONARY_OF(NSString *, id) *attributes;
-
static CLLocationCoordinate2D coordinateFromPoint(const mapbox::geometry::point &point) {
return CLLocationCoordinate2DMake(point.y, point.x);
}
@@ -181,64 +254,20 @@ NS_ARRAY_OF(MGLShape *) *MGLFeaturesFromMBGLFeatures(const std::vec
std::vector *> shapes;
shapes.reserve(features.size());
std::transform(features.begin(), features.end(), std::back_inserter(shapes), ^MGLShape * (const mbgl::Feature &feature) {
- GeometryEvaluator evaluator(feature);
- return mapbox::geometry::geometry::visit(feature.geometry, evaluator);
+ NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()];
+ for (auto &pair : feature.properties) {
+ auto &value = pair.second;
+ PropertyValueEvaluator evaluator;
+ attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator);
+ }
+
+ GeometryEvaluator evaluator;
+ MGLShape *shape = mapbox::geometry::geometry::visit(feature.geometry, evaluator);
+ if (feature.id) {
+ shape.identifier = @(*feature.id);
+ }
+ shape.attributes = attributes;
+ return shape;
});
return [NSArray arrayWithObjects:&shapes[0] count:shapes.size()];
}
-
-@implementation MGLPointFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLPolylineFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLPolygonFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLMultiPointFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLMultiPolylineFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLMultiPolygonFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLShapeCollectionFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h
index 837461871..fbc7f8855 100644
--- a/platform/darwin/src/MGLFeature_Private.h
+++ b/platform/darwin/src/MGLFeature_Private.h
@@ -4,4 +4,8 @@
#import
#import
+/**
+ Returns an array of `MGLFeature` objects converted from the given vector of
+ vector tile features.
+ */
NS_ARRAY_OF(MGLShape *) *MGLFeaturesFromMBGLFeatures(const std::vector &features);