summaryrefslogtreecommitdiff
path: root/platform/darwin/src
diff options
context:
space:
mode:
authorJesse Bounds <jesse@rebounds.net>2016-10-26 17:08:27 -0700
committerGitHub <noreply@github.com>2016-10-26 17:08:27 -0700
commit67ffc9685e573b10e4761b0bdb9962c79139f5da (patch)
tree89215ac8c3bc212ea3cf4e569d48d10e999590e2 /platform/darwin/src
parent12093c10ad7557a92c8852bd6b61428990311dd4 (diff)
downloadqtlocation-mapboxgl-67ffc9685e573b10e4761b0bdb9962c79139f5da.tar.gz
[ios, macos] Make source ownership consistent and GeoJSON content properties writable
Use common initialization logic to create an unique pointer to an mbgl source object, up front, when a MGL source is created. Keep a raw pointer to the unique pointer that is pointed at the mbgl source instance when a MGL source is created or when a MGL source is obtained by identifier from MGLStyle. Once the transfer of ownership of the mbgl source takes place, the unique ptr is null. The raw pointer can be used internally for future work that involves mutating the source. This also changes the URL, features, and geoJSONData content properties for MGLGeoJSON source to be writable. If they are set with valid data after a source has been added to the map then the map will update to reflect the new data.
Diffstat (limited to 'platform/darwin/src')
-rw-r--r--platform/darwin/src/MGLGeoJSONSource.h6
-rw-r--r--platform/darwin/src/MGLGeoJSONSource.mm105
-rw-r--r--platform/darwin/src/MGLGeoJSONSource_Private.h1
-rw-r--r--platform/darwin/src/MGLRasterSource.mm23
-rw-r--r--platform/darwin/src/MGLSource.mm17
-rw-r--r--platform/darwin/src/MGLSource_Private.h23
-rw-r--r--platform/darwin/src/MGLStyle.mm12
-rw-r--r--platform/darwin/src/MGLVectorSource.mm22
8 files changed, 160 insertions, 49 deletions
diff --git a/platform/darwin/src/MGLGeoJSONSource.h b/platform/darwin/src/MGLGeoJSONSource.h
index 9eeb1e1188..d0c1e0dc67 100644
--- a/platform/darwin/src/MGLGeoJSONSource.h
+++ b/platform/darwin/src/MGLGeoJSONSource.h
@@ -109,7 +109,7 @@ 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.
@@ -123,7 +123,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 +131,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..3efcd59ae2 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,6 +8,7 @@
#include <mbgl/style/sources/geojson_source.hpp>
+
NSString * const MGLGeoJSONClusterOption = @"MGLGeoJSONCluster";
NSString * const MGLGeoJSONClusterRadiusOption = @"MGLGeoJSONClusterRadius";
NSString * const MGLGeoJSONClusterMaximumZoomLevelOption = @"MGLGeoJSONClusterMaximumZoomLevel";
@@ -17,10 +19,14 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance
@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 +34,7 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance
{
_geoJSONData = data;
_options = options;
+ [self commonInit];
}
return self;
}
@@ -38,6 +45,7 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance
{
_URL = url;
_options = options;
+ [self commonInit];
}
return self;
}
@@ -46,11 +54,45 @@ 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();
@@ -102,30 +144,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/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/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