[core, darwin] Object identity for MGLSource*, MGLStyleLayer*

All `MGLSource` pointers referencing the same logical source will now be object identical; similarly for `MGLStyleLayer`.
This commit is contained in:
John Firebaugh
2017-04-04 11:33:22 -07:00
parent de6c9b35f3
commit 7b041b123c
12 changed files with 66 additions and 20 deletions

View File

@@ -40,6 +40,7 @@ set_source_files_properties(src/mbgl/util/version.cpp PROPERTIES COMPILE_DEFINIT
mason_use(geometry VERSION 0.9.0 HEADER_ONLY)
mason_use(variant VERSION 1.1.4 HEADER_ONLY)
mason_use(any VERSION 8fef1e9 HEADER_ONLY)
mason_use(unique_resource VERSION cba309e HEADER_ONLY)
mason_use(rapidjson VERSION 1.1.0 HEADER_ONLY)
mason_use(boost VERSION 1.62.0 HEADER_ONLY)

View File

@@ -14,6 +14,7 @@ target_include_directories(mbgl-core
target_add_mason_package(mbgl-core PUBLIC geometry)
target_add_mason_package(mbgl-core PUBLIC variant)
target_add_mason_package(mbgl-core PUBLIC any)
target_add_mason_package(mbgl-core PRIVATE unique_resource)
target_add_mason_package(mbgl-core PRIVATE rapidjson)
target_add_mason_package(mbgl-core PRIVATE boost)

View File

@@ -27,6 +27,7 @@ target_link_libraries(mbgl-test
target_add_mason_package(mbgl-test PRIVATE geometry)
target_add_mason_package(mbgl-test PRIVATE variant)
target_add_mason_package(mbgl-test PRIVATE any)
target_add_mason_package(mbgl-test PRIVATE unique_resource)
target_add_mason_package(mbgl-test PRIVATE rapidjson)
target_add_mason_package(mbgl-test PRIVATE gtest)

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/any.hpp>
#include <mbgl/style/types.hpp>
#include <memory>
@@ -118,6 +119,11 @@ public:
// Private implementation
const std::unique_ptr<Impl> baseImpl;
// For use in SDK bindings, which store a reference to a platform-native peer
// object here, so that separately-obtained references to this object share
// identical platform-native peers.
any peer;
friend std::string layoutKey(const Layer&);
};

View File

@@ -4,6 +4,7 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/range.hpp>
#include <mbgl/util/any.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/style/query.hpp>
@@ -64,6 +65,11 @@ public:
class Impl;
const std::unique_ptr<Impl> baseImpl;
// For use in SDK bindings, which store a reference to a platform-native peer
// object here, so that separately-obtained references to this object share
// identical platform-native peers.
any peer;
protected:
const SourceType type;
Source(SourceType, std::unique_ptr<Impl>);

10
include/mbgl/util/any.hpp Normal file
View File

@@ -0,0 +1,10 @@
#pragma once
#include <linb/any.hpp>
namespace mbgl {
using linb::any;
using linb::any_cast;
} // namespace mbgl

View File

@@ -29,6 +29,7 @@
NSString *identifier = @(rawSource->getID().c_str());
if (self = [self initWithIdentifier:identifier]) {
_rawSource = rawSource;
_rawSource->peer = SourceWrapper { self };
}
return self;
}

View File

@@ -10,6 +10,14 @@ namespace mbgl {
}
}
// A struct to be stored in the `peer` member of mbgl::style::Source, in order to implement
// object identity. We don't store a MGLSource pointer directly because that doesn't
// interoperate with ARC. The inner pointer is weak in order to avoid a reference cycle for
// "pending" MGLSources, which have a strong owning pointer to the mbgl::style::Source.
struct SourceWrapper {
__weak MGLSource *source;
};
@class MGLMapView;
@interface MGLSource (Private)

View File

@@ -166,17 +166,21 @@ static NSURL *MGLStyleURL_emerald;
return rawSource ? [self sourceFromMBGLSource:rawSource] : nil;
}
- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)source {
- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)rawSource {
if (MGLSource *source = rawSource->peer.empty() ? nil : mbgl::any_cast<SourceWrapper>(rawSource->peer).source) {
return source;
}
// TODO: Fill in options specific to the respective source classes
// https://github.com/mapbox/mapbox-gl-native/issues/6584
if (auto vectorSource = source->as<mbgl::style::VectorSource>()) {
if (auto vectorSource = rawSource->as<mbgl::style::VectorSource>()) {
return [[MGLVectorSource alloc] initWithRawSource:vectorSource];
} else if (auto geoJSONSource = source->as<mbgl::style::GeoJSONSource>()) {
} else if (auto geoJSONSource = rawSource->as<mbgl::style::GeoJSONSource>()) {
return [[MGLShapeSource alloc] initWithRawSource:geoJSONSource];
} else if (auto rasterSource = source->as<mbgl::style::RasterSource>()) {
} else if (auto rasterSource = rawSource->as<mbgl::style::RasterSource>()) {
return [[MGLRasterSource alloc] initWithRawSource:rasterSource];
} else {
return [[MGLSource alloc] initWithRawSource:source];
return [[MGLSource alloc] initWithRawSource:rawSource];
}
}
@@ -319,35 +323,32 @@ static NSURL *MGLStyleURL_emerald;
[styleLayer removeFromMapView:self.mapView];
}
- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)mbglLayer
- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)rawLayer
{
NSParameterAssert(mbglLayer);
NSParameterAssert(rawLayer);
NSString *identifier = @(mbglLayer->getID().c_str());
if (MGLStyleLayer *layer = rawLayer->peer.empty() ? nil : mbgl::any_cast<LayerWrapper>(rawLayer->peer).layer) {
return layer;
}
if (auto fillLayer = mbglLayer->as<mbgl::style::FillLayer>()) {
if (auto fillLayer = rawLayer->as<mbgl::style::FillLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(fillLayer->getSourceID().c_str())];
return [[MGLFillStyleLayer alloc] initWithRawLayer:fillLayer source:source];
} else if (auto lineLayer = mbglLayer->as<mbgl::style::LineLayer>()) {
} else if (auto lineLayer = rawLayer->as<mbgl::style::LineLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(lineLayer->getSourceID().c_str())];
return [[MGLLineStyleLayer alloc] initWithRawLayer:lineLayer source:source];
} else if (auto symbolLayer = mbglLayer->as<mbgl::style::SymbolLayer>()) {
} else if (auto symbolLayer = rawLayer->as<mbgl::style::SymbolLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(symbolLayer->getSourceID().c_str())];
return [[MGLSymbolStyleLayer alloc] initWithRawLayer:symbolLayer source:source];
} else if (auto rasterLayer = mbglLayer->as<mbgl::style::RasterLayer>()) {
} else if (auto rasterLayer = rawLayer->as<mbgl::style::RasterLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(rasterLayer->getSourceID().c_str())];
return [[MGLRasterStyleLayer alloc] initWithRawLayer:rasterLayer source:source];
} else if (auto circleLayer = mbglLayer->as<mbgl::style::CircleLayer>()) {
} else if (auto circleLayer = rawLayer->as<mbgl::style::CircleLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(circleLayer->getSourceID().c_str())];
return [[MGLCircleStyleLayer alloc] initWithRawLayer:circleLayer source:source];
} else if (auto backgroundLayer = mbglLayer->as<mbgl::style::BackgroundLayer>()) {
} else if (auto backgroundLayer = rawLayer->as<mbgl::style::BackgroundLayer>()) {
return [[MGLBackgroundStyleLayer alloc] initWithRawLayer:backgroundLayer];
} else if (auto customLayer = mbglLayer->as<mbgl::style::CustomLayer>()) {
MGLStyleLayer *styleLayer = self.openGLLayers[identifier];
if (styleLayer) {
NSAssert(styleLayer.rawLayer == customLayer, @"%@ wraps a CustomLayer that differs from the one associated with the underlying style.", styleLayer);
return styleLayer;
}
} else if (auto customLayer = rawLayer->as<mbgl::style::CustomLayer>()) {
return [[MGLOpenGLStyleLayer alloc] initWithRawLayer:customLayer];
} else {
NSAssert(NO, @"Unrecognized layer type");

View File

@@ -18,6 +18,7 @@
if (self = [super init]) {
_identifier = @(rawLayer->getID().c_str());
_rawLayer = rawLayer;
_rawLayer->peer = LayerWrapper { self };
}
return self;
}

View File

@@ -7,6 +7,14 @@
NS_ASSUME_NONNULL_BEGIN
// A struct to be stored in the `peer` member of mbgl::style::Layer, in order to implement
// object identity. We don't store a MGLStyleLayer pointer directly because that doesn't
// interoperate with ARC. The inner pointer is weak in order to avoid a reference cycle for
// "pending" MGLStyleLayers, which have a strong owning pointer to the mbgl::style::Layer.
struct LayerWrapper {
__weak MGLStyleLayer *layer;
};
/**
Assert that the style layer is valid.

View File

@@ -148,6 +148,7 @@
MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"shapeSource" shape:nil options:nil];
[self.style addSource:shapeSource];
XCTAssertEqual(self.style.sources.count, initialSources.count + 1);
XCTAssertEqual(shapeSource, [self.style sourceWithIdentifier:@"shapeSource"]);
[self.style removeSource:shapeSource];
XCTAssertEqual(self.style.sources.count, initialSources.count);
}
@@ -238,6 +239,7 @@
MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fillLayer" source:shapeSource];
[self.style addLayer:fillLayer];
XCTAssertEqual(self.style.layers.count, initialLayers.count + 1);
XCTAssertEqual(fillLayer, [self.style layerWithIdentifier:@"fillLayer"]);
[self.style removeLayer:fillLayer];
XCTAssertEqual(self.style.layers.count, initialLayers.count);
}