diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-11-03 13:16:27 -0700 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-11-03 13:16:27 -0700 |
commit | 4f40fceb728258e486ffd0b813ddef3e4e2c3cd2 (patch) | |
tree | 8fa5fe2e12ffb36290e15c7163cf06c97b4f66e2 | |
parent | b8a2fd390cd4b3172e85d18c1718edb41c039036 (diff) | |
parent | 7c68d7773d208993c9ebb76ac42a440e1a27c29a (diff) | |
download | qtlocation-mapboxgl-4f40fceb728258e486ffd0b813ddef3e4e2c3cd2.tar.gz |
Merge branch 'release-ios-v3.4.0' into 1ec5-release-ios-v3.4.0-beta.2-master
52 files changed, 1258 insertions, 373 deletions
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 4bcfe54d32..62ab3b6b98 100644 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -152,6 +152,9 @@ global.describeValue = function (value, property, layerType) { case 'number': return 'an `NSNumber` object containing the float `' + value + '`'; case 'string': + if (value === '') { + return 'the empty string'; + } return 'the string `' + value + '`'; case 'enum': let displayValue; diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h index 239a338f67..384c5a073e 100644 --- a/platform/darwin/src/MGLFeature.h +++ b/platform/darwin/src/MGLFeature.h @@ -3,6 +3,7 @@ #import "MGLPolyline.h" #import "MGLPolygon.h" #import "MGLPointAnnotation.h" +#import "MGLPointCollection.h" #import "MGLShapeCollection.h" NS_ASSUME_NONNULL_BEGIN @@ -18,8 +19,8 @@ NS_ASSUME_NONNULL_BEGIN using `-[MGLMapView visibleFeaturesAtPoint:]` and related methods. Each feature object associates a shape with an identifier and attributes as specified by the source. Like ordinary `MGLAnnotation` objects, some kinds of `MGLFeature` - objects can also be added to a map view using `-[MGLMapView addAnnotations:]` - and related methods. + objects can also be added to a map view using an `MGLGeoJSONSource` or + `-[MGLMapView addAnnotations:]` and related methods. */ @protocol MGLFeature <MGLAnnotation> @@ -48,9 +49,13 @@ NS_ASSUME_NONNULL_BEGIN For details about the identifiers used in most Mapbox-provided styles, consult the <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets</a> - layer reference. + layer reference. Note that while it is possible to change this value on feature + instances obtained from `-[MGLMapView visibleFeaturesAtPoint:]` and related + methods, there will be no effect on the map. Setting this value can be useful + when the feature instance is used to initialize an `MGLGeoJSONSource` and that + source is added to the map and styled. */ -@property (nonatomic, copy, nullable, readonly) id identifier; +@property (nonatomic, copy, nullable) id identifier; /** A dictionary of attributes for this feature specified by the @@ -79,9 +84,13 @@ NS_ASSUME_NONNULL_BEGIN <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets</a> and <a href="https://www.mapbox.com/vector-tiles/mapbox-terrain/">Mapbox Terrain</a> - layer references. + layer references. Note that while it is possible to change this value on feature + instances obtained from `-[MGLMapView visibleFeaturesAtPoint:]` and related + methods, there will be no effect on the map. Setting this value can be useful + when the feature instance is used to initialize an `MGLGeoJSONSource` and that + source is added to the map and styled. */ -@property (nonatomic, copy, readonly) NS_DICTIONARY_OF(NSString *, id) *attributes; +@property (nonatomic, copy) NS_DICTIONARY_OF(NSString *, id) *attributes; /** Returns the feature attribute for the given attribute name. @@ -126,10 +135,10 @@ NS_ASSUME_NONNULL_BEGIN @end /** - The `MGLMultiPointFeature` class represents a multipoint in a + The `MGLPointCollectionFeature` class represents a multipoint in a <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>. */ -@interface MGLMultiPointFeature : MGLMultiPoint <MGLFeature> +@interface MGLPointCollectionFeature : MGLPointCollection <MGLFeature> @end /** diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm index 84dcc4f0bb..5483433710 100644 --- a/platform/darwin/src/MGLFeature.mm +++ b/platform/darwin/src/MGLFeature.mm @@ -6,7 +6,7 @@ #import "MGLValueEvaluator.h" #import "MGLShape_Private.h" -#import "MGLMultiPoint_Private.h" +#import "MGLPointCollection_Private.h" #import "MGLPolyline+MGLAdditions.h" #import "MGLPolygon+MGLAdditions.h" #import "NSDictionary+MGLAdditions.h" @@ -82,10 +82,10 @@ @end -@interface MGLMultiPointFeature () <MGLFeaturePrivate> +@interface MGLPointCollectionFeature () <MGLFeaturePrivate> @end -@implementation MGLMultiPointFeature +@implementation MGLPointCollectionFeature @synthesize identifier; @synthesize attributes; @@ -202,7 +202,7 @@ public: MGLShape <MGLFeaturePrivate> * operator()(const mbgl::MultiPoint<T> &geometry) const { std::vector<CLLocationCoordinate2D> coordinates = toLocationCoordinates2D(geometry); - return [[MGLMultiPointFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()]; + return [[MGLPointCollectionFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()]; } MGLShape <MGLFeaturePrivate> * operator()(const mbgl::MultiLineString<T> &geometry) const { diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h index 5fb82bde5b..e6858c7c11 100644 --- a/platform/darwin/src/MGLFeature_Private.h +++ b/platform/darwin/src/MGLFeature_Private.h @@ -26,9 +26,6 @@ NS_DICTIONARY_OF(NSString *, id) *NSDictionaryFeatureForGeometry(NSDictionary *g @protocol MGLFeaturePrivate <MGLFeature> -@property (nonatomic, copy, nullable, readwrite) id identifier; -@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes; - - (mbgl::Feature)mbglFeature; @end diff --git a/platform/darwin/src/MGLGeoJSONSource.h b/platform/darwin/src/MGLGeoJSONSource.h index 9eeb1e1188..30232c6211 100644 --- a/platform/darwin/src/MGLGeoJSONSource.h +++ b/platform/darwin/src/MGLGeoJSONSource.h @@ -7,33 +7,38 @@ NS_ASSUME_NONNULL_BEGIN @protocol MGLFeature; /** + Options for `MGLGeoJSONSource` objects. + */ +typedef NSString *MGLGeoJSONSourceOption NS_STRING_ENUM; + +/** An `NSNumber` object containing a Boolean enabling or disabling clustering. If the `features` property contains point features, setting this option to `YES` clusters the points by radius into groups. The default value is `NO`. */ -extern NSString * const MGLGeoJSONClusterOption; +extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClustered; /** An `NSNumber` object containing an integer; specifies the radius of each cluster if clustering is enabled. A value of 512 produces a radius equal to the width of a tile. The default value is 50. */ -extern NSString * const MGLGeoJSONClusterRadiusOption; +extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClusterRadius; /** An `NSNumber` object containing an integer; specifies the maximum zoom level at which to cluster points if clustering is enabled. Defaults to one zoom level - less than the value of `MGLGeoJSONMaximumZoomLevelOption` so that, at the + less than the value of `MGLGeoJSONSourceOptionMaximumZoomLevel` so that, at the maximum zoom level, the features are not clustered. */ -extern NSString * const MGLGeoJSONClusterMaximumZoomLevelOption; +extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevelForClustering; /** An `NSNumber` object containing an integer; specifies the maximum zoom level at which to create vector tiles. A greater value produces greater detail at high zoom levels. The default value is 18. */ -extern NSString * const MGLGeoJSONMaximumZoomLevelOption; +extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevel; /** An `NSNumber` object containing an integer; specifies the size of the tile @@ -41,14 +46,14 @@ extern NSString * const MGLGeoJSONMaximumZoomLevelOption; buffer as wide as the tile itself. Larger values produce fewer rendering artifacts near tile edges and slower performance. The default value is 128. */ -extern NSString * const MGLGeoJSONBufferOption; +extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionBuffer; /** An `NSNumber` object containing a double; specifies the Douglas-Peucker simplification tolerance. A greater value produces simpler geometries and improves performance. The default value is 0.375. */ -extern NSString * const MGLGeoJSONToleranceOption; +extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance; /** A GeoJSON source. @@ -71,7 +76,7 @@ extern NSString * const MGLGeoJSONToleranceOption; @param options An `NSDictionary` of options for this source. @return An initialized GeoJSON source. */ -- (instancetype)initWithIdentifier:(NSString *)identifier geoJSONData:(NSData *)data options:(nullable NS_DICTIONARY_OF(NSString *, id) *)options NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithIdentifier:(NSString *)identifier geoJSONData:(NSData *)data options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; /** Returns a GeoJSON source with an identifier, URL, and dictionary of options for @@ -85,7 +90,7 @@ extern NSString * const MGLGeoJSONToleranceOption; @param options An `NSDictionary` of options for this source. @return An initialized GeoJSON source. */ -- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(nullable NS_DICTIONARY_OF(NSString *, id) *)options NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; /** Returns a GeoJSON source with an identifier, features dictionary, and dictionary @@ -98,7 +103,7 @@ extern NSString * const MGLGeoJSONToleranceOption; @param options An `NSDictionary` of options for this source. @return An initialized GeoJSON source. */ -- (instancetype)initWithIdentifier:(NSString *)identifier features:(NSArray<id<MGLFeature>> *)features options:(nullable NS_DICTIONARY_OF(NSString *,id) *)options NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithIdentifier:(NSString *)identifier features:(NSArray<id<MGLFeature>> *)features options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; #pragma mark Accessing a Source’s Content @@ -109,13 +114,13 @@ extern NSString * const MGLGeoJSONToleranceOption; is set to `nil`. This property is unavailable until the receiver is passed into `-[MGLStyle addSource]`. */ -@property (nonatomic, readonly, nullable) NS_ARRAY_OF(id <MGLFeature>) *features; +@property (nonatomic, nullable) NS_ARRAY_OF(id <MGLFeature>) *features; /** A GeoJSON representation of the contents of the source. Use the `features` property instead to get an object representation of the - contents. Alternatively, use NSJSONSerialization with the value of this + contents. Alternatively, use `NSJSONSerialization` with the value of this property to transform it into Foundation types. If the receiver was initialized using `-initWithIdentifier:URL:options` or @@ -123,7 +128,7 @@ extern NSString * const MGLGeoJSONToleranceOption; This property is unavailable until the receiver is passed into `-[MGLStyle addSource]`. */ -@property (nonatomic, readonly, nullable, copy) NSData *geoJSONData; +@property (nonatomic, nullable, copy) NSData *geoJSONData; /** The URL to the GeoJSON document that specifies the contents of the source. @@ -131,7 +136,7 @@ extern NSString * const MGLGeoJSONToleranceOption; If the receiver was initialized using `-initWithIdentifier:geoJSONData:options`, this property is set to `nil`. */ -@property (nonatomic, readonly, nullable) NSURL *URL; +@property (nonatomic, nullable) NSURL *URL; @end diff --git a/platform/darwin/src/MGLGeoJSONSource.mm b/platform/darwin/src/MGLGeoJSONSource.mm index 27f2eb8bda..0dbe1030c6 100644 --- a/platform/darwin/src/MGLGeoJSONSource.mm +++ b/platform/darwin/src/MGLGeoJSONSource.mm @@ -1,5 +1,6 @@ -#import "MGLGeoJSONSource.h" +#import "MGLGeoJSONSource_Private.h" +#import "MGLMapView_Private.h" #import "MGLSource_Private.h" #import "MGLFeature_Private.h" @@ -7,20 +8,24 @@ #include <mbgl/style/sources/geojson_source.hpp> -NSString * const MGLGeoJSONClusterOption = @"MGLGeoJSONCluster"; -NSString * const MGLGeoJSONClusterRadiusOption = @"MGLGeoJSONClusterRadius"; -NSString * const MGLGeoJSONClusterMaximumZoomLevelOption = @"MGLGeoJSONClusterMaximumZoomLevel"; -NSString * const MGLGeoJSONMaximumZoomLevelOption = @"MGLGeoJSONMaximumZoomLevel"; -NSString * const MGLGeoJSONBufferOption = @"MGLGeoJSONBuffer"; -NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance"; +const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClustered = @"MGLGeoJSONSourceOptionClustered"; +const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClusterRadius = @"MGLGeoJSONSourceOptionClusterRadius"; +const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevelForClustering = @"MGLGeoJSONSourceOptionMaximumZoomLevelForClustering"; +const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevel = @"MGLGeoJSONSourceOptionMaximumZoomLevel"; +const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionBuffer = @"MGLGeoJSONSourceOptionBuffer"; +const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance = @"MGLGeoJSONSourceOptionSimplificationTolerance"; @interface MGLGeoJSONSource () @property (nonatomic, readwrite) NSDictionary *options; +@property (nonatomic) mbgl::style::GeoJSONSource *rawSource; @end @implementation MGLGeoJSONSource +{ + std::unique_ptr<mbgl::style::GeoJSONSource> _pendingSource; +} - (instancetype)initWithIdentifier:(NSString *)identifier geoJSONData:(NSData *)data options:(NS_DICTIONARY_OF(NSString *, id) *)options { @@ -28,6 +33,7 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance { _geoJSONData = data; _options = options; + [self commonInit]; } return self; } @@ -38,6 +44,7 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance { _URL = url; _options = options; + [self commonInit]; } return self; } @@ -46,47 +53,75 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance if (self = [super initWithIdentifier:identifier]) { _features = features; _options = options; + [self commonInit]; } return self; } +- (void)addToMapView:(MGLMapView *)mapView +{ + mapView.mbglMap->addSource(std::move(_pendingSource)); +} + +- (void)commonInit +{ + auto source = std::make_unique<mbgl::style::GeoJSONSource>(self.identifier.UTF8String, self.geoJSONOptions); + + if (self.URL) { + NSURL *url = self.URL.mgl_URLByStandardizingScheme; + source->setURL(url.absoluteString.UTF8String); + _features = nil; + } else if (self.geoJSONData) { + 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 { + mbgl::FeatureCollection featureCollection; + featureCollection.reserve(self.features.count); + for (id <MGLFeaturePrivate> feature in self.features) { + featureCollection.push_back([feature mbglFeature]); + } + const auto geojson = mbgl::GeoJSON{featureCollection}; + source->setGeoJSON(geojson); + _features = MGLFeaturesFromMBGLFeatures(featureCollection); + } + + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); +} + - (mbgl::style::GeoJSONOptions)geoJSONOptions { auto mbglOptions = mbgl::style::GeoJSONOptions(); - if (self.options[MGLGeoJSONMaximumZoomLevelOption]) { - id value = self.options[MGLGeoJSONMaximumZoomLevelOption]; + if (id value = self.options[MGLGeoJSONSourceOptionMaximumZoomLevel]) { [self validateValue:value]; mbglOptions.maxzoom = [value integerValue]; } - if (self.options[MGLGeoJSONBufferOption]) { - id value = self.options[MGLGeoJSONBufferOption]; + if (id value = self.options[MGLGeoJSONSourceOptionBuffer]) { [self validateValue:value]; mbglOptions.buffer = [value integerValue]; } - if (self.options[MGLGeoJSONToleranceOption]) { - id value = self.options[MGLGeoJSONToleranceOption]; + if (id value = self.options[MGLGeoJSONSourceOptionSimplificationTolerance]) { [self validateValue:value]; mbglOptions.tolerance = [value doubleValue]; } - if (self.options[MGLGeoJSONClusterRadiusOption]) { - id value = self.options[MGLGeoJSONClusterRadiusOption]; + if (id value = self.options[MGLGeoJSONSourceOptionClusterRadius]) { [self validateValue:value]; mbglOptions.clusterRadius = [value integerValue]; } - if (self.options[MGLGeoJSONClusterMaximumZoomLevelOption]) { - id value = self.options[MGLGeoJSONClusterMaximumZoomLevelOption]; + if (id value = self.options[MGLGeoJSONSourceOptionMaximumZoomLevelForClustering]) { [self validateValue:value]; mbglOptions.clusterMaxZoom = [value integerValue]; } - if (self.options[MGLGeoJSONClusterOption]) { - id value = self.options[MGLGeoJSONClusterOption]; + if (id value = self.options[MGLGeoJSONSourceOptionClustered]) { [self validateValue:value]; mbglOptions.cluster = [value boolValue]; } @@ -102,30 +137,51 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance } } -- (std::unique_ptr<mbgl::style::Source>)mbglSource +- (void)setGeoJSONData:(NSData *)geoJSONData { - auto source = std::make_unique<mbgl::style::GeoJSONSource>(self.identifier.UTF8String, self.geoJSONOptions); + _geoJSONData = geoJSONData; - if (self.URL) { - NSURL *url = self.URL.mgl_URLByStandardizingScheme; - source->setURL(url.absoluteString.UTF8String); - } else if (self.geoJSONData) { - 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 { - mbgl::FeatureCollection featureCollection; - featureCollection.reserve(self.features.count); - for (id <MGLFeaturePrivate> feature in self.features) { - featureCollection.push_back([feature mbglFeature]); - } - const auto geojson = mbgl::GeoJSON{featureCollection}; - source->setGeoJSON(geojson); - _features = MGLFeaturesFromMBGLFeatures(featureCollection); + if (self.rawSource == NULL) + { + [self commonInit]; + } + + NSString *string = [[NSString alloc] initWithData:_geoJSONData encoding:NSUTF8StringEncoding]; + const auto geojson = mapbox::geojson::parse(string.UTF8String).get<mapbox::geojson::feature_collection>(); + self.rawSource->setGeoJSON(geojson); + + _features = MGLFeaturesFromMBGLFeatures(geojson); +} + +- (void)setURL:(NSURL *)URL +{ + _URL = URL; + + if (self.rawSource == NULL) + { + [self commonInit]; + } + + NSURL *url = self.URL.mgl_URLByStandardizingScheme; + self.rawSource->setURL(url.absoluteString.UTF8String); +} + +- (void)setFeatures:(NSArray *)features +{ + if (self.rawSource == NULL) + { + [self commonInit]; + } + + mbgl::FeatureCollection featureCollection; + featureCollection.reserve(features.count); + for (id <MGLFeaturePrivate> feature in features) { + featureCollection.push_back([feature mbglFeature]); } + const auto geojson = mbgl::GeoJSON{featureCollection}; + self.rawSource->setGeoJSON(geojson); - return std::move(source); + _features = MGLFeaturesFromMBGLFeatures(featureCollection); } @end diff --git a/platform/darwin/src/MGLGeoJSONSource_Private.h b/platform/darwin/src/MGLGeoJSONSource_Private.h index 3aeb07ad25..de5bb10fac 100644 --- a/platform/darwin/src/MGLGeoJSONSource_Private.h +++ b/platform/darwin/src/MGLGeoJSONSource_Private.h @@ -1,3 +1,4 @@ +#import "MGLGeoJSONSource.h" #import "MGLGeoJSONSource_Private.h" #include <mbgl/style/sources/geojson_source.hpp> diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h index b936205ab2..69c7295842 100644 --- a/platform/darwin/src/MGLMultiPoint.h +++ b/platform/darwin/src/MGLMultiPoint.h @@ -6,25 +6,16 @@ NS_ASSUME_NONNULL_BEGIN /** - The `MGLMultiPoint` class is used to define shapes composed of multiple points. - This class is also the superclass of `MGLPolyline` and `MGLPolygon`. The - methods and properties of this class can be used to access information about - the specific points associated with a line or polygon. + The `MGLMultiPoint` class is an abstract superclass used to define shapes + composed of multiple points. You should not create instances of this class + directly. Instead, you should create instances of the `MGLPolyline` or + `MGLPolygon` classes. However, you can use the method and properties of this + class to access information about the specific points associated with the line + or polygon. */ @interface MGLMultiPoint : MGLShape /** - Creates and returns an `MGLMultiPoint` object from the specified set of - coordinates. - - @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. - */ -+ (instancetype)multiPointWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count NS_SWIFT_NAME(multiPoint(coordinates:count:)); - -/** The array of coordinates associated with the shape. This C array is a pointer to a structure inside the multipoint object, diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm index 0090c5e35f..17a61ed081 100644 --- a/platform/darwin/src/MGLMultiPoint.mm +++ b/platform/darwin/src/MGLMultiPoint.mm @@ -18,11 +18,6 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) MGLCoordinateBounds _bounds; } -+ (instancetype)multiPointWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count -{ - return [[self alloc] initWithCoordinates:coords count:count]; -} - - (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count { self = [super init]; @@ -146,29 +141,6 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) return mbgl::SymbolAnnotation({mbgl::Point<double>()}); } -- (mbgl::Feature)featureObject -{ - mbgl::MultiPoint<double> multiPoint; - multiPoint.reserve(self.pointCount); - for (NSInteger i = 0; i< self.pointCount; i++) - { - multiPoint.push_back(mbgl::Point<double>(self.coordinates[i].longitude, self.coordinates[i].latitude)); - } - return mbgl::Feature {multiPoint}; -} - -- (NSDictionary *)geoJSONDictionary -{ - NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.pointCount]; - for (NSUInteger index = 0; index < self.pointCount; index++) { - CLLocationCoordinate2D coordinate = self.coordinates[index]; - [coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]]; - } - - return @{@"type": @"MultiPoint", - @"coordinates": coordinates}; -} - - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; count = %lu; bounds = %@>", diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h index 211135f84f..b3fb7a2d54 100644 --- a/platform/darwin/src/MGLOfflineStorage.h +++ b/platform/darwin/src/MGLOfflineStorage.h @@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN alternatively observe KVO change notifications to the pack’s `progress` key path. */ -extern NSString * const MGLOfflinePackProgressChangedNotification; +extern const NSNotificationName MGLOfflinePackProgressChangedNotification; /** Posted by the shared `MGLOfflineStorage` object whenever an `MGLOfflinePack` @@ -37,7 +37,7 @@ extern NSString * const MGLOfflinePackProgressChangedNotification; `userInfo` dictionary contains the error object in the `MGLOfflinePackErrorUserInfoKey` key. */ -extern NSString * const MGLOfflinePackErrorNotification; +extern const NSNotificationName MGLOfflinePackErrorNotification; /** Posted by the shared `MGLOfflineStorage` object when the maximum number of @@ -52,7 +52,12 @@ extern NSString * const MGLOfflinePackErrorNotification; calling the `-[MGLOfflineStorage removePack:withCompletionHandler:]` method. Contact your Mapbox sales representative to have the limit raised. */ -extern NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification; +extern const NSNotificationName MGLOfflinePackMaximumMapboxTilesReachedNotification; + +/** + A key in the `userInfo` property of a notification posted by `MGLOfflinePack`. + */ +typedef NSString *MGLOfflinePackUserInfoKey NS_EXTENSIBLE_STRING_ENUM; /** The key for an `NSNumber` object that indicates an offline pack’s current @@ -60,7 +65,9 @@ extern NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification; `MGLOfflinePackProgressChangedNotification` notification. Call `-integerValue` on the object to receive the `MGLOfflinePackState`-typed state. */ -extern NSString * const MGLOfflinePackStateUserInfoKey; +extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState; + +extern NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyState"))); /** The key for an `NSValue` object that indicates an offline pack’s current @@ -69,7 +76,9 @@ extern NSString * const MGLOfflinePackStateUserInfoKey; `-MGLOfflinePackProgressValue` on the object to receive the `MGLOfflinePackProgress`-typed progress. */ -extern NSString * const MGLOfflinePackProgressUserInfoKey; +extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress; + +extern NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyProgress"))); /** The key for an `NSError` object that is encountered in the course of @@ -77,7 +86,9 @@ extern NSString * const MGLOfflinePackProgressUserInfoKey; an `MGLOfflinePackErrorNotification` notification. The error’s domain is `MGLErrorDomain`. See `MGLErrorCode` for possible error codes. */ -extern NSString * const MGLOfflinePackErrorUserInfoKey; +extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError; + +extern NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyError"))); /** The key for an `NSNumber` object that indicates the maximum number of @@ -87,7 +98,9 @@ extern NSString * const MGLOfflinePackErrorUserInfoKey; `-unsignedLongLongValue` on the object to receive the `uint64_t`-typed tile limit. */ -extern NSString * const MGLOfflinePackMaximumCountUserInfoKey; +extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount; + +extern NSString * const MGLOfflinePackMaximumCountUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyMaximumCount"))); /** A block to be called once an offline pack has been completely created and diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 5f284b76a1..10acc58b25 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -13,14 +13,18 @@ static NSString * const MGLOfflineStorageFileName = @"cache.db"; static NSString * const MGLOfflineStorageFileName3_2_0_beta_1 = @"offline.db"; -NSString * const MGLOfflinePackProgressChangedNotification = @"MGLOfflinePackProgressChanged"; -NSString * const MGLOfflinePackErrorNotification = @"MGLOfflinePackError"; -NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification = @"MGLOfflinePackMaximumMapboxTilesReached"; - -NSString * const MGLOfflinePackStateUserInfoKey = @"State"; -NSString * const MGLOfflinePackProgressUserInfoKey = @"Progress"; -NSString * const MGLOfflinePackErrorUserInfoKey = @"Error"; -NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; +const NSNotificationName MGLOfflinePackProgressChangedNotification = @"MGLOfflinePackProgressChanged"; +const NSNotificationName MGLOfflinePackErrorNotification = @"MGLOfflinePackError"; +const NSNotificationName MGLOfflinePackMaximumMapboxTilesReachedNotification = @"MGLOfflinePackMaximumMapboxTilesReached"; + +const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState = @"State"; +NSString * const MGLOfflinePackStateUserInfoKey = MGLOfflinePackUserInfoKeyState; +const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress = @"Progress"; +NSString * const MGLOfflinePackProgressUserInfoKey = MGLOfflinePackUserInfoKeyProgress; +const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError = @"Error"; +NSString * const MGLOfflinePackErrorUserInfoKey = MGLOfflinePackUserInfoKeyError; +const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount = @"MaximumCount"; +NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoKeyMaximumCount; @interface MGLOfflineStorage () <MGLOfflinePackDelegate> @@ -317,20 +321,20 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; - (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(__unused MGLOfflinePackProgress)progress { [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackProgressChangedNotification object:pack userInfo:@{ - MGLOfflinePackStateUserInfoKey: @(pack.state), - MGLOfflinePackProgressUserInfoKey: [NSValue valueWithMGLOfflinePackProgress:progress], + MGLOfflinePackUserInfoKeyState: @(pack.state), + MGLOfflinePackUserInfoKeyProgress: [NSValue valueWithMGLOfflinePackProgress:progress], }]; } - (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error { [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackErrorNotification object:pack userInfo:@{ - MGLOfflinePackErrorUserInfoKey: error, + MGLOfflinePackUserInfoKeyError: error, }]; } - (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount { [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackMaximumMapboxTilesReachedNotification object:pack userInfo:@{ - MGLOfflinePackMaximumCountUserInfoKey: @(maximumCount), + MGLOfflinePackUserInfoKeyMaximumCount: @(maximumCount), }]; } diff --git a/platform/darwin/src/MGLPointCollection.h b/platform/darwin/src/MGLPointCollection.h new file mode 100644 index 0000000000..db497d0a52 --- /dev/null +++ b/platform/darwin/src/MGLPointCollection.h @@ -0,0 +1,51 @@ +#import <Foundation/Foundation.h> +#import <CoreLocation/CoreLocation.h> + +#import "MGLOverlay.h" +#import "MGLShape.h" + +/** + The `MGLPointCollection` class is used to define an array of disconnected + coordinates. The points in the collection may be related but are not + connected visually in any way. + + @note `MGLPointCollection` objects cannot be added to a map view using + `-[MGLMapView addAnnotations:]` and related methods. However, when used in a + `MGLPointCollectionFeature` to initialize a `MGLGeoJSONSource` that is added + to the map view's style, the point collection represents as a group of distinct + annotations. + */ +@interface MGLPointCollection : MGLShape <MGLOverlay> + +/** + Creates and returns a `MGLPointCollection` object from the specified set of + coordinates. + + @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 point collection object. + */ ++ (instancetype)pointCollectionWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; + +/** The array of coordinates associated with the shape. */ +@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates NS_RETURNS_INNER_POINTER; + +/** The number of coordinates associated with the shape. */ +@property (nonatomic, readonly) NSUInteger pointCount; + +/** + Retrieves one or more coordinates associated with the shape. + + @param coords On input, you must provide a C array of structures large enough + to hold the desired number of coordinates. On output, this structure + contains the requested coordinate data. + @param range The range of points you want. The `location` field indicates the + first point you are requesting, with `0` being the first point, `1` being + the second point, and so on. The `length` field indicates the number of + points you want. The array in _`coords`_ must be large enough to accommodate + the number of requested coordinates. + */ +- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range; + +@end diff --git a/platform/darwin/src/MGLPointCollection.mm b/platform/darwin/src/MGLPointCollection.mm new file mode 100644 index 0000000000..5871915b5d --- /dev/null +++ b/platform/darwin/src/MGLPointCollection.mm @@ -0,0 +1,112 @@ +#import "MGLPointCollection_Private.h" +#import "MGLGeometry_Private.h" + +#import <mbgl/util/geometry.hpp> +#import <mbgl/util/feature.hpp> + +NS_ASSUME_NONNULL_BEGIN + +@implementation MGLPointCollection +{ + size_t _count; + MGLCoordinateBounds _bounds; +} + ++ (instancetype)pointCollectionWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count +{ + return [[self alloc] initWithCoordinates:coords count:count]; +} + +- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count +{ + self = [super init]; + if (self) + { + _count = count; + _coordinates = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D)); + + mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); + + for (NSUInteger i = 0; i < count; i++) + { + _coordinates[i] = coords[i]; + bounds.extend(mbgl::LatLng(coords[i].latitude, coords[i].longitude)); + } + + _bounds = MGLCoordinateBoundsFromLatLngBounds(bounds); + } + return self; +} + +- (NSUInteger)pointCount +{ + return _count; +} + +- (CLLocationCoordinate2D)coordinate +{ + assert(_count > 0); + + return CLLocationCoordinate2DMake(_coordinates[0].latitude, _coordinates[0].longitude); +} + +- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range +{ + if (range.location + range.length > _count) + { + [NSException raise:NSRangeException + format:@"Invalid coordinate range %@ extends beyond current coordinate count of %zu", + NSStringFromRange(range), _count]; + } + + NSUInteger index = 0; + + for (NSUInteger i = range.location; i < range.location + range.length; i++) + { + coords[index] = _coordinates[i]; + index++; + } +} + +- (MGLCoordinateBounds)overlayBounds +{ + return _bounds; +} + +- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds +{ + return MGLLatLngBoundsFromCoordinateBounds(_bounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds)); +} + +- (mbgl::Feature)featureObject +{ + mbgl::MultiPoint<double> multiPoint; + multiPoint.reserve(self.pointCount); + for (NSInteger i = 0; i< self.pointCount; i++) + { + multiPoint.push_back(mbgl::Point<double>(self.coordinates[i].longitude, self.coordinates[i].latitude)); + } + return mbgl::Feature {multiPoint}; +} + +- (NSDictionary *)geoJSONDictionary +{ + NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.pointCount]; + for (NSUInteger index = 0; index < self.pointCount; index++) { + CLLocationCoordinate2D coordinate = self.coordinates[index]; + [coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]]; + } + + return @{@"type": @"MultiPoint", + @"coordinates": coordinates}; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p; count = %lu>", + NSStringFromClass([self class]), (void *)self, (unsigned long)_count]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLPointCollection_Private.h b/platform/darwin/src/MGLPointCollection_Private.h new file mode 100644 index 0000000000..039c1f18be --- /dev/null +++ b/platform/darwin/src/MGLPointCollection_Private.h @@ -0,0 +1,11 @@ +#import "MGLPointCollection.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MGLPointCollection (Private) + +- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLPolygon.h b/platform/darwin/src/MGLPolygon.h index 6d53356ba4..3d5b36abb6 100644 --- a/platform/darwin/src/MGLPolygon.h +++ b/platform/darwin/src/MGLPolygon.h @@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN @param count The number of items in the `coords` array. @return A new polygon object. */ -+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count NS_SWIFT_NAME(polygon(coordinates:count:)); ++ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; /** Creates and returns an `MGLPolygon` object from the specified set of diff --git a/platform/darwin/src/MGLPolyline.h b/platform/darwin/src/MGLPolyline.h index 6642afef7e..d0274b44e3 100644 --- a/platform/darwin/src/MGLPolyline.h +++ b/platform/darwin/src/MGLPolyline.h @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @param count The number of items in the `coords` array. @return A new polyline object. */ -+ (instancetype)polylineWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count NS_SWIFT_NAME(polyline(coordinates:count:)); ++ (instancetype)polylineWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; @end diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm index 41b9a5b043..fc47c23853 100644 --- a/platform/darwin/src/MGLRasterSource.mm +++ b/platform/darwin/src/MGLRasterSource.mm @@ -1,18 +1,29 @@ #import "MGLRasterSource.h" +#import "MGLMapView_Private.h" #import "MGLSource_Private.h" #import "MGLTileSet_Private.h" #import "NSURL+MGLAdditions.h" #include <mbgl/style/sources/raster_source.hpp> +@interface MGLRasterSource () + +@property (nonatomic) mbgl::style::RasterSource *rawSource; + +@end + @implementation MGLRasterSource +{ + std::unique_ptr<mbgl::style::RasterSource> _pendingSource; +} - (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url tileSize:(CGFloat)tileSize { if (self = [super initWithIdentifier:identifier]) { _URL = url; _tileSize = tileSize; + [self commonInit]; } return self; } @@ -23,11 +34,12 @@ { _tileSet = tileSet; _tileSize = tileSize; + [self commonInit]; } return self; } -- (std::unique_ptr<mbgl::style::Source>)mbglSource +- (void)commonInit { std::unique_ptr<mbgl::style::RasterSource> source; @@ -42,10 +54,15 @@ source = std::make_unique<mbgl::style::RasterSource>(self.identifier.UTF8String, self.tileSet.mbglTileset, uint16_t(self.tileSize)); - } - return std::move(source); + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); +} + +- (void)addToMapView:(MGLMapView *)mapView +{ + mapView.mbglMap->addSource(std::move(_pendingSource)); } @end diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm index 85bbc06342..1b889d44d7 100644 --- a/platform/darwin/src/MGLSource.mm +++ b/platform/darwin/src/MGLSource.mm @@ -2,27 +2,14 @@ #include <mbgl/style/source.hpp> -@interface MGLSource () - -@property (nonatomic) mbgl::style::Source *source; - -@end - @implementation MGLSource -- (instancetype)initWithIdentifier:(NSString *)identifier { +- (instancetype)initWithIdentifier:(NSString *)identifier +{ if (self = [super init]) { _identifier = identifier; } return self; } -- (std::unique_ptr<mbgl::style::Source>)mbglSource { - [NSException raise:@"MGLAbstractClassException" format: - @"The source %@ cannot be added to the style. " - @"Make sure the source was created as a member of a concrete subclass of MGLSource.", - NSStringFromClass(self)]; - return nil; -} - @end diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h index 2b8658b4cb..dff230ede5 100644 --- a/platform/darwin/src/MGLSource_Private.h +++ b/platform/darwin/src/MGLSource_Private.h @@ -3,10 +3,29 @@ #include <mbgl/mbgl.hpp> #include <mbgl/style/source.hpp> +@class MGLMapView; + @interface MGLSource (Private) -- (std::unique_ptr<mbgl::style::Source>)mbglSource; +/** + A raw pointer to the mbgl object, which is always initialized, either to the + value returned by `mbgl::Map getSource`, or for independently created objects, + to the pointer value held in `pendingSource`. In the latter case, this raw + pointer value stays even after ownership of the object is transferred via + `mbgl::Map addSource`. + */ +@property (nonatomic) mbgl::style::Source *rawSource; -@property (nonatomic) mbgl::style::Source *source; +/** + Adds the mbgl source that this object represents to the mbgl map. + + Once a mbgl source is added, ownership of the object is transferred to the + `mbgl::Map` and this object no longer has an active unique_ptr reference to the + `mbgl::Source`. If this object's mbgl source is in that state, the mbgl source + can still be changed but the changes will not be visible until the `MGLSource` + is added back to the map via `-[MGLStyle addSource:]` and styled with a + `MGLLayer`. + */ +- (void)addToMapView:(MGLMapView *)mapView; @end diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 3964b47ad6..a17b7d6b74 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -142,6 +142,7 @@ static NSURL *MGLStyleURL_emerald; - (MGLSource *)sourceWithIdentifier:(NSString *)identifier { auto mbglSource = self.mapView.mbglMap->getSource(identifier.UTF8String); + if (!mbglSource) { return nil; } @@ -159,8 +160,8 @@ static NSURL *MGLStyleURL_emerald; NSAssert(NO, @"Unrecognized source type"); return nil; } - - source.source = mbglSource; + + source.rawSource = mbglSource; return source; } @@ -205,12 +206,17 @@ static NSURL *MGLStyleURL_emerald; - (void)addSource:(MGLSource *)source { - self.mapView.mbglMap->addSource(source.mbglSource); + [source addToMapView:self.mapView]; } - (void)removeSource:(MGLSource *)source { self.mapView.mbglMap->removeSource(source.identifier.UTF8String); + + // Once a mbgl source is removed from the map, ownership does not return + // to the MGL source. Therefore, the rawSource pointer is set to NULL + // so that the implementation of MGL source can avoid using it again. + source.rawSource = NULL; } - (NS_ARRAY_OF(NSString *) *)styleClasses diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h index eb0eaf5340..ab5e76bbe3 100644 --- a/platform/darwin/src/MGLStyleValue.h +++ b/platform/darwin/src/MGLStyleValue.h @@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN The `MGLStyleConstantValue` class takes a generic parameter `T` that indicates the Foundation class being wrapped by this class. */ -@interface MGLStyleConstantValue<T> : MGLStyleValue +@interface MGLStyleConstantValue<T> : MGLStyleValue<T> #pragma mark Creating a Style Constant Value @@ -111,7 +111,7 @@ NS_ASSUME_NONNULL_BEGIN The `MGLStyleFunction` class takes a generic parameter `T` that indicates the Foundation class being wrapped by this class. */ -@interface MGLStyleFunction<T> : MGLStyleValue +@interface MGLStyleFunction<T> : MGLStyleValue<T> #pragma mark Creating a Style Function diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index 3fcecedca3..9bd943a34e 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -388,7 +388,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Value to use for a text label. Feature properties are specified using tokens like {field_name}. - The default value of this property is an `MGLStyleValue` object containing the string ``. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing the empty string. Set this property to `nil` to reset it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue<NSString *> *textField; diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h index a3ea587add..e9e05bc684 100644 --- a/platform/darwin/src/MGLTypes.h +++ b/platform/darwin/src/MGLTypes.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN /** Indicates an error occurred in the Mapbox SDK. */ -extern NSString * const MGLErrorDomain; +extern NSErrorDomain const MGLErrorDomain; /** Error constants for the Mapbox SDK. */ typedef NS_ENUM(NSInteger, MGLErrorCode) { @@ -97,3 +97,9 @@ NS_ASSUME_NONNULL_END #define NS_MUTABLE_DICTIONARY_OF(ObjectClass...) NSMutableDictionary #endif #endif + +#if !defined(FOUNDATION_SWIFT_SDK_EPOCH_LESS_THAN) || FOUNDATION_SWIFT_SDK_EPOCH_LESS_THAN(8) + #define NS_STRING_ENUM + #define NS_EXTENSIBLE_STRING_ENUM + #define NSNotificationName NSString * +#endif diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index 3597812359..995565419f 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -1,12 +1,22 @@ #import "MGLVectorSource.h" +#import "MGLMapView_Private.h" #import "MGLSource_Private.h" #import "MGLTileSet_Private.h" #import "NSURL+MGLAdditions.h" #include <mbgl/style/sources/vector_source.hpp> +@interface MGLVectorSource () + +@property (nonatomic) mbgl::style::VectorSource *rawSource; + +@end + @implementation MGLVectorSource +{ + std::unique_ptr<mbgl::style::VectorSource> _pendingSource; +} static NSString *MGLVectorSourceType = @"vector"; @@ -15,6 +25,7 @@ static NSString *MGLVectorSourceType = @"vector"; if (self = [super initWithIdentifier:identifier]) { _URL = url; + [self commonInit]; } return self; } @@ -24,11 +35,12 @@ static NSString *MGLVectorSourceType = @"vector"; if (self = [super initWithIdentifier:identifier]) { _tileSet = tileSet; + [self commonInit]; } return self; } -- (std::unique_ptr<mbgl::style::Source>)mbglSource +- (void)commonInit { std::unique_ptr<mbgl::style::VectorSource> source; @@ -43,7 +55,13 @@ static NSString *MGLVectorSourceType = @"vector"; self.tileSet.mbglTileset); } - return std::move(source); + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); +} + +- (void)addToMapView:(MGLMapView *)mapView +{ + mapView.mbglMap->addSource(std::move(_pendingSource)); } @end diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm index 18c3fd16c2..7f464aaab1 100644 --- a/platform/darwin/test/MGLFeatureTests.mm +++ b/platform/darwin/test/MGLFeatureTests.mm @@ -227,24 +227,6 @@ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry); } -- (void)testMultiPointFeatureGeoJSONDictionary { - CLLocationCoordinate2D coord1 = { 0, 0 }; - CLLocationCoordinate2D coord2 = { 10, 10 }; - CLLocationCoordinate2D coord3 = { 0, 0 }; - CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 }; - MGLMultiPointFeature *multiPointFeature = [MGLMultiPointFeature multiPointWithCoordinates:coords count:3]; - - // A GeoJSON feature - NSDictionary *geoJSONFeature = [multiPointFeature geoJSONDictionary]; - - // it has the correct geometry - NSDictionary *expectedGeometry = @{@"type": @"MultiPoint", - @"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)], - @[@(coord2.longitude), @(coord2.latitude)], - @[@(coord3.longitude), @(coord3.latitude)]]}; - XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry); -} - - (void)testMultiPolylineFeatureGeoJSONDictionary { CLLocationCoordinate2D coord1 = { 0, 0 }; CLLocationCoordinate2D coord2 = { 10, 10 }; @@ -296,6 +278,25 @@ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry); } +- (void)testPointCollectionFeatureGeoJSONDictionary { + CLLocationCoordinate2D coord1 = { 0, 0 }; + CLLocationCoordinate2D coord2 = { 10, 10 }; + CLLocationCoordinate2D coord3 = { 0, 0 }; + CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 }; + MGLPointCollectionFeature *pointCollectionFeature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coords count:3]; + + // A GeoJSON feature + NSDictionary *geoJSONFeature = [pointCollectionFeature geoJSONDictionary]; + + // it has the correct geometry + NSDictionary *expectedGeometry = @{@"type": @"MultiPoint", + @"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)], + @[@(coord2.longitude), @(coord2.latitude)], + @[@(coord3.longitude), @(coord3.latitude)]]}; + XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry); + +} + - (void)testShapeCollectionFeatureGeoJSONDictionary { MGLPointAnnotation *pointFeature = [[MGLPointAnnotation alloc] init]; CLLocationCoordinate2D pointCoordinate = { 10, 10 }; diff --git a/platform/ios/test/MGLGeoJSONSourceTests.mm b/platform/darwin/test/MGLGeoJSONSourceTests.mm index 40d8067985..be8bb143ce 100644 --- a/platform/ios/test/MGLGeoJSONSourceTests.mm +++ b/platform/darwin/test/MGLGeoJSONSourceTests.mm @@ -10,23 +10,17 @@ @interface MGLGeoJSONSourceTests : XCTestCase @end -@interface MGLPolygonFeature (Test) - -@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes; - -@end - @implementation MGLGeoJSONSourceTests - (void)testMGLGeoJSONSourceWithOptions { NSURL *url = [NSURL URLWithString:@"http://www.mapbox.com/source"]; - NSDictionary *options = @{MGLGeoJSONClusterOption: @(YES), - MGLGeoJSONClusterRadiusOption: @42, - MGLGeoJSONClusterMaximumZoomLevelOption: @98, - MGLGeoJSONMaximumZoomLevelOption: @99, - MGLGeoJSONBufferOption: @1976, - MGLGeoJSONToleranceOption: @0.42}; + NSDictionary *options = @{MGLGeoJSONSourceOptionClustered: @YES, + MGLGeoJSONSourceOptionClusterRadius: @42, + MGLGeoJSONSourceOptionMaximumZoomLevelForClustering: @98, + MGLGeoJSONSourceOptionMaximumZoomLevel: @99, + MGLGeoJSONSourceOptionBuffer: @1976, + MGLGeoJSONSourceOptionSimplificationTolerance: @0.42}; MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" URL:url options:options]; auto mbglOptions = [source geoJSONOptions]; @@ -37,9 +31,8 @@ XCTAssertEqual(mbglOptions.buffer, 1976); XCTAssertEqual(mbglOptions.tolerance, 0.42); - options = @{MGLGeoJSONClusterOption: @"number 1"}; - source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" URL:url options:options]; - XCTAssertThrows([source geoJSONOptions]); + options = @{MGLGeoJSONSourceOptionClustered: @"number 1"}; + XCTAssertThrows([[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" URL:url options:options]); } - (void)testMGLGeoJSONSourceWithData { @@ -49,8 +42,6 @@ NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" geoJSONData:data options:nil]; - [source mbglSource]; - XCTAssertNotNil(source.features); XCTAssertEqual(source.features.count, 1); XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolylineFeature class]]); @@ -62,8 +53,6 @@ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[polylineFeature] options:nil]; - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; - XCTAssertNotNil(source.features); XCTAssertEqual(source.features.count, 1); XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolylineFeature class]]); @@ -101,8 +90,6 @@ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[polygonFeature] options:nil]; - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; - XCTAssertNotNil(source.features); XCTAssertEqual(source.features.count, 1); MGLPolygonFeature *expectedPolygonFeature = (MGLPolygonFeature *)source.features.firstObject; @@ -137,56 +124,7 @@ MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]]; MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[polygonFeature] options:nil]; - - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; - - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolygonFeature class]]); -} - - -- (void)testMGLGeoJSONSourceWithMultiPointFeaturesUsingPolylines { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(100.0, 0.0), - CLLocationCoordinate2DMake(101.0, 0.0), - CLLocationCoordinate2DMake(101.0, 1.0), - CLLocationCoordinate2DMake(100.0, 1.0), - CLLocationCoordinate2DMake(100.0, 0.0)}; - - MGLMultiPointFeature *multiPointFeature = [MGLMultiPointFeature multiPointWithCoordinates:coordinates count:5]; - - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[multiPointFeature] options:nil]; - - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; - - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLMultiPointFeature class]]); -} - -- (void)testMGLGeoJSONSourceWithMultiPointFeaturesUsingPolygons { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(100.0, 0.0), - CLLocationCoordinate2DMake(101.0, 0.0), - CLLocationCoordinate2DMake(101.0, 1.0), - CLLocationCoordinate2DMake(100.0, 1.0), - CLLocationCoordinate2DMake(100.0, 0.0)}; - - CLLocationCoordinate2D interiorCoordinates[] = { - CLLocationCoordinate2DMake(100.2, 0.2), - CLLocationCoordinate2DMake(100.8, 0.2), - CLLocationCoordinate2DMake(100.8, 0.8), - CLLocationCoordinate2DMake(100.2, 0.8), - CLLocationCoordinate2DMake(100.2, 0.2)}; - - MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5]; - - MGLMultiPointFeature *multiPointFeature = (MGLMultiPointFeature *)[MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]]; - - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[multiPointFeature] options:nil]; - - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; + XCTAssertNotNil(source.features); XCTAssertEqual(source.features.count, 1); @@ -202,8 +140,6 @@ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[multiPolylineFeature] options:nil]; - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; - XCTAssertNotNil(source.features); XCTAssertEqual(source.features.count, 1); XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLMultiPolylineFeature class]]); @@ -233,8 +169,6 @@ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[multiPolygonFeature] options:nil]; - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; - XCTAssertNotNil(source.features); XCTAssertEqual(source.features.count, 1); XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLMultiPolygonFeature class]]); @@ -247,13 +181,26 @@ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"souce-id" features:@[pointFeature] options:nil]; - std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource]; - XCTAssertNotNil(source.features); XCTAssertEqual(source.features.count, 1); XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPointFeature class]]); } +- (void)testMGLGeoJSONSourceWithPointCollectionFeature { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(100.0, 0.0), + CLLocationCoordinate2DMake(101.0, 0.0), + CLLocationCoordinate2DMake(101.0, 1.0), + CLLocationCoordinate2DMake(100.0, 1.0), + CLLocationCoordinate2DMake(100.0, 0.0)}; + MGLPointCollectionFeature *pointCollectionFeature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:5]; + MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"souce-id" features:@[pointCollectionFeature] options:nil]; + + XCTAssertNotNil(source.features); + XCTAssertEqual(source.features.count, 1); + XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPointCollectionFeature class]]); +} + - (void)testMGLGeoJSONSourceWithShapeCollectionFeatures { CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(100.0, 0.0), @@ -280,18 +227,16 @@ MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[polylineFeature, polylineFeature]]; - MGLMultiPointFeature *multiPointFeature = (MGLMultiPointFeature *)[MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]]; + MGLPointCollectionFeature *pointCollectionFeature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:5]; MGLPointFeature *pointFeature = [MGLPointFeature new]; pointFeature.coordinate = CLLocationCoordinate2DMake(100.2, 0.2); - MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, multiPointFeature, pointFeature]]; + MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, pointCollectionFeature, pointFeature]]; - MGLShapeCollectionFeature *shapeCollectionFeature_1 = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, multiPointFeature, pointFeature, shapeCollectionFeature]]; + MGLShapeCollectionFeature *shapeCollectionFeature_1 = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, pointCollectionFeature, pointFeature, shapeCollectionFeature]]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[shapeCollectionFeature_1] options:nil]; - - XCTAssertThrowsSpecificNamed([source mbglSource], NSException, @"Method unavailable"); + XCTAssertThrowsSpecificNamed([[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[shapeCollectionFeature_1] options:nil], NSException, @"Method unavailable"); } @end diff --git a/platform/darwin/test/MGLOfflineStorageTests.m b/platform/darwin/test/MGLOfflineStorageTests.m index 8400cb43cb..cd13a9262e 100644 --- a/platform/darwin/test/MGLOfflineStorageTests.m +++ b/platform/darwin/test/MGLOfflineStorageTests.m @@ -90,11 +90,11 @@ NSDictionary *userInfo = notification.userInfo; XCTAssertNotNil(userInfo, @"Progress change notification should have a userInfo dictionary."); - NSNumber *stateNumber = userInfo[MGLOfflinePackStateUserInfoKey]; + NSNumber *stateNumber = userInfo[MGLOfflinePackUserInfoKeyState]; XCTAssert([stateNumber isKindOfClass:[NSNumber class]], @"Progress change notification’s state should be an NSNumber."); XCTAssertEqual(stateNumber.integerValue, pack.state, @"State in a progress change notification should match the pack’s state."); - NSValue *progressValue = userInfo[MGLOfflinePackProgressUserInfoKey]; + NSValue *progressValue = userInfo[MGLOfflinePackUserInfoKeyProgress]; XCTAssert([progressValue isKindOfClass:[NSValue class]], @"Progress change notification’s progress should be an NSValue."); XCTAssertEqualObjects(progressValue, [NSValue valueWithMGLOfflinePackProgress:pack.progress], @"Progress change notification’s progress should match pack’s progress."); diff --git a/platform/darwin/test/MGLStyleLayerTests.m b/platform/darwin/test/MGLStyleLayerTests.m index b16bcfed56..74c6b2f906 100644 --- a/platform/darwin/test/MGLStyleLayerTests.m +++ b/platform/darwin/test/MGLStyleLayerTests.m @@ -13,6 +13,7 @@ [vc.view addSubview:_mapView]; _mapView.delegate = self; #else + [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:@"MGLStyleLayerTests" owner:self]; [windowController showWindow:nil]; #endif diff --git a/platform/darwin/test/MGLStyleValueTests.swift b/platform/darwin/test/MGLStyleValueTests.swift new file mode 100644 index 0000000000..f7bf343852 --- /dev/null +++ b/platform/darwin/test/MGLStyleValueTests.swift @@ -0,0 +1,36 @@ +import XCTest +import Mapbox + +class MGLStyleValueTests: XCTestCase { + func testConstantValues() { + let geoJSONSource = MGLGeoJSONSource(identifier: "test", features: [], options: nil) + let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: geoJSONSource) + + // Boolean + symbolStyleLayer.iconAllowOverlap = MGLStyleConstantValue(rawValue: true) + XCTAssertEqual((symbolStyleLayer.iconAllowOverlap as! MGLStyleConstantValue<NSNumber>).rawValue, true) + + // Number + symbolStyleLayer.iconHaloWidth = MGLStyleConstantValue(rawValue: 3) + XCTAssertEqual((symbolStyleLayer.iconHaloWidth as! MGLStyleConstantValue<NSNumber>).rawValue, 3) + + // String + symbolStyleLayer.textField = MGLStyleConstantValue(rawValue: "{name}") + XCTAssertEqual((symbolStyleLayer.textField as! MGLStyleConstantValue<NSString>).rawValue, "{name}") + } + + func testFunctions() { + let geoJSONSource = MGLGeoJSONSource(identifier: "test", features: [], options: nil) + let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: geoJSONSource) + + // Boolean + let stops: [NSNumber: MGLStyleValue<NSNumber>] = [ + 1: MGLStyleValue(rawValue: true), + 2: MGLStyleValue(rawValue: false), + 3: MGLStyleValue(rawValue: true), + 4: MGLStyleValue(rawValue: false), + ] + symbolStyleLayer.iconAllowOverlap = MGLStyleFunction<NSNumber>(base: 1, stops: stops) + XCTAssertEqual((symbolStyleLayer.iconAllowOverlap as! MGLStyleFunction<NSNumber>), MGLStyleFunction(base: 1, stops: stops)) + } +} diff --git a/platform/ios/test/MGLTileSetTests.mm b/platform/darwin/test/MGLTileSetTests.mm index d77046928c..d77046928c 100644 --- a/platform/ios/test/MGLTileSetTests.mm +++ b/platform/darwin/test/MGLTileSetTests.mm diff --git a/platform/darwin/test/test-Bridging-Header.h b/platform/darwin/test/test-Bridging-Header.h new file mode 100644 index 0000000000..e11d920b12 --- /dev/null +++ b/platform/darwin/test/test-Bridging-Header.h @@ -0,0 +1,3 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index b064c7181b..494adbda64 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -7,9 +7,10 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ### Packaging * Xcode 7.3 or above is required for using this SDK. ([#6059](https://github.com/mapbox/mapbox-gl-native/issues/6059)) -* Fixed an issue with symbols not being properly stripped from the dynamic framework. The dSYM file included with the standard dynamic framework in previous releases (e.g., `mapbox-ios-sdk-3.3.4-dynamic.zip` or the `Mapbox-iOS-SDK` pod) could not be used to symbolicate crashes. ([#6531](https://github.com/mapbox/mapbox-gl-native/pull/6531)) +* Fixed an issue with symbols not being properly stripped from the dynamic framework. The dSYM file included with the standard dynamic framework in previous releases (e.g., `mapbox-ios-sdk-3.3.5-dynamic.zip` or the `Mapbox-iOS-SDK` pod) could not be used to symbolicate crashes. ([#6531](https://github.com/mapbox/mapbox-gl-native/pull/6531)) * Simulator architecture slices are included in the included dSYM file, allowing you to symbolicate crashes that occur in the Simulator. ([#5740](https://github.com/mapbox/mapbox-gl-native/pull/5740)) * Clarified that the `-ObjC` linker flag is required for linking against the static framework distribution of this SDK. ([#6213](https://github.com/mapbox/mapbox-gl-native/pull/6213)) +* Added documentation for the Info.plist keys used by this SDK. ([#6833](https://github.com/mapbox/mapbox-gl-native/pull/6833)) ### Styles and data @@ -18,8 +19,11 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * GeoJSON sources specified by the stylesheet at design time now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) * Added [quadkey](https://msdn.microsoft.com/en-us/library/bb259689.aspx) support and limited WMS support in raster tile URL templates. ([#5628](https://github.com/mapbox/mapbox-gl-native/pull/5628)) * TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) +* Fixed an issue causing abstract MGLMultiPointFeature objects to be returned in feature query results. Now concrete MGLPointCollectionFeature objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) * Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908)) * `-[MGLMapView resetPosition]` now resets to the current style’s default center coordinates, zoom level, direction, and pitch, if specified. ([#6127](https://github.com/mapbox/mapbox-gl-native/pull/6127)) +* Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773)) +* MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728)) * The `text-pitch-alignment` property is now supported in stylesheets for improved street label legibility on a tilted map. ([#5288](https://github.com/mapbox/mapbox-gl-native/pull/5288)) * The `icon-text-fit` and `icon-text-fit-padding` properties are now supported in stylesheets, allowing the background of a shield to automatically resize to fit the shield’s text. ([#5334](https://github.com/mapbox/mapbox-gl-native/pull/5334)) * The `circle-pitch-scale` property is now supported in stylesheets, allowing circle features in a tilted base map to scale or remain the same size as the viewing distance changes. ([#5576](https://github.com/mapbox/mapbox-gl-native/pull/5576)) @@ -31,6 +35,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * A source’s tiles are no longer rendered when the map is outside the source’s supported zoom levels. ([#6345](https://github.com/mapbox/mapbox-gl-native/pull/6345)) * Improved style parsing performance. ([#6170](https://github.com/mapbox/mapbox-gl-native/pull/6170)) * Improved feature querying performance. ([#6514](https://github.com/mapbox/mapbox-gl-native/pull/6514)) +* Fixed an issue where shapes that cannot currently be visually represented as annotations were still shown on the map as point annotations. ([#6764](https://github.com/mapbox/mapbox-gl-native/issues/6764)) ### User location @@ -43,16 +48,18 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ### Annotations * MGLPolyline annotations and the exterior coordinates of MGLPolygon annotations are now able to be mutated, part or all, and changes are displayed immediately. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) +* Added new APIs to MGLMapView to query for visible annotations. Combined with `-[MGLMapView viewForAnnotation:]`, these APIs can be used to access all visible annotation views. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061)) +* Fixed an issue causing offscreen annotation views to be updated even when they were in the reuse queue. ([#5987](https://github.com/mapbox/mapbox-gl-native/pull/5987)) * Fixed an issue preventing MGLAnnotationView from animating when its coordinate changes. ([#6215](https://github.com/mapbox/mapbox-gl-native/pull/6215)) * Fixed an issue causing the wrong annotation view to be selected when tapping an annotation view with a center offset applied. ([#5931](https://github.com/mapbox/mapbox-gl-native/pull/5931)) * Fixed an issue that assigned annotation views to polyline and polygon annotations. ([#5770](https://github.com/mapbox/mapbox-gl-native/pull/5770)) * Per documentation, the first and last coordinates in an MGLPolygon must be identical in order for the polygon to draw correctly. The same is true for an MGLPolygon’s interior polygon. ([#5514](https://github.com/mapbox/mapbox-gl-native/pull/5514)) * To make an MGLPolyline or MGLPolygon span the antimeridian, specify coordinates with longitudes greater than 180° or less than −180°. ([#6088](https://github.com/mapbox/mapbox-gl-native/pull/6088)) +* Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706)) +* Fixed an issue that caused an annotation view to disappear if it isn’t created using the annotation view reuse queue. ([#6485](https://github.com/mapbox/mapbox-gl-native/pull/6485)) +* Fixed an issue that could reset user-added transformations on annotation views. ([#6166](https://github.com/mapbox/mapbox-gl-native/pull/6166)) * Improved the performance of relocating a non-view-backed point annotation by changing its `coordinate` property. ([#5385](https://github.com/mapbox/mapbox-gl-native/pull/5385)) * Improved the precision of annotations at zoom levels greater than 18. ([#5517](https://github.com/mapbox/mapbox-gl-native/pull/5517)) -* Fixed an issue that could reset user-added transformations on annotation views. ([#6166](https://github.com/mapbox/mapbox-gl-native/pull/6166)) -* Fixed an issue that caused an annotation view to disappear if it isn’t created using the annotation view reuse queue. ([#6485](https://github.com/mapbox/mapbox-gl-native/pull/6485)) -* Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706)) ### Networking and offline maps @@ -69,6 +76,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ### Other changes * As the user zooms in, tiles from lower zoom levels are scaled up until tiles for higher zoom levels are loaded. ([#5143](https://github.com/mapbox/mapbox-gl-native/pull/5143)) +* Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794)) * MGLMapDebugOverdrawVisualizationMask no longer has any effect in Release builds of the SDK. This debug mask has been disabled for performance reasons. ([#5555](https://github.com/mapbox/mapbox-gl-native/pull/5555)) * Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879)) diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec index bbc0425088..e26de7915f 100644 --- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec +++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.4.0-beta.1-symbols' + m.version = '3.4.0-beta.2-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 77ada60fa4..6fd6d4b46f 100644 --- a/platform/ios/Mapbox-iOS-SDK.podspec +++ b/platform/ios/Mapbox-iOS-SDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.4.0-beta.1' + m.version = '3.4.0-beta.2' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' diff --git a/platform/ios/app/Info.plist b/platform/ios/app/Info.plist index 3602ab7964..043bebc926 100644 --- a/platform/ios/app/Info.plist +++ b/platform/ios/app/Info.plist @@ -51,5 +51,18 @@ <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> + <key>NSAppTransportSecurity</key> + <dict> + <key>NSExceptionDomains</key> + <dict> + <key>stamen.com</key> + <dict> + <key>NSIncludesSubdomains</key> + <true/> + <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> + <true/> + </dict> + </dict> + </dict> </dict> </plist> diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m index 008d843b1e..7bceec7ef7 100644 --- a/platform/ios/app/MBXOfflinePacksTableViewController.m +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -244,7 +244,7 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac MGLOfflinePack *pack = notification.object; NSAssert([pack isKindOfClass:[MGLOfflinePack class]], @"MGLOfflineStorage notification has a non-pack object."); - NSError *error = notification.userInfo[MGLOfflinePackErrorUserInfoKey]; + NSError *error = notification.userInfo[MGLOfflinePackUserInfoKeyError]; NSAssert([error isKindOfClass:[NSError class]], @"MGLOfflineStorage notification has a non-error error."); NSString *message = [NSString stringWithFormat:@"Mapbox GL encountered an error while downloading the offline pack “%@”: %@", pack.name, error.localizedFailureReason]; @@ -261,7 +261,7 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac MGLOfflinePack *pack = notification.object; NSAssert([pack isKindOfClass:[MGLOfflinePack class]], @"MGLOfflineStorage notification has a non-pack object."); - uint64_t maximumCount = [notification.userInfo[MGLOfflinePackMaximumCountUserInfoKey] unsignedLongLongValue]; + uint64_t maximumCount = [notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount] unsignedLongLongValue]; NSLog(@"Offline pack “%@” reached limit of %llu tiles.", pack.name, maximumCount); } diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 046f602384..a7ea429300 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -46,6 +46,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsAnnotationsRows) { MBXSettingsAnnotations10000Sprites, MBXSettingsAnnotationsTestShapes, MBXSettingsAnnotationsCustomCallout, + MBXSettingsAnnotationsQueryAnnotations, MBXSettingsAnnotationsRemoveAnnotations, }; @@ -62,10 +63,19 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) { MBXSettingsRuntimeStylingFilteredLines, MBXSettingsRuntimeStylingNumericFilteredFill, MBXSettingsRuntimeStylingStyleQuery, + MBXSettingsRuntimeStylingFeatureSource, + MBXSettingsRuntimeStylingPointCollection, + MBXSettingsRuntimeStylingUpdateGeoJSONSourceData, + MBXSettingsRuntimeStylingUpdateGeoJSONSourceURL, + MBXSettingsRuntimeStylingUpdateGeoJSONSourceFeatures, + MBXSettingsRuntimeStylingVectorSource, + MBXSettingsRuntimeStylingRasterSource, + MBXSettingsRuntimeStylingCountryLabels, }; typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { - MBXSettingsMiscellaneousWorldTour = 0, + MBXSettingsMiscellaneousShowReuseQueueStats = 0, + MBXSettingsMiscellaneousWorldTour, MBXSettingsMiscellaneousCustomUserDot, MBXSettingsMiscellaneousPrintLogFile, MBXSettingsMiscellaneousDeleteLogFile, @@ -93,10 +103,21 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { UITableViewDataSource, MGLMapViewDelegate> + @property (nonatomic) IBOutlet MGLMapView *mapView; +@property (weak, nonatomic) IBOutlet UILabel *hudLabel; @property (nonatomic) NSInteger styleIndex; @property (nonatomic) BOOL debugLoggingEnabled; @property (nonatomic) BOOL customUserLocationAnnnotationEnabled; +@property (nonatomic) BOOL usingLocaleBasedCountryLabels; +@property (nonatomic) BOOL reuseQueueStatsEnabled; + +@end + +@interface MGLMapView (MBXViewController) + +@property (nonatomic) BOOL usingLocaleBasedCountryLabels; +@property (nonatomic) NSDictionary *annotationViewReuseQueueByIdentifier; @end @@ -130,12 +151,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { [self restoreState:nil]; self.debugLoggingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsDebugLoggingEnabled"]; -} + self.hudLabel.hidden = YES; -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - if ([MGLAccountManager accessToken].length) { self.styleIndex = -1; @@ -289,6 +306,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @"Add 10,000 Sprites", @"Add Test Shapes", @"Add Point With Custom Callout", + @"Query Annotations", @"Remove Annotations", ]]; break; @@ -306,9 +324,19 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @"Style Lines With Filter", @"Style Fill With Numeric Filter", @"Style Query For GeoJSON", + @"Style Feature", + @"Style Dynamic Point Collection", + @"Update GeoJSON Source: Data", + @"Update GeoJSON Source: URL", + @"Update GeoJSON Source: Features", + @"Style Vector Source", + @"Style Raster Source", + [NSString stringWithFormat:@"Label Countries in %@", (_usingLocaleBasedCountryLabels ? @"Local Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])], ]]; break; case MBXSettingsMiscellaneous: + [settingsTitles addObject:@"Show Reuse Queue Stats"]; + [settingsTitles addObjectsFromArray:@[ @"Start World Tour", [NSString stringWithFormat:@"%@ Custom User Dot", (_customUserLocationAnnnotationEnabled ? @"Disable" : @"Enable")], @@ -321,6 +349,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @"Delete Telemetry Logfile", ]]; }; + break; default: NSAssert(NO, @"All settings sections should be implemented"); @@ -387,6 +416,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { case MBXSettingsAnnotationsCustomCallout: [self addAnnotationWithCustomCallout]; break; + case MBXSettingsAnnotationsQueryAnnotations: + [self testQueryPointAnnotations]; + break; case MBXSettingsAnnotationsRemoveAnnotations: [self.mapView removeAnnotations:self.mapView.annotations]; break; @@ -434,6 +466,30 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { case MBXSettingsRuntimeStylingStyleQuery: [self styleQuery]; break; + case MBXSettingsRuntimeStylingFeatureSource: + [self styleFeature]; + break; + case MBXSettingsRuntimeStylingPointCollection: + [self styleDynamicPointCollection]; + break; + case MBXSettingsRuntimeStylingUpdateGeoJSONSourceURL: + [self updateGeoJSONSourceURL]; + break; + case MBXSettingsRuntimeStylingUpdateGeoJSONSourceData: + [self updateGeoJSONSourceData]; + break; + case MBXSettingsRuntimeStylingUpdateGeoJSONSourceFeatures: + [self updateGeoJSONSourceFeatures]; + break; + case MBXSettingsRuntimeStylingVectorSource: + [self styleVectorSource]; + break; + case MBXSettingsRuntimeStylingRasterSource: + [self styleRasterSource]; + break; + case MBXSettingsRuntimeStylingCountryLabels: + [self styleCountryLabelsLanguage]; + break; default: NSAssert(NO, @"All runtime styling setting rows should be implemented"); break; @@ -454,6 +510,12 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { case MBXSettingsMiscellaneousDeleteLogFile: [self deleteTelemetryLogFile]; break; + case MBXSettingsMiscellaneousShowReuseQueueStats: + { + self.reuseQueueStatsEnabled = YES; + self.hudLabel.hidden = NO; + break; + } default: NSAssert(NO, @"All miscellaneous setting rows should be implemented"); break; @@ -794,7 +856,6 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { }); } - - (void)styleQuery { CGRect queryRect = CGRectInset(self.mapView.bounds, 100, 200); @@ -828,6 +889,247 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { }); } +- (void)styleFeature +{ + self.mapView.zoomLevel = 10; + self.mapView.centerCoordinate = CLLocationCoordinate2DMake(51.068585180672635, -114.06074523925781); + + CLLocationCoordinate2D leafCoords[] = { + CLLocationCoordinate2DMake(50.9683733218221,-114.07035827636719), + CLLocationCoordinate2DMake(51.02325750523972,-114.06967163085938), + CLLocationCoordinate2DMake(51.009434536947786,-114.14245605468749), + CLLocationCoordinate2DMake(51.030599281184124,-114.12597656249999), + CLLocationCoordinate2DMake(51.060386316691016,-114.21043395996094), + CLLocationCoordinate2DMake(51.063838646941576,-114.17816162109375), + CLLocationCoordinate2DMake(51.08152779888779,-114.19876098632812), + CLLocationCoordinate2DMake(51.08066507029602,-114.16854858398438), + CLLocationCoordinate2DMake(51.09662294502995,-114.17472839355469), + CLLocationCoordinate2DMake(51.07764539352731,-114.114990234375), + CLLocationCoordinate2DMake(51.13670896949613,-114.12391662597656), + CLLocationCoordinate2DMake(51.13369295212583,-114.09576416015624), + CLLocationCoordinate2DMake(51.17546878815025,-114.07585144042969), + CLLocationCoordinate2DMake(51.140155605265896,-114.04632568359375), + CLLocationCoordinate2DMake(51.15049396880196,-114.01542663574219), + CLLocationCoordinate2DMake(51.088860342359965,-114.00924682617186), + CLLocationCoordinate2DMake(51.12205789681453,-113.94813537597656), + CLLocationCoordinate2DMake(51.106539930027225,-113.94882202148438), + CLLocationCoordinate2DMake(51.117747873223344,-113.92616271972656), + CLLocationCoordinate2DMake(51.10093493903458,-113.92616271972656), + CLLocationCoordinate2DMake(51.10697105503078,-113.90625), + CLLocationCoordinate2DMake(51.09144802136697,-113.9117431640625), + CLLocationCoordinate2DMake(51.04916446529361,-113.97010803222655), + CLLocationCoordinate2DMake(51.045279344649146,-113.9398956298828), + CLLocationCoordinate2DMake(51.022825599852496,-114.06211853027344), + CLLocationCoordinate2DMake(51.045279344649146,-113.9398956298828), + CLLocationCoordinate2DMake(51.022825599852496,-114.06211853027344), + CLLocationCoordinate2DMake(51.022825599852496,-114.06280517578125), + CLLocationCoordinate2DMake(50.968805734317804,-114.06280517578125), + CLLocationCoordinate2DMake(50.9683733218221,-114.07035827636719), + }; + NSUInteger coordsCount = sizeof(leafCoords) / sizeof(leafCoords[0]); + + MGLPolygonFeature *feature = [MGLPolygonFeature polygonWithCoordinates:leafCoords count:coordsCount]; + feature.identifier = @"leaf-feature"; + feature.attributes = @{@"color": @"red"}; + + MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"leaf-source" features:@[feature] options:nil]; + [self.mapView.style addSource:source]; + + MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"leaf-fill-layer" source:source]; + layer.predicate = [NSPredicate predicateWithFormat:@"color = %@", @"red"]; + MGLStyleValue *fillColor = [MGLStyleValue<UIColor *> valueWithRawValue:[UIColor redColor]]; + layer.fillColor = fillColor; + [self.mapView.style addLayer:layer]; +} + +- (void)updateGeoJSONSourceData +{ + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(40.329795743702064, -107.75390625) zoomLevel:11 animated:NO]; + + NSString *geoJSON = @"{\"type\": \"FeatureCollection\",\"features\": [{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[-107.75390625,40.329795743702064],[-104.34814453125,37.64903402157866]]}}]}"; + + NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; + MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"mutable-data-source-id" geoJSONData:data options:nil]; + [self.mapView.style addSource:source]; + + MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"mutable-data-layer-id" source:source]; + [self.mapView.style addLayer:layer]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + NSString *geoJSON = @"{\"type\": \"FeatureCollection\",\"features\": [{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[-107.75390625,40.329795743702064],[-109.34814453125,37.64903402157866]]}}]}"; + NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; + + source.geoJSONData = data; + }); +} + +- (void)updateGeoJSONSourceURL +{ + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(48.668731, -122.857151) zoomLevel:11 animated:NO]; + + NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"polyline" ofType:@"geojson"]; + NSURL *geoJSONURL = [NSURL fileURLWithPath:filePath]; + MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"mutable-data-source-url-id" URL:geoJSONURL options:nil]; + [self.mapView.style addSource:source]; + + MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"mutable-data-layer-url-id" source:source]; + [self.mapView.style addLayer:layer]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(41.563986787078704, -75.04843935793578) zoomLevel:8 animated:NO]; + + NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"threestates" ofType:@"geojson"]; + NSURL *geoJSONURL = [NSURL fileURLWithPath:filePath]; + + source.URL = geoJSONURL; + }); +} + +- (void)updateGeoJSONSourceFeatures +{ + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(-41.1520, 288.6592) zoomLevel:10 animated:NO]; + + CLLocationCoordinate2D smallBox[] = { + {-41.14763798539186, 288.68019104003906}, + {-41.140915920129665, 288.68019104003906}, + {-41.140915920129665, 288.6887741088867}, + {-41.14763798539186, 288.6887741088867}, + {-41.14763798539186, 288.68019104003906} + }; + + CLLocationCoordinate2D largeBox[] = { + {-41.17710352162799, 288.67298126220703}, + {-41.13962313627545, 288.67298126220703}, + {-41.13962313627545, 288.7261962890625}, + {-41.17710352162799, 288.7261962890625}, + {-41.17710352162799, 288.67298126220703} + }; + + MGLPolygonFeature *smallBoxFeature = [MGLPolygonFeature polygonWithCoordinates:smallBox count:sizeof(smallBox)/sizeof(smallBox[0])]; + MGLPolygonFeature *largeBoxFeature = [MGLPolygonFeature polygonWithCoordinates:largeBox count:sizeof(largeBox)/sizeof(largeBox[0])]; + + MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"mutable-data-source-features-id" features:@[smallBoxFeature] options:nil]; + [self.mapView.style addSource:source]; + + MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"mutable-data-layer-features-id" source:source]; + MGLStyleValue *fillColor = [MGLStyleValue<UIColor *> valueWithRawValue:[UIColor redColor]]; + layer.fillColor = fillColor; + [self.mapView.style addLayer:layer]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + source.features = @[largeBoxFeature]; + }); +} + +- (void)styleDynamicPointCollection +{ + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(36.9979, -109.0441) zoomLevel:14 animated:NO]; + CLLocationCoordinate2D coordinates[] = { + {37.00145594210082, -109.04960632324219}, + {37.00173012609867, -109.0404224395752}, + {36.99453246847359, -109.04960632324219}, + {36.99508088541243, -109.04007911682129}, + }; + MGLPointCollectionFeature *feature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:4]; + MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"wiggle-source" features:@[feature] options:nil]; + [self.mapView.style addSource:source]; + + MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"wiggle-layer" source:source]; + [self.mapView.style addLayer:layer]; +} + +- (void)styleVectorSource +{ + NSURL *url = [[NSURL alloc] initWithString:@"mapbox://mapbox.mapbox-terrain-v2"]; + MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"style-vector-source-id" URL:url]; + [self.mapView.style addSource:vectorSource]; + + MGLBackgroundStyleLayer *backgroundLayer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:@"style-vector-background-layer-id"]; + backgroundLayer.backgroundColor = [MGLStyleValue<UIColor *> valueWithRawValue:[UIColor blackColor]]; + [self.mapView.style addLayer:backgroundLayer]; + + MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-vector-line-layer-id" source:vectorSource]; + lineLayer.sourceLayerIdentifier = @"contour"; + NSUInteger lineJoinValue = MGLLineJoinRound; + lineLayer.lineJoin = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue value:&lineJoinValue withObjCType:@encode(MGLLineJoin)]]; + NSUInteger lineCapValue = MGLLineCapRound; + lineLayer.lineCap = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue value:&lineCapValue withObjCType:@encode(MGLLineCap)]]; + lineLayer.lineColor = [MGLStyleValue<UIColor *> valueWithRawValue:[UIColor greenColor]]; + + [self.mapView.style addLayer:lineLayer]; +} + +- (void)styleRasterSource +{ + // 3rd party raster source requires NSAppTransportSecurity exception for stamen.com + MGLTileSet *rasterTileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"http://a.tile.stamen.com/terrain-background/{z}/{x}/{y}.jpg"]]; + MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"style-raster-source-id" tileSet:rasterTileSet tileSize:256]; + [self.mapView.style addSource:rasterSource]; + + MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"style-raster-layer-id" source:rasterSource]; + [self.mapView.style addLayer:rasterLayer]; +} + +-(void)styleCountryLabelsLanguage +{ + NSArray<NSString *> *labelLayers = @[ + @"country-label-lg", + @"country-label-md", + @"country-label-sm", + ]; + [self styleLabelLanguageForLayersNamed:labelLayers]; +} + +- (void)styleLabelLanguageForLayersNamed:(NSArray<NSString *> *)layers +{ + _usingLocaleBasedCountryLabels = !_usingLocaleBasedCountryLabels; + NSString *bestLanguageForUser = [NSString stringWithFormat:@"{name_%@}", [self bestLanguageForUser]]; + NSString *language = _usingLocaleBasedCountryLabels ? bestLanguageForUser : @"{name}"; + + for (NSString *layerName in layers) { + MGLSymbolStyleLayer *layer = (MGLSymbolStyleLayer *)[self.mapView.style layerWithIdentifier:layerName]; + + if ([layer isKindOfClass:[MGLSymbolStyleLayer class]]) { + if ([layer.textField isKindOfClass:[MGLStyleConstantValue class]]) { + MGLStyleConstantValue *label = (MGLStyleConstantValue<NSString *> *)layer.textField; + if ([label.rawValue hasPrefix:@"{name"]) { + layer.textField = [MGLStyleValue valueWithRawValue:language]; + } + } else if ([layer.textField isKindOfClass:[MGLStyleFunction class]]) { + MGLStyleFunction *function = (MGLStyleFunction<NSString *> *)layer.textField; + [function.stops enumerateKeysAndObjectsUsingBlock:^(id zoomLevel, id stop, BOOL *done) { + if ([stop isKindOfClass:[MGLStyleConstantValue class]]) { + MGLStyleConstantValue *label = (MGLStyleConstantValue<NSString *> *)stop; + if ([label.rawValue hasPrefix:@"{name"]) { + [function.stops setValue:[MGLStyleValue valueWithRawValue:language] forKey:zoomLevel]; + } + } + }]; + layer.textField = function; + } + } else { + NSLog(@"%@ is not a symbol style layer", layerName); + } + } +} + +- (NSString *)bestLanguageForUser +{ + NSArray *supportedLanguages = @[ @"en", @"es", @"fr", @"de", @"ru", @"zh" ]; + NSArray<NSString *> *preferredLanguages = [NSLocale preferredLanguages]; + NSString *bestLanguage; + + for (NSString *language in preferredLanguages) { + NSString *thisLanguage = [NSLocale localeWithLocaleIdentifier:language].languageCode; + if ([supportedLanguages containsObject:thisLanguage]) { + bestLanguage = thisLanguage; + break; + } + } + + return bestLanguage ?: @"en"; +} + - (IBAction)startWorldTour { _isTouringWorld = YES; @@ -875,6 +1177,20 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { self.mapView.userTrackingMode = MGLUserTrackingModeFollow; } +- (void)testQueryPointAnnotations { + NSNumber *visibleAnnotationCount = @(self.mapView.visibleAnnotations.count); + NSString *message; + if ([visibleAnnotationCount integerValue] == 1) { + message = [NSString stringWithFormat:@"There is %@ visible annotation.", visibleAnnotationCount]; + } else { + message = [NSString stringWithFormat:@"There are %@ visible annotations.", visibleAnnotationCount]; + } + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Visible Annotations" message:message preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:alertController animated:YES completion:nil]; +} + - (void)printTelemetryLogFile { NSString *fileContents = [NSString stringWithContentsOfFile:[self telemetryDebugLogFilePath] encoding:NSUTF8StringEncoding error:nil]; @@ -1208,4 +1524,24 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { point.coordinate = [self.mapView convertPoint:self.mapView.center toCoordinateFromView:self.mapView]; } +- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style +{ + // Default Mapbox styles use {name_en} as their label language, which means + // that a device with an English-language locale is already effectively + // using locale-based country labels. + _usingLocaleBasedCountryLabels = [[self bestLanguageForUser] isEqualToString:@"en"]; +} + +- (void)mapViewRegionIsChanging:(MGLMapView *)mapView +{ + if (self.reuseQueueStatsEnabled) { + NSUInteger queuedAnnotations = 0; + for (NSArray *queue in self.mapView.annotationViewReuseQueueByIdentifier.allValues) + { + queuedAnnotations += queue.count; + } + self.hudLabel.text = [NSString stringWithFormat:@"Visible: %ld Queued: %ld", (long)mapView.visibleAnnotations.count, (long)queuedAnnotations]; + } +} + @end diff --git a/platform/ios/app/Main.storyboard b/platform/ios/app/Main.storyboard index 7d8b2c304f..5819f17edc 100644 --- a/platform/ios/app/Main.storyboard +++ b/platform/ios/app/Main.storyboard @@ -1,9 +1,11 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="PSe-Ot-7Ff"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="PSe-Ot-7Ff"> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> + <capability name="Constraints to layout margins" minToolsVersion="6.0"/> <capability name="Navigation items with more than one left or right bar item" minToolsVersion="7.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--Map View Controller--> @@ -15,24 +17,35 @@ <viewControllerLayoutGuide type="bottom" id="m8o-i7-QIy"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="Z9X-fc-PUC"> - <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kNe-zV-9ha" customClass="MGLMapView"> - <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <gestureRecognizers/> <connections> <outlet property="delegate" destination="WaX-pd-UZQ" id="za0-3B-qR6"/> <outletCollection property="gestureRecognizers" destination="lfd-mn-7en" appends="YES" id="0PH-gH-GRm"/> </connections> </view> + <label opaque="NO" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="58y-pX-YyB"> + <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <constraints> + <constraint firstAttribute="width" constant="180" id="OL2-l5-I2f"/> + <constraint firstAttribute="height" constant="21" id="xHg-ye-wzT"/> + </constraints> + <fontDescription key="fontDescription" type="system" pointSize="8"/> + <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/> + <nil key="highlightedColor"/> + </label> </subviews> - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="kNe-zV-9ha" firstAttribute="leading" secondItem="Z9X-fc-PUC" secondAttribute="leading" id="53e-Tz-QxF"/> <constraint firstItem="kNe-zV-9ha" firstAttribute="bottom" secondItem="m8o-i7-QIy" secondAttribute="top" id="Etp-BC-E1N"/> <constraint firstAttribute="trailing" secondItem="kNe-zV-9ha" secondAttribute="trailing" id="MGr-8G-VEb"/> + <constraint firstItem="58y-pX-YyB" firstAttribute="trailing" secondItem="Z9X-fc-PUC" secondAttribute="trailingMargin" id="O3a-bR-boI"/> + <constraint firstItem="m8o-i7-QIy" firstAttribute="top" secondItem="58y-pX-YyB" secondAttribute="bottom" constant="20" id="cjh-ZS-Mv4"/> <constraint firstItem="kNe-zV-9ha" firstAttribute="top" secondItem="Z9X-fc-PUC" secondAttribute="top" id="qMm-e9-jxH"/> </constraints> </view> @@ -47,7 +60,7 @@ </connections> </barButtonItem> <button key="titleView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="KsN-ny-Hou"> - <rect key="frame" x="180" y="7" width="240" height="30"/> + <rect key="frame" x="61" y="7" width="207" height="30"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/> <state key="normal" title="Streets"/> @@ -75,6 +88,7 @@ </rightBarButtonItems> </navigationItem> <connections> + <outlet property="hudLabel" destination="58y-pX-YyB" id="MEh-ir-3IH"/> <outlet property="mapView" destination="kNe-zV-9ha" id="VNR-WO-1q4"/> </connections> </viewController> @@ -85,60 +99,60 @@ </connections> </pongPressGestureRecognizer> </objects> - <point key="canvasLocation" x="1366" y="350"/> + <point key="canvasLocation" x="1365.5999999999999" y="349.47526236881561"/> </scene> <!--Offline Packs--> <scene sceneID="xIg-PA-7r3"> <objects> <tableViewController id="7q0-lI-zqb" customClass="MBXOfflinePacksTableViewController" sceneMemberID="viewController"> <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="eeN-6b-zqe"> - <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <prototypes> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Inactive" editingAccessoryType="detailDisclosureButton" textLabel="JtH-Ce-MI5" detailTextLabel="tTJ-jv-U9v" style="IBUITableViewCellStyleSubtitle" id="fGu-Ys-Eh1"> - <rect key="frame" x="0.0" y="92" width="600" height="44"/> + <rect key="frame" x="0.0" y="92" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fGu-Ys-Eh1" id="sUf-bc-8xG"> - <rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/> + <frame key="frameInset" width="375" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="My Inactive Offline Pack" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="JtH-Ce-MI5"> - <rect key="frame" x="15" y="6" width="174.5" height="19.5"/> + <frame key="frameInset" minX="15" minY="6" width="174.5" height="19.5"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="456 resources (789 MB)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tTJ-jv-U9v"> - <rect key="frame" x="15" y="25.5" width="128" height="13.5"/> + <frame key="frameInset" minX="15" minY="25.5" width="128" height="13.5"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" pointSize="11"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> </tableViewCellContentView> </tableViewCell> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Active" editingAccessoryType="detailDisclosureButton" textLabel="9ZK-gS-wJ4" detailTextLabel="0xK-p8-Mmh" style="IBUITableViewCellStyleSubtitle" id="mKB-tz-Zfl"> - <rect key="frame" x="0.0" y="136" width="600" height="44"/> + <rect key="frame" x="0.0" y="136" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="mKB-tz-Zfl" id="nS3-aU-nBr"> - <rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/> + <frame key="frameInset" width="375" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="My Active Offline Pack" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9ZK-gS-wJ4"> - <rect key="frame" x="15" y="6" width="163" height="19.5"/> + <frame key="frameInset" minX="15" minY="6" width="163" height="19.5"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" pointSize="16"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Downloading 123 of 456 resources… (789 MB downloaded)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="0xK-p8-Mmh"> - <rect key="frame" x="15" y="25.5" width="310.5" height="13.5"/> + <frame key="frameInset" minX="15" minY="25.5" width="310.5" height="13.5"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" pointSize="11"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> @@ -189,5 +203,5 @@ <image name="TrackingLocationOffMask.png" width="23" height="23"/> <image name="settings.png" width="28" height="28"/> </resources> - <color key="tintColor" red="0.12156862745098039" green="0.5490196078431373" blue="0.6705882352941176" alpha="1" colorSpace="calibratedRGB"/> + <color key="tintColor" red="0.12156862745098039" green="0.5490196078431373" blue="0.6705882352941176" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </document> diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 3c19f5ea41..a78cf583cb 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -128,6 +128,11 @@ 4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4018B1CB1CDC288E00F666AF /* MGLAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404326881D5B9B1A007111BD /* MGLAnnotationContainerView_Private.h */; }; + 4049C29D1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4049C29E1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4049C29F1DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */; }; + 4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */; }; + 4049C2AC1DB6E05500B3F799 /* MGLPointCollection_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */; }; 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 */; }; @@ -169,6 +174,7 @@ DA1DC99B1CB6E064006E619F /* MBXViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1DC99A1CB6E064006E619F /* MBXViewController.m */; }; DA1DC99D1CB6E076006E619F /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC99C1CB6E076006E619F /* Default-568h@2x.png */; }; DA1DC99F1CB6E088006E619F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC99E1CB6E088006E619F /* Assets.xcassets */; }; + DA2207BF1DC0805F0002F84D /* MGLStyleValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */; }; DA25D5C01CCD9F8400607828 /* Root.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5BF1CCD9F8400607828 /* Root.plist */; }; DA25D5C61CCDA06800607828 /* Root.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5C41CCDA06800607828 /* Root.strings */; }; DA25D5CD1CCDA11500607828 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5B91CCD9EDE00607828 /* Settings.bundle */; }; @@ -555,14 +561,17 @@ 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationView.h; sourceTree = "<group>"; }; 402E9DE01CD2C76200FD4519 /* Mapbox.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Mapbox.playground; sourceTree = "<group>"; }; 404326881D5B9B1A007111BD /* MGLAnnotationContainerView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView_Private.h; sourceTree = "<group>"; }; + 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection.h; sourceTree = "<group>"; }; + 4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLPointCollection.mm; sourceTree = "<group>"; }; + 4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection_Private.h; sourceTree = "<group>"; }; 404C26E01D89B877000AA13D /* MGLTileSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSet.h; sourceTree = "<group>"; }; 404C26E11D89B877000AA13D /* MGLTileSet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSet.mm; sourceTree = "<group>"; }; 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTileSet_Private.h; sourceTree = "<group>"; }; - 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSetTests.mm; sourceTree = "<group>"; }; + 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLTileSetTests.mm; path = ../../darwin/test/MGLTileSetTests.mm; sourceTree = "<group>"; }; 408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+MGLAdditions.h"; sourceTree = "<group>"; }; 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDictionary+MGLAdditions.mm"; sourceTree = "<group>"; }; 40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLShape_Private.h; sourceTree = "<group>"; }; - 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLGeoJSONSourceTests.mm; sourceTree = "<group>"; }; + 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLGeoJSONSourceTests.mm; path = ../../darwin/test/MGLGeoJSONSourceTests.mm; sourceTree = "<group>"; }; 40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView.h; sourceTree = "<group>"; }; 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAnnotationContainerView.m; sourceTree = "<group>"; }; 40F8876F1D7A1DB8008ECB67 /* MGLGeoJSONSource_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLGeoJSONSource_Private.h; sourceTree = "<group>"; }; @@ -593,6 +602,8 @@ DA1DC99A1CB6E064006E619F /* MBXViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXViewController.m; sourceTree = "<group>"; }; DA1DC99C1CB6E076006E619F /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; }; DA1DC99E1CB6E088006E619F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; + DA2207BD1DC0805F0002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = "<group>"; }; + DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLStyleValueTests.swift; path = ../../darwin/test/MGLStyleValueTests.swift; sourceTree = "<group>"; }; DA25D5B91CCD9EDE00607828 /* Settings.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Settings.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; DA25D5BF1CCD9F8400607828 /* Root.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Root.plist; sourceTree = "<group>"; }; DA25D5C51CCDA06800607828 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Root.strings; sourceTree = "<group>"; }; @@ -877,9 +888,11 @@ 357579811D502AD4000B822E /* Styling */ = { isa = PBXGroup; children = ( + DA2207BD1DC0805F0002F84D /* test-Bridging-Header.h */, 3575798F1D513EF1000B822E /* Layers */, 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */, 40CFA64E1D78754A008103BD /* Sources */, + DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */, ); name = Styling; sourceTree = "<group>"; @@ -1257,12 +1270,15 @@ DA8847E11CBAFA5100AB86E3 /* MGLGeometry.h */, DA8848011CBAFA6200AB86E3 /* MGLGeometry_Private.h */, DA8848021CBAFA6200AB86E3 /* MGLGeometry.mm */, - DA8847E31CBAFA5100AB86E3 /* MGLMultiPoint.h */, DA8848041CBAFA6200AB86E3 /* MGLMultiPoint_Private.h */, + DA8847E31CBAFA5100AB86E3 /* MGLMultiPoint.h */, DA8848051CBAFA6200AB86E3 /* MGLMultiPoint.mm */, DA8847E71CBAFA5100AB86E3 /* MGLOverlay.h */, DA8847E81CBAFA5100AB86E3 /* MGLPointAnnotation.h */, DA88480B1CBAFA6200AB86E3 /* MGLPointAnnotation.mm */, + 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */, + 4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */, + 4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */, DA8847E91CBAFA5100AB86E3 /* MGLPolygon.h */, DA88480C1CBAFA6200AB86E3 /* MGLPolygon.mm */, DA8847EA1CBAFA5100AB86E3 /* MGLPolyline.h */, @@ -1410,6 +1426,7 @@ DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */, 7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */, 400533011DB0862B0069F638 /* NSArray+MGLAdditions.h in Headers */, + 4049C29D1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */, DA88483E1CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */, 40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */, 4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */, @@ -1449,6 +1466,7 @@ 35136D4C1D4277FC00C20EFD /* MGLSource.h in Headers */, 3566C76C1D4A8DFA008152BC /* MGLRasterSource.h in Headers */, DA8847F91CBAFA5100AB86E3 /* MGLPolygon.h in Headers */, + 4049C2AC1DB6E05500B3F799 /* MGLPointCollection_Private.h in Headers */, DA8847F81CBAFA5100AB86E3 /* MGLPointAnnotation.h in Headers */, 353933F21D3FB753003F57D7 /* MGLCircleStyleLayer.h in Headers */, DA8847F31CBAFA5100AB86E3 /* MGLMultiPoint.h in Headers */, @@ -1493,6 +1511,7 @@ DABFB85E1CBE99E500D62B32 /* MGLAnnotation.h in Headers */, DABFB8641CBE99E500D62B32 /* MGLOfflineStorage.h in Headers */, DAD165791CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */, + 4049C29E1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */, 3566C7671D4A77BA008152BC /* MGLGeoJSONSource.h in Headers */, DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */, DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */, @@ -1699,6 +1718,7 @@ }; DA2E88501CC036F400F24E7B = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; }; DA8847D11CBAF91600AB86E3 = { CreatedOnToolsVersion = 7.3; @@ -1868,6 +1888,7 @@ 357579851D502AF5000B822E /* MGLSymbolStyleLayerTests.m in Sources */, 357579871D502AFE000B822E /* MGLLineStyleLayerTests.m in Sources */, 357579891D502B06000B822E /* MGLCircleStyleLayerTests.m in Sources */, + DA2207BF1DC0805F0002F84D /* MGLStyleValueTests.swift in Sources */, 40CFA6511D7875BB008103BD /* MGLGeoJSONSourceTests.mm in Sources */, DA35A2C51CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m in Sources */, 35B8E08C1D6C8B5100E768D2 /* MGLFilterTests.mm in Sources */, @@ -1943,6 +1964,7 @@ 35D13AC51D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */, DA8848241CBAFA6200AB86E3 /* MGLOfflineStorage.mm in Sources */, DA88482A1CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm in Sources */, + 4049C29F1DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */, 35136D3F1D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */, DA88481A1CBAFA6200AB86E3 /* MGLAccountManager.m in Sources */, 3510FFFB1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */, @@ -2014,6 +2036,7 @@ 35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */, DAA4E42A1CBB730400178DFB /* NSProcessInfo+MGLAdditions.m in Sources */, DAA4E4211CBB730400178DFB /* MGLOfflineStorage.mm in Sources */, + 4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */, 35136D401D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */, DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */, 3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */, @@ -2264,6 +2287,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; INFOPLIST_FILE = test/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -2276,6 +2300,9 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "test/test-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -2283,6 +2310,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; INFOPLIST_FILE = test/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -2295,6 +2323,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "test/test-Bridging-Header.h"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index c41dddc899..c19d9e3883 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -34,6 +34,7 @@ custom_categories: - MGLMultiPolygon - MGLMultiPolyline - MGLPointAnnotation + - MGLPointCollection - MGLPolygon - MGLPolyline - MGLOverlay @@ -44,9 +45,9 @@ custom_categories: - name: Map Data children: - MGLFeature - - MGLMultiPointFeature - MGLMultiPolygonFeature - MGLMultiPolylineFeature + - MGLPointCollectionFeature - MGLPointFeature - MGLPolygonFeature - MGLPolylineFeature diff --git a/platform/ios/scripts/deploy-packages.sh b/platform/ios/scripts/deploy-packages.sh index 51b90a545f..8ad5e7abb1 100755 --- a/platform/ios/scripts/deploy-packages.sh +++ b/platform/ios/scripts/deploy-packages.sh @@ -43,7 +43,7 @@ buildPackageStyle() { github-release upload \ --tag "ios-v${PUBLISH_VERSION}" \ --name ${file_name} \ - --file "${BINARY_DIRECTORY}/${file_name}" + --file "${BINARY_DIRECTORY}/${file_name}" > /dev/null fi } @@ -58,9 +58,6 @@ BINARY_DIRECTORY=${BINARY_DIRECTORY:-build/ios/deploy} GITHUB_RELEASE=${GITHUB_RELEASE:-true} PUBLISH_PRE_FLAG='' -rm -rf ${BINARY_DIRECTORY} -mkdir -p ${BINARY_DIRECTORY} - if [[ ${GITHUB_RELEASE} = "true" ]]; then GITHUB_RELEASE=true # Assign bool, not just a string @@ -98,6 +95,7 @@ git checkout ${VERSION_TAG} step "Deploying version ${PUBLISH_VERSION}…" make clean && make distclean +mkdir -p ${BINARY_DIRECTORY} if [[ "${GITHUB_RELEASE}" == true ]]; then step "Create GitHub release…" @@ -116,4 +114,4 @@ buildPackageStyle "iframework" "symbols-dynamic" buildPackageStyle "iframework SYMBOLS=NO" "dynamic" buildPackageStyle "ifabric" "fabric" -step "Finished deploying ${PUBLISH_VERSION}" +step "Finished deploying ${PUBLISH_VERSION} in $(($SECONDS / 60)) minutes and $(($SECONDS % 60)) seconds" diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h index 57b74daa04..e467495a4a 100644 --- a/platform/ios/src/MGLMapView.h +++ b/platform/ios/src/MGLMapView.h @@ -893,13 +893,22 @@ IB_DESIGNABLE @property (nonatomic, readonly, nullable) NS_ARRAY_OF(id <MGLAnnotation>) *annotations; /** + The complete list of annotations associated with the receiver that are + currently visible. + + The objects in this array must adopt the `MGLAnnotation` protocol. If no + annotations are associated with the map view or if no annotations associated + with the map view are currently visible, the value of this property is `nil`. + */ +@property (nonatomic, readonly, nullable) NS_ARRAY_OF(id <MGLAnnotation>) *visibleAnnotations; + +/** Adds an annotation to the map view. - @note `MGLMultiPolyline`, `MGLMultiPolygon`, and `MGLShapeCollection` objects - cannot be added to the map view at this time. Nor can `MGLMultiPoint` - objects that are not instances of `MGLPolyline` or `MGLPolygon`. Any - multipoint, multipolyline, multipolygon, or shape collection object that is - specified is silently ignored. + @note `MGLMultiPolyline`, `MGLMultiPolygon`, `MGLShapeCollection`, and + `MGLPointCollection` objects cannot be added to the map view at this time. + Any multipoint, multipolyline, multipolygon, shape or point collection + object that is specified is silently ignored. @param annotation The annotation object to add to the receiver. This object must conform to the `MGLAnnotation` protocol. The map view retains the @@ -987,6 +996,17 @@ IB_DESIGNABLE */ - (nullable __kindof MGLAnnotationView *)dequeueReusableAnnotationViewWithIdentifier:(NSString *)identifier; +/** + Returns the list of annotations associated with the receiver that intersect with + the given rectangle. + + @param rect A rectangle expressed in the map view’s coordinate system. + @return An array of objects that adopt the `MGLAnnotation` protocol or `nil` if + no annotations associated with the map view are currently visible in the + rectangle. + */ +- (nullable NS_ARRAY_OF(id <MGLAnnotation>) *)visibleAnnotationsInRect:(CGRect)rect; + #pragma mark Managing Annotation Selections /** diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index d392849522..466912c217 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -129,7 +129,10 @@ enum { MGLAnnotationTagNotFound = UINT32_MAX }; /// Mapping from an annotation tag to metadata about that annotation, including /// the annotation itself. -typedef std::map<MGLAnnotationTag, MGLAnnotationContext> MGLAnnotationContextMap; +typedef std::unordered_map<MGLAnnotationTag, MGLAnnotationContext> MGLAnnotationTagContextMap; + +/// Mapping from an annotation object to an annotation tag. +typedef std::map<id<MGLAnnotation>, MGLAnnotationTag> MGLAnnotationObjectTagMap; /// Initializes the run loop shim that lives on the main thread. void MGLinitializeRunLoop() { @@ -254,6 +257,7 @@ public: @property (nonatomic) MGLMapViewProxyAccessibilityElement *mapViewProxyAccessibilityElement; @property (nonatomic) MGLAnnotationContainerView *annotationContainerView; @property (nonatomic) MGLUserLocation *userLocation; +@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, NS_MUTABLE_ARRAY_OF(MGLAnnotationView *) *) *annotationViewReuseQueueByIdentifier; @end @@ -267,10 +271,11 @@ public: NS_MUTABLE_ARRAY_OF(NSURL *) *_bundledStyleURLs; - MGLAnnotationContextMap _annotationContextsByAnnotationTag; + MGLAnnotationTagContextMap _annotationContextsByAnnotationTag; + MGLAnnotationObjectTagMap _annotationTagsByAnnotation; + /// Tag of the selected annotation. If the user location annotation is selected, this ivar is set to `MGLAnnotationTagNotFound`. MGLAnnotationTag _selectedAnnotationTag; - NS_MUTABLE_DICTIONARY_OF(NSString *, NS_MUTABLE_ARRAY_OF(MGLAnnotationView *) *) *_annotationViewReuseQueueByIdentifier; BOOL _userLocationAnnotationIsSelected; /// Size of the rectangle formed by unioning the maximum slop area around every annotation image and annotation image view. @@ -426,6 +431,7 @@ public: // Set up annotation management and selection state. _annotationImagesByIdentifier = [NSMutableDictionary dictionary]; _annotationContextsByAnnotationTag = {}; + _annotationTagsByAnnotation = {}; _annotationViewReuseQueueByIdentifier = [NSMutableDictionary dictionary]; _selectedAnnotationTag = MGLAnnotationTagNotFound; _annotationsNearbyLastTap = {}; @@ -2819,6 +2825,35 @@ public: return [NSArray arrayWithObjects:&annotations[0] count:annotations.size()]; } +- (nullable NS_ARRAY_OF(id <MGLAnnotation>) *)visibleAnnotations +{ + return [self visibleAnnotationsInRect:self.bounds]; +} + +- (nullable NS_ARRAY_OF(id <MGLAnnotation>) *)visibleAnnotationsInRect:(CGRect)rect +{ + if (_annotationContextsByAnnotationTag.empty()) + { + return nil; + } + + std::vector<MGLAnnotationTag> annotationTags = [self annotationTagsInRect:rect]; + if (annotationTags.size()) + { + NSMutableArray *annotations = [NSMutableArray arrayWithCapacity:annotationTags.size()]; + + for (auto const& annotationTag: annotationTags) + { + MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag]; + [annotations addObject:annotationContext.annotation]; + } + + return [annotations copy]; + } + + return nil; +} + /// Returns the annotation assigned the given tag. Cheap. - (id <MGLAnnotation>)annotationWithTag:(MGLAnnotationTag)tag { @@ -2878,13 +2913,6 @@ public: if ([annotation isKindOfClass:[MGLMultiPoint class]]) { - // Actual multipoints aren’t supported as annotations. - if ([annotation isMemberOfClass:[MGLMultiPoint class]] - || [annotation isMemberOfClass:[MGLMultiPointFeature class]]) - { - continue; - } - // The polyline or polygon knows how to style itself (with the map view’s help). MGLMultiPoint *multiPoint = (MGLMultiPoint *)annotation; if (!multiPoint.pointCount) { @@ -2899,8 +2927,9 @@ public: [(NSObject *)annotation addObserver:self forKeyPath:@"coordinates" options:0 context:(void *)(NSUInteger)annotationTag]; } else if ( ! [annotation isKindOfClass:[MGLMultiPolyline class]] - || ![annotation isKindOfClass:[MGLMultiPolygon class]] - || ![annotation isKindOfClass:[MGLShapeCollection class]]) + && ![annotation isKindOfClass:[MGLMultiPolygon class]] + && ![annotation isKindOfClass:[MGLShapeCollection class]] + && ![annotation isKindOfClass:[MGLPointCollection class]]) { MGLAnnotationView *annotationView; NSString *symbolName; @@ -2972,6 +3001,7 @@ public: context.viewReuseIdentifier = annotationView.reuseIdentifier; } + _annotationTagsByAnnotation[annotation] = annotationTag; _annotationContextsByAnnotationTag[annotationTag] = context; if ([annotation isKindOfClass:[NSObject class]]) { @@ -3068,9 +3098,7 @@ public: - (nullable MGLAnnotationView *)viewForAnnotation:(id<MGLAnnotation>)annotation { - MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation]; - if (annotationTag == MGLAnnotationTagNotFound) return nil; - + MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation); MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); return annotationContext.annotationView; } @@ -3171,6 +3199,16 @@ public: MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); MGLAnnotationView *annotationView = annotationContext.annotationView; + + if (annotationContext.viewReuseIdentifier) + { + NSMutableArray *annotationViewReuseQueue = [self annotationViewReuseQueueForIdentifier:annotationContext.viewReuseIdentifier]; + if (![annotationViewReuseQueue containsObject:annotationView]) + { + [annotationViewReuseQueue removeObject:annotationView]; + } + } + annotationView.annotation = nil; [annotationView removeFromSuperview]; @@ -3180,6 +3218,7 @@ public: } _annotationContextsByAnnotationTag.erase(annotationTag); + _annotationTagsByAnnotation.erase(annotation); if ([annotation isKindOfClass:[NSObject class]] && ![annotation isKindOfClass:[MGLMultiPoint class]]) { @@ -4614,49 +4653,89 @@ public: [CATransaction begin]; [CATransaction setDisableActions:YES]; - for (auto &pair : _annotationContextsByAnnotationTag) + // If the map is pitched consider the viewport to be exactly the same as the bounds. + // Otherwise, add a small buffer. + CGFloat widthAdjustment = self.camera.pitch > 0.0 ? 0.0 : -_largestAnnotationViewSize.width * 2.0; + CGFloat heightAdjustment = self.camera.pitch > 0.0 ? 0.0 : -_largestAnnotationViewSize.height * 2.0; + CGRect viewPort = CGRectInset(self.bounds, widthAdjustment, heightAdjustment); + + NSArray *visibleAnnotations = [self visibleAnnotationsInRect:viewPort]; + NSMutableArray *offscreenAnnotations = [self.annotations mutableCopy]; + [offscreenAnnotations removeObjectsInArray:visibleAnnotations]; + + // Update the center of visible annotation views + for (id<MGLAnnotation> annotation in visibleAnnotations) { - CGRect viewPort = CGRectInset(self.bounds, - -_largestAnnotationViewSize.width / 2.0 - MGLAnnotationUpdateViewportOutset.width / 2.0, - -_largestAnnotationViewSize.height / 2.0 - MGLAnnotationUpdateViewportOutset.width); - - MGLAnnotationContext &annotationContext = pair.second; - MGLAnnotationView *annotationView = annotationContext.annotationView; - // Defer to the shape/polygon styling delegate methods - if ([annotationContext.annotation isKindOfClass:[MGLMultiPoint class]]) + if ([annotation isKindOfClass:[MGLMultiPoint class]]) { continue; } + // Get the annotation tag then use it to get the context. This avoids the expensive lookup + // by tag in `annotationTagForAnnotation:` + MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation); + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); + + MGLAnnotationView *annotationView = annotationContext.annotationView; if (!annotationView) { + // This will dequeue views if the delegate implements the dequeue call MGLAnnotationView *annotationView = [self annotationViewForAnnotation:annotationContext.annotation]; + if (annotationView) { annotationView.mapView = self; - annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; annotationContext.annotationView = annotationView; + // New annotation (created because there is nothing to dequeue) may not have been added to the + // container view yet. Add them here. if (!annotationView.superview) { [self.annotationContainerView insertSubview:annotationView atIndex:0]; } } - else - { - // if there is no annotationView at this point then we are dealing with a sprite backed annotation - continue; - } } - bool annotationViewIsVisible = CGRectContainsRect(viewPort, annotationView.frame); - if (!annotationViewIsVisible && annotationContext.viewReuseIdentifier) + if (annotationView) { - [self enqueueAnnotationViewForAnnotationContext:annotationContext]; + annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; } - else + } + + CGPoint upperLeft = {_largestAnnotationViewSize.width,_largestAnnotationViewSize.height}; + CGPoint lowerRight = {CGRectGetWidth(self.bounds) + _largestAnnotationViewSize.width, + CGRectGetHeight(self.bounds) + _largestAnnotationViewSize.height}; + + CLLocationCoordinate2D upperLeftCoordinate = [self convertPoint:upperLeft toCoordinateFromView:self]; + CLLocationCoordinate2D lowerRightCoordinate = [self convertPoint:lowerRight toCoordinateFromView:self]; + + // Enqueue (and move if required) offscreen annotation views + for (id<MGLAnnotation> annotation in offscreenAnnotations) + { + CLLocationCoordinate2D coordinate = annotation.coordinate; + MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation); + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); + UIView *annotationView = annotationContext.annotationView; + + if (annotationView) { - annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; + // Every so often (1 out of 1000 frames?) the mbgl query mechanism fails. This logic spot checks the + // offscreenAnnotations values -- if they are actually still on screen then the view center is + // moved and the enqueue operation is avoided. This allows us to keep the performance benefit of + // using the mbgl query result. It also forces views that have just gone offscreen to be cleared + // fully from view. + if ((coordinate.latitude > upperLeftCoordinate.latitude || coordinate.latitude < lowerRightCoordinate.latitude) || + (coordinate.longitude < upperLeftCoordinate.longitude || coordinate.longitude > lowerRightCoordinate.longitude)) + { + CGRect adjustedFrame = annotationView.frame; + adjustedFrame.origin.x = -CGRectGetWidth(adjustedFrame) * 2.0; + annotationView.frame = adjustedFrame; + [self enqueueAnnotationViewForAnnotationContext:annotationContext]; + } + else + { + annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; + } } } @@ -4669,10 +4748,9 @@ public: if (!annotationView) return; - annotationView.annotation = nil; - if (annotationContext.viewReuseIdentifier) { + annotationView.annotation = nil; NSMutableArray *annotationViewReuseQueue = [self annotationViewReuseQueueForIdentifier:annotationContext.viewReuseIdentifier]; if (![annotationViewReuseQueue containsObject:annotationView]) { diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h index 04892eb6a1..c2fda1be1f 100644 --- a/platform/ios/src/Mapbox.h +++ b/platform/ios/src/Mapbox.h @@ -27,6 +27,7 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[]; #import "MGLOfflineStorage.h" #import "MGLOverlay.h" #import "MGLPointAnnotation.h" +#import "MGLPointCollection.h" #import "MGLPolygon.h" #import "MGLPolyline.h" #import "MGLShape.h" diff --git a/platform/ios/test/test-Bridging-Header.h b/platform/ios/test/test-Bridging-Header.h new file mode 100644 index 0000000000..e11d920b12 --- /dev/null +++ b/platform/ios/test/test-Bridging-Header.h @@ -0,0 +1,3 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 56f5f7d307..9f08e5de9d 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -7,6 +7,7 @@ * Fixed an issue causing code signing failures and bloating the framework. ([#5850](https://github.com/mapbox/mapbox-gl-native/pull/5850)) * Xcode 7.3 or higher is now required for using this SDK. ([#6059](https://github.com/mapbox/mapbox-gl-native/issues/6059)) * Fixed an issue with symbols not being properly stripped from the dynamic framework when built with `make xpackage SYMBOLS=NO`. ([#6531](https://github.com/mapbox/mapbox-gl-native/pull/6531)) +* Added documentation for the Info.plist keys used by this SDK. ([#6833](https://github.com/mapbox/mapbox-gl-native/pull/6833)) ### Styles and data @@ -14,8 +15,11 @@ * MGLMapView’s `styleURL` property can now be set to an absolute file URL. ([#6026](https://github.com/mapbox/mapbox-gl-native/pull/6026)) * GeoJSON sources specified by the stylesheet at design time now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) * TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) +* Fixed an issue causing abstract `MGLMultiPointFeature` objects to be returned in feature query results. Now concrete `MGLPointCollectionFeature` objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) * Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908)) * Fixed an issue where the style zoom levels were not respected when deciding when to render a layer. ([#5811](https://github.com/mapbox/mapbox-gl-native/issues/5811)) +* Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773)) +* MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728)) * If MGLMapView is unable to obtain or parse a style, it now calls its delegate’s `-mapViewDidFailLoadingMap:withError:` method. ([#6145](https://github.com/mapbox/mapbox-gl-native/pull/6145)) * Added the `-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` delegate method, which offers the earliest opportunity to modify the layout or appearance of the current style before the map view is displayed to the user. ([#6636](https://github.com/mapbox/mapbox-gl-native/pull/6636)) * Fixed an issue causing stepwise zoom functions to be misinterpreted. ([#6328](https://github.com/mapbox/mapbox-gl-native/pull/6328)) @@ -23,14 +27,17 @@ * Fixed crashes that could occur when loading a malformed stylesheet. ([#5736](https://github.com/mapbox/mapbox-gl-native/pull/5736)) * Improved style parsing performance. ([#6170](https://github.com/mapbox/mapbox-gl-native/pull/6170)) * Improved feature querying performance. ([#6514](https://github.com/mapbox/mapbox-gl-native/pull/6514)) +* Fixed an issue where shapes that cannot currently be visually represented as annotations were still shown on the map as point annotations. ([#6764](https://github.com/mapbox/mapbox-gl-native/issues/6764)) ### Annotations * Added `showAnnotations:animated:` and `showAnnotations:edgePadding:animated:`, which moves the map viewport to show the specified annotations. ([#5749](https://github.com/mapbox/mapbox-gl-native/pull/5749)) * MGLPolyline annotations and the exterior coordinates of MGLPolygon annotations are now able to be mutated, part or all, and changes are displayed immediately. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) +* Added new APIs to MGLMapView to query for visible annotations. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061)) +* Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706)) * To make an MGLPolyline or MGLPolygon span the antimeridian, specify coordinates with longitudes greater than 180° or less than −180°. ([#6088](https://github.com/mapbox/mapbox-gl-native/pull/6088)) +* Fixed an issue where placing a point annotation on Null Island also placed a duplicate annotation on its antipode. ([#3563](https://github.com/mapbox/mapbox-gl-native/pull/3563)) * Improved the precision of annotations at zoom levels greater than 18. ([#5517](https://github.com/mapbox/mapbox-gl-native/pull/5517)) -* Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706)) ### Networking and offline maps @@ -46,6 +53,7 @@ ### Other changes * Fixed an issue where the map view’s center would always be calculated as if the view occupied the entire window. ([#6102](https://github.com/mapbox/mapbox-gl-native/pull/6102)) +* Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794)) * Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879)) ## 0.2.1 - July 19, 2016 diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index 6909e14385..42f978283e 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -30,6 +30,7 @@ custom_categories: - MGLMultiPolygon - MGLMultiPolyline - MGLPointAnnotation + - MGLPointCollection - MGLPolygon - MGLPolyline - MGLOverlay @@ -37,11 +38,11 @@ custom_categories: - MGLShapeCollection - name: Map Data children: - - MGLFeature - - MGLMultiPointFeature + - MGLFeature - MGLMultiPolygonFeature - MGLMultiPolylineFeature - - MGLPointFeature + - MGLPointCollectionFeature + - MGLPointFeature - MGLPolygonFeature - MGLPolylineFeature - MGLShapeCollectionFeature diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index eedad040b0..194d543f82 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -40,6 +40,8 @@ 35C5D84A1D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D8461D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.mm */; }; 35D65C5A1D65AD5500722C23 /* NSDate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35D65C581D65AD5500722C23 /* NSDate+MGLAdditions.h */; }; 35D65C5B1D65AD5500722C23 /* NSDate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D65C591D65AD5500722C23 /* NSDate+MGLAdditions.mm */; }; + 4049C2A51DB6CE7F00B3F799 /* MGLPointCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4049C2AD1DB8020600B3F799 /* MGLPointCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */; }; 408AA85B1DAEECFE00022900 /* MGLShape_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA85A1DAEECF100022900 /* MGLShape_Private.h */; }; 408AA8651DAEEE3400022900 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA8601DAEED3300022900 /* MGLPolygon+MGLAdditions.h */; }; 408AA8661DAEEE3600022900 /* MGLPolyline+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA8611DAEED3300022900 /* MGLPolyline+MGLAdditions.h */; }; @@ -55,6 +57,7 @@ 558F18221D0B13B100123F46 /* libmbgl-loop.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 558F18211D0B13B000123F46 /* libmbgl-loop.a */; }; 55D9B4B11D005D3900C1CCE2 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D9B4B01D005D3900C1CCE2 /* libz.tbd */; }; DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */; }; + DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */; }; DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */; }; DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */; }; @@ -79,6 +82,19 @@ DA839EA01CC2E3400062CAFB /* MapDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA839E9E1CC2E3400062CAFB /* MapDocument.xib */; }; DA839EA21CC2E3400062CAFB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA839EA11CC2E3400062CAFB /* Assets.xcassets */; }; DA839EA51CC2E3400062CAFB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA839EA31CC2E3400062CAFB /* MainMenu.xib */; }; + DA87A9981DC9D88400810D09 /* MGLGeoJSONSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9961DC9D88400810D09 /* MGLGeoJSONSourceTests.mm */; }; + DA87A9991DC9D88400810D09 /* MGLTileSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */; }; + DA87A99C1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99B1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h */; }; + DA87A99D1DC9DB2E00810D09 /* MGLStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2DBBC81D51E26600D38FF9 /* MGLStyleLayerTests.m */; }; + DA87A99E1DC9DC2100810D09 /* MGLFilterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */; }; + DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */; }; + DA87A9A11DC9DCB400810D09 /* MGLRuntimeStylingHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F257B1D51C5F40010E6B5 /* MGLRuntimeStylingHelper.m */; }; + DA87A9A21DC9DCF100810D09 /* MGLFillStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25741D51C5F40010E6B5 /* MGLFillStyleLayerTests.m */; }; + DA87A9A31DCACC5000810D09 /* MGLRasterStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25751D51C5F40010E6B5 /* MGLRasterStyleLayerTests.m */; }; + DA87A9A41DCACC5000810D09 /* MGLSymbolStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25761D51C5F40010E6B5 /* MGLSymbolStyleLayerTests.m */; }; + DA87A9A51DCACC5000810D09 /* MGLLineStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25771D51C5F40010E6B5 /* MGLLineStyleLayerTests.m */; }; + DA87A9A61DCACC5000810D09 /* MGLCircleStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25781D51C5F40010E6B5 /* MGLCircleStyleLayerTests.m */; }; + DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25791D51C5F40010E6B5 /* MGLBackgroundStyleLayerTests.m */; }; DA8933A51CCD287300E68420 /* MGLAnnotationCallout.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA8933A71CCD287300E68420 /* MGLAnnotationCallout.xib */; }; DA8933AE1CCD290700E68420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933AB1CCD290700E68420 /* Localizable.strings */; }; DA8933B51CCD2C2500E68420 /* Foundation.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933B31CCD2C2500E68420 /* Foundation.strings */; }; @@ -249,6 +265,8 @@ 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFilterTests.mm; sourceTree = "<group>"; }; 35D65C581D65AD5500722C23 /* NSDate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+MGLAdditions.h"; sourceTree = "<group>"; }; 35D65C591D65AD5500722C23 /* NSDate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDate+MGLAdditions.mm"; sourceTree = "<group>"; }; + 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection.h; sourceTree = "<group>"; }; + 4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLPointCollection.mm; sourceTree = "<group>"; }; 405C03961DB0004E001AC280 /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSImage+MGLAdditions.h"; sourceTree = "<group>"; }; 405C03971DB0004E001AC280 /* NSImage+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSImage+MGLAdditions.mm"; sourceTree = "<group>"; }; 408AA85A1DAEECF100022900 /* MGLShape_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShape_Private.h; sourceTree = "<group>"; }; @@ -267,6 +285,8 @@ 55D9B4B01D005D3900C1CCE2 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 55FE0E8D1D100A0900FD240B /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/macos/config.xcconfig; sourceTree = "<group>"; }; DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; }; + DA2207BA1DC076930002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = "<group>"; }; + DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLStyleValueTests.swift; sourceTree = "<group>"; }; DA2DBBC71D51E26600D38FF9 /* MGLStyleLayerTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLStyleLayerTests.h; path = ../darwin/test/MGLStyleLayerTests.h; sourceTree = SOURCE_ROOT; }; DA2DBBC81D51E26600D38FF9 /* MGLStyleLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLStyleLayerTests.m; path = ../darwin/test/MGLStyleLayerTests.m; sourceTree = SOURCE_ROOT; }; DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MGLStyleLayerTests.xib; sourceTree = "<group>"; }; @@ -297,6 +317,10 @@ DA839EA11CC2E3400062CAFB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; DA839EA41CC2E3400062CAFB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; }; DA839EA61CC2E3400062CAFB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + DA87A9961DC9D88400810D09 /* MGLGeoJSONSourceTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLGeoJSONSourceTests.mm; sourceTree = "<group>"; }; + DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSetTests.mm; sourceTree = "<group>"; }; + DA87A99B1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLGeoJSONSource_Private.h; sourceTree = "<group>"; }; + DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = "<group>"; }; DA8933A61CCD287300E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MGLAnnotationCallout.xib; sourceTree = "<group>"; }; DA8933AC1CCD290700E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; }; DA8933B41CCD2C2500E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Foundation.strings; sourceTree = "<group>"; }; @@ -496,6 +520,7 @@ DA8F25951D51CAC70010E6B5 /* MGLVectorSource.h */, DA8F25961D51CAC70010E6B5 /* MGLVectorSource.mm */, 352742871D4C245800A1ECE6 /* MGLGeoJSONSource.h */, + DA87A99B1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h */, 352742881D4C245800A1ECE6 /* MGLGeoJSONSource.mm */, 352742831D4C244700A1ECE6 /* MGLRasterSource.h */, 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */, @@ -577,6 +602,15 @@ name = "Supporting Files"; sourceTree = "<group>"; }; + DA87A99A1DC9D88800810D09 /* Sources */ = { + isa = PBXGroup; + children = ( + DA87A9961DC9D88400810D09 /* MGLGeoJSONSourceTests.mm */, + DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */, + ); + name = Sources; + sourceTree = "<group>"; + }; DA8933A81CCD28D100E68420 /* Kit Resources */ = { isa = PBXGroup; children = ( @@ -601,6 +635,7 @@ DA8F257C1D51C5F40010E6B5 /* Layers */ = { isa = PBXGroup; children = ( + DA2207BA1DC076930002F84D /* test-Bridging-Header.h */, DA2DBBC71D51E26600D38FF9 /* MGLStyleLayerTests.h */, DA2DBBC81D51E26600D38FF9 /* MGLStyleLayerTests.m */, DA8F25741D51C5F40010E6B5 /* MGLFillStyleLayerTests.m */, @@ -620,7 +655,9 @@ isa = PBXGroup; children = ( DA8F257C1D51C5F40010E6B5 /* Layers */, + DA87A99A1DC9D88800810D09 /* Sources */, 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */, + DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */, ); name = Styling; path = ../../darwin/test; @@ -665,24 +702,26 @@ isa = PBXGroup; children = ( DAE6C34B1CC31E0400DB3429 /* MGLAnnotation.h */, - DACC22121CF3D3E200D220D9 /* MGLFeature.h */, DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */, + DACC22121CF3D3E200D220D9 /* MGLFeature.h */, DACC22131CF3D3E200D220D9 /* MGLFeature.mm */, - DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */, DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */, + DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */, DAE6C36D1CC31E2A00DB3429 /* MGLGeometry.mm */, - DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */, DAE6C36F1CC31E2A00DB3429 /* MGLMultiPoint_Private.h */, + DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */, DAE6C3701CC31E2A00DB3429 /* MGLMultiPoint.mm */, DAE6C3521CC31E0400DB3429 /* MGLOverlay.h */, DAE6C3531CC31E0400DB3429 /* MGLPointAnnotation.h */, DAE6C3761CC31E2A00DB3429 /* MGLPointAnnotation.mm */, + 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */, + 4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */, DAE6C3541CC31E0400DB3429 /* MGLPolygon.h */, DAE6C3771CC31E2A00DB3429 /* MGLPolygon.mm */, DAE6C3551CC31E0400DB3429 /* MGLPolyline.h */, DAE6C3781CC31E2A00DB3429 /* MGLPolyline.mm */, - DAE6C3561CC31E0400DB3429 /* MGLShape.h */, 408AA85A1DAEECF100022900 /* MGLShape_Private.h */, + DAE6C3561CC31E0400DB3429 /* MGLShape.h */, DAE6C3791CC31E2A00DB3429 /* MGLShape.mm */, DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */, DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.m */, @@ -813,6 +852,7 @@ DAE6C37A1CC31E2A00DB3429 /* MGLStyle.mm */, DAE6C3591CC31E0400DB3429 /* MGLTypes.h */, DAE6C37C1CC31E2A00DB3429 /* MGLTypes.m */, + DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */, ); name = Foundation; path = ../darwin/src; @@ -889,6 +929,7 @@ DAE6C3691CC31E0400DB3429 /* MGLTypes.h in Headers */, DAE6C3991CC31E2A00DB3429 /* NSException+MGLAdditions.h in Headers */, DA8F25871D51C9E10010E6B5 /* MGLBackgroundStyleLayer.h in Headers */, + 4049C2A51DB6CE7F00B3F799 /* MGLPointCollection.h in Headers */, 30E5781B1DAA857E0050F07E /* NSImage+MGLAdditions.h in Headers */, DAE6C3661CC31E0400DB3429 /* MGLShape.h in Headers */, DA551B831DB496AC0009AFAF /* MGLTileSet_Private.h in Headers */, @@ -907,6 +948,7 @@ DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */, DAE6C38E1CC31E2A00DB3429 /* MGLOfflineStorage_Private.h in Headers */, 408AA8661DAEEE3600022900 /* MGLPolyline+MGLAdditions.h in Headers */, + DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */, DAE6C3601CC31E0400DB3429 /* MGLOfflineRegion.h in Headers */, DAE6C3681CC31E0400DB3429 /* MGLTilePyramidOfflineRegion.h in Headers */, DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */, @@ -920,6 +962,7 @@ 35602C001D3EA9B40050646F /* MGLForegroundStyleLayer.h in Headers */, DAE6C35D1CC31E0400DB3429 /* MGLMapCamera.h in Headers */, DAE6C3B41CC31EF300DB3429 /* MGLCompassCell.h in Headers */, + DA87A99C1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h in Headers */, 3537CA741D3F93A600380318 /* MGLStyle_Private.h in Headers */, DA8F259A1D51CAD00010E6B5 /* MGLSource_Private.h in Headers */, DA8F25931D51CA750010E6B5 /* MGLSymbolStyleLayer.h in Headers */, @@ -1034,6 +1077,7 @@ }; DAE6C3301CC30DB200DB3429 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; }; }; }; @@ -1146,6 +1190,7 @@ DAE6C3BA1CC31EF300DB3429 /* MGLOpenGLLayer.mm in Sources */, DAE6C38A1CC31E2A00DB3429 /* MGLMultiPoint.mm in Sources */, DAE6C3961CC31E2A00DB3429 /* MGLTypes.m in Sources */, + 4049C2AD1DB8020600B3F799 /* MGLPointCollection.mm in Sources */, DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */, 352742821D4C243B00A1ECE6 /* MGLSource.mm in Sources */, DAE6C3881CC31E2A00DB3429 /* MGLMapCamera.mm in Sources */, @@ -1181,14 +1226,26 @@ files = ( DA35A2C21CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m in Sources */, DAE6C3D41CC34C9900DB3429 /* MGLOfflineRegionTests.m in Sources */, + DA87A9A11DC9DCB400810D09 /* MGLRuntimeStylingHelper.m in Sources */, DAE6C3D61CC34C9900DB3429 /* MGLStyleTests.mm in Sources */, DA35A2B61CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */, DAE6C3D21CC34C9900DB3429 /* MGLGeometryTests.mm in Sources */, + DA87A9A41DCACC5000810D09 /* MGLSymbolStyleLayerTests.m in Sources */, DAE6C3D51CC34C9900DB3429 /* MGLOfflineStorageTests.m in Sources */, + DA87A9A61DCACC5000810D09 /* MGLCircleStyleLayerTests.m in Sources */, + DA87A99D1DC9DB2E00810D09 /* MGLStyleLayerTests.m in Sources */, + DA87A99E1DC9DC2100810D09 /* MGLFilterTests.mm in Sources */, DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */, + DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.m in Sources */, DAE6C3D31CC34C9900DB3429 /* MGLOfflinePackTests.m in Sources */, + DA87A9A51DCACC5000810D09 /* MGLLineStyleLayerTests.m in Sources */, + DA87A9A31DCACC5000810D09 /* MGLRasterStyleLayerTests.m in Sources */, + DA87A9991DC9D88400810D09 /* MGLTileSetTests.mm in Sources */, DA35A2A81CC9F41600E826B2 /* MGLCoordinateFormatterTests.m in Sources */, + DA87A9981DC9D88400810D09 /* MGLGeoJSONSourceTests.mm in Sources */, + DA87A9A21DC9DCF100810D09 /* MGLFillStyleLayerTests.m in Sources */, DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */, + DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1457,6 +1514,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 55FE0E8D1D100A0900FD240B /* config.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; INFOPLIST_FILE = test/Info.plist; @@ -1469,6 +1527,9 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "../darwin/test/test-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -1476,6 +1537,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 55FE0E8D1D100A0900FD240B /* config.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; INFOPLIST_FILE = test/Info.plist; @@ -1488,6 +1550,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "../darwin/test/test-Bridging-Header.h"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h index 3499671ff1..3dbbbe3d82 100644 --- a/platform/macos/src/MGLMapView.h +++ b/platform/macos/src/MGLMapView.h @@ -569,6 +569,16 @@ IB_DESIGNABLE - (void)addAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations; /** + The complete list of annotations associated with the receiver that are + currently visible. + + The objects in this array must adopt the `MGLAnnotation` protocol. If no + annotations are associated with the map view or if no annotations associated + with the map view are currently visible, the value of this property is `nil`. + */ +@property (nonatomic, readonly, nullable) NS_ARRAY_OF(id <MGLAnnotation>) *visibleAnnotations; + +/** Removes an annotation from the map view, deselecting it if it is selected. Removing an annotation object dissociates it from the map view entirely, @@ -608,6 +618,17 @@ IB_DESIGNABLE */ - (nullable MGLAnnotationImage *)dequeueReusableAnnotationImageWithIdentifier:(NSString *)identifier; +/** + Returns the list of annotations associated with the receiver that intersect with + the given rectangle. + + @param rect A rectangle expressed in the map view’s coordinate system. + @return An array of objects that adopt the `MGLAnnotation` protocol or `nil` if + no annotations associated with the map view are currently visible in the + rectangle. + */ +- (nullable NS_ARRAY_OF(id <MGLAnnotation>) *)visibleAnnotationsInRect:(CGRect)rect; + #pragma mark Managing Annotation Selections /** diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 45208408fe..02f96ac3ff 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -108,7 +108,7 @@ enum { MGLAnnotationTagNotFound = UINT32_MAX }; /// Mapping from an annotation tag to metadata about that annotation, including /// the annotation itself. -typedef std::unordered_map<MGLAnnotationTag, MGLAnnotationContext> MGLAnnotationContextMap; +typedef std::unordered_map<MGLAnnotationTag, MGLAnnotationContext> MGLAnnotationTagContextMap; /// Returns an NSImage for the default marker image. NSImage *MGLDefaultMarkerImage() { @@ -171,7 +171,7 @@ public: CGFloat _pitchAtBeginningOfGesture; BOOL _didHideCursorDuringGesture; - MGLAnnotationContextMap _annotationContextsByAnnotationTag; + MGLAnnotationTagContextMap _annotationContextsByAnnotationTag; MGLAnnotationTag _selectedAnnotationTag; MGLAnnotationTag _lastSelectedAnnotationTag; /// Size of the rectangle formed by unioning the maximum slop area around every annotation image. @@ -1623,6 +1623,35 @@ public: return [NSArray arrayWithObjects:&annotations[0] count:annotations.size()]; } +- (nullable NS_ARRAY_OF(id <MGLAnnotation>) *)visibleAnnotations +{ + return [self visibleFeaturesInRect:self.bounds]; +} + +- (nullable NS_ARRAY_OF(id <MGLAnnotation>) *)visibleAnnotationsInRect:(CGRect)rect +{ + if (_annotationContextsByAnnotationTag.empty()) + { + return nil; + } + + std::vector<MGLAnnotationTag> annotationTags = [self annotationTagsInRect:rect]; + if (annotationTags.size()) + { + NSMutableArray *annotations = [NSMutableArray arrayWithCapacity:annotationTags.size()]; + + for (auto const& annotationTag: annotationTags) + { + MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag]; + [annotations addObject:annotationContext.annotation]; + } + + return [annotations copy]; + } + + return nil; +} + /// Returns the annotation assigned the given tag. Cheap. - (id <MGLAnnotation>)annotationWithTag:(MGLAnnotationTag)tag { if (!_annotationContextsByAnnotationTag.count(tag)) { @@ -1666,12 +1695,6 @@ public: NSAssert([annotation conformsToProtocol:@protocol(MGLAnnotation)], @"Annotation does not conform to MGLAnnotation"); if ([annotation isKindOfClass:[MGLMultiPoint class]]) { - // Actual multipoints aren’t supported as annotations. - if ([annotation isMemberOfClass:[MGLMultiPoint class]] - || [annotation isMemberOfClass:[MGLMultiPointFeature class]]) { - continue; - } - // The multipoint knows how to style itself (with the map view’s help). MGLMultiPoint *multiPoint = (MGLMultiPoint *)annotation; if (!multiPoint.pointCount) { @@ -1685,8 +1708,9 @@ public: [(NSObject *)annotation addObserver:self forKeyPath:@"coordinates" options:0 context:(void *)(NSUInteger)annotationTag]; } else if (![annotation isKindOfClass:[MGLMultiPolyline class]] - || ![annotation isKindOfClass:[MGLMultiPolygon class]] - || ![annotation isKindOfClass:[MGLShapeCollection class]]) { + && ![annotation isKindOfClass:[MGLMultiPolygon class]] + && ![annotation isKindOfClass:[MGLShapeCollection class]] + && ![annotation isKindOfClass:[MGLPointCollection class]]) { MGLAnnotationImage *annotationImage = nil; if (delegateHasImagesForAnnotations) { annotationImage = [self.delegate mapView:self imageForAnnotation:annotation]; diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h index 67e3775100..cfddfe6e89 100644 --- a/platform/macos/src/Mapbox.h +++ b/platform/macos/src/Mapbox.h @@ -24,6 +24,7 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[]; #import "MGLOfflineStorage.h" #import "MGLOverlay.h" #import "MGLPointAnnotation.h" +#import "MGLPointCollection.h" #import "MGLPolygon.h" #import "MGLPolyline.h" #import "MGLShape.h" diff --git a/platform/macos/src/NSColor+MGLAdditions.mm b/platform/macos/src/NSColor+MGLAdditions.mm index e347fd1798..2a55af5cad 100644 --- a/platform/macos/src/NSColor+MGLAdditions.mm +++ b/platform/macos/src/NSColor+MGLAdditions.mm @@ -13,7 +13,7 @@ + (NSColor *)mgl_colorWithColor:(mbgl::Color)color { - return [NSColor colorWithRed:color.r green:color.g blue:color.b alpha:color.a]; + return [NSColor colorWithCalibratedRed:color.r green:color.g blue:color.b alpha:color.a]; } - (mbgl::style::PropertyValue<mbgl::Color>)mgl_colorPropertyValue |