[core, ios, macos] SDK objects should hold weak pointers to the core style objects (#15539)

This commit is contained in:
Mikhail Pozdnyakov
2019-09-10 06:55:38 +03:00
committed by Julian Rex
parent 45140af7cb
commit 5207a36074
35 changed files with 316 additions and 70 deletions

View File

@@ -6,6 +6,8 @@
#include <mbgl/style/types.hpp>
#include <mbgl/style/conversion.hpp>
#include <mapbox/weak.hpp>
#include <cassert>
#include <memory>
#include <string>
@@ -124,10 +126,15 @@ public:
const LayerTypeInfo* getTypeInfo() const noexcept;
mapbox::base::WeakPtr<Layer> makeWeakPtr() {
return weakFactory.makeWeakPtr();
}
protected:
virtual Mutable<Impl> mutableBaseImpl() const = 0;
LayerObserver* observer;
mapbox::base::WeakPtrFactory<Layer> weakFactory {this};
};
} // namespace style

View File

@@ -6,6 +6,8 @@
#include <mbgl/util/immutable.hpp>
#include <mbgl/style/types.hpp>
#include <mapbox/weak.hpp>
#include <memory>
#include <string>
@@ -78,6 +80,8 @@ public:
// object here, so that separately-obtained references to this object share
// identical platform-native peers.
util::peer peer;
virtual mapbox::base::WeakPtr<Source> makeWeakPtr() = 0;
};
} // namespace style

View File

@@ -20,7 +20,7 @@ using TileFunction = std::function<void(const CanonicalTileID&)>;
class CustomTileLoader;
class CustomGeometrySource : public Source {
class CustomGeometrySource final : public Source {
public:
struct TileOptions {
double tolerance = 0.375;
@@ -46,9 +46,13 @@ public:
// Private implementation
class Impl;
const Impl& impl() const;
mapbox::base::WeakPtr<Source> makeWeakPtr() override {
return weakFactory.makeWeakPtr();
}
private:
std::shared_ptr<ThreadPool> threadPool;
std::unique_ptr<Actor<CustomTileLoader>> loader;
mapbox::base::WeakPtrFactory<Source> weakFactory {this};
};
template <>

View File

@@ -35,7 +35,7 @@ struct GeoJSONOptions {
ClusterProperties clusterProperties;
};
class GeoJSONSource : public Source {
class GeoJSONSource final : public Source {
public:
GeoJSONSource(const std::string& id, optional<GeoJSONOptions> = nullopt);
~GeoJSONSource() final;
@@ -50,9 +50,14 @@ public:
void loadDescription(FileSource&) final;
mapbox::base::WeakPtr<Source> makeWeakPtr() override {
return weakFactory.makeWeakPtr();
}
private:
optional<std::string> url;
std::unique_ptr<AsyncRequest> req;
mapbox::base::WeakPtrFactory<Source> weakFactory {this};
};
template <>

View File

@@ -10,7 +10,7 @@ class AsyncRequest;
namespace style {
class ImageSource : public Source {
class ImageSource final : public Source {
public:
ImageSource(std::string id, const std::array<LatLng, 4>);
~ImageSource() override;
@@ -27,9 +27,14 @@ public:
const Impl& impl() const;
void loadDescription(FileSource&) final;
mapbox::base::WeakPtr<Source> makeWeakPtr() override {
return weakFactory.makeWeakPtr();
}
private:
optional<std::string> url;
std::unique_ptr<AsyncRequest> req;
mapbox::base::WeakPtrFactory<Source> weakFactory {this};
};
template <>

View File

@@ -25,9 +25,14 @@ public:
void loadDescription(FileSource&) final;
mapbox::base::WeakPtr<Source> makeWeakPtr() final {
return weakFactory.makeWeakPtr();
}
private:
const variant<std::string, Tileset> urlOrTileset;
std::unique_ptr<AsyncRequest> req;
mapbox::base::WeakPtrFactory<Source> weakFactory {this};
};
template <>

View File

@@ -10,7 +10,7 @@ class AsyncRequest;
namespace style {
class VectorSource : public Source {
class VectorSource final : public Source {
public:
VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset);
~VectorSource() final;
@@ -23,9 +23,14 @@ public:
void loadDescription(FileSource&) final;
mapbox::base::WeakPtr<Source> makeWeakPtr() override {
return weakFactory.makeWeakPtr();
}
private:
const variant<std::string, Tileset> urlOrTileset;
std::unique_ptr<AsyncRequest> req;
mapbox::base::WeakPtrFactory<Source> weakFactory {this};
};
template <>

View File

@@ -199,6 +199,7 @@ mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDi
}
- (void)setFeatures:(NSArray<MGLShape <MGLFeature> *>*)features inTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)zoomLevel {
MGLAssertStyleSourceIsValid();
mbgl::CanonicalTileID tileID = mbgl::CanonicalTileID((uint8_t)zoomLevel, (uint32_t)x, (uint32_t)y);
mbgl::FeatureCollection featureCollection;
featureCollection.reserve(features.count);
@@ -236,10 +237,12 @@ mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDi
}
- (void) invalidateBounds:(MGLCoordinateBounds)bounds {
MGLAssertStyleSourceIsValid();
((mbgl::style::CustomGeometrySource *)self.rawSource)->invalidateRegion(MGLLatLngBoundsFromCoordinateBounds(bounds));
}
- (void) invalidateTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)z {
MGLAssertStyleSourceIsValid();
((mbgl::style::CustomGeometrySource *)self.rawSource)->invalidateTile(mbgl::CanonicalTileID(z, (unsigned int)x, (unsigned int)y));
}

View File

@@ -1,4 +1,5 @@
#import "MGLForegroundStyleLayer.h"
#import "MGLStyleLayer_Private.h"
@implementation MGLForegroundStyleLayer
@@ -9,10 +10,17 @@
}
- (NSString *)description {
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; sourceIdentifier = %@; visible = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
self.sourceIdentifier, self.visible ? @"YES" : @"NO"];
if (self.rawLayer) {
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; sourceIdentifier = %@; visible = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
self.sourceIdentifier, self.visible ? @"YES" : @"NO"];
}
else {
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; sourceIdentifier = <unknown>; visible = NO>",
NSStringFromClass([self class]), (void *)self, self.identifier];
}
}
@end

View File

@@ -45,11 +45,13 @@
}
- (NSURL *)URL {
MGLAssertStyleSourceIsValid();
auto url = self.rawSource->getURL();
return url ? [NSURL URLWithString:@(url->c_str())] : nil;
}
- (void)setURL:(NSURL *)url {
MGLAssertStyleSourceIsValid();
if (url) {
self.rawSource->setURL(url.mgl_URLByStandardizingScheme.absoluteString.UTF8String);
_image = nil;
@@ -59,6 +61,7 @@
}
- (void)setImage:(MGLImage *)image {
MGLAssertStyleSourceIsValid();
if (image != nullptr) {
self.rawSource->setImage(image.mgl_premultipliedImage);
} else {
@@ -68,16 +71,27 @@
}
- (MGLCoordinateQuad)coordinates {
MGLAssertStyleSourceIsValid();
return MGLCoordinateQuadFromLatLngArray(self.rawSource->getCoordinates());
}
- (void)setCoordinates: (MGLCoordinateQuad)coordinateQuad {
MGLAssertStyleSourceIsValid();
self.rawSource->setCoordinates(MGLLatLngArrayFromCoordinateQuad(coordinateQuad));
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; coordinates = %@; URL = %@; image = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, MGLStringFromCoordinateQuad(self.coordinates), self.URL, self.image];
if (self.rawSource) {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; coordinates = %@; URL = %@; image = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
MGLStringFromCoordinateQuad(self.coordinates),
self.URL,
self.image];
}
else {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; coordinates = <unknown>; URL = <unknown>; image = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.image];
}
}
- (mbgl::style::ImageSource *)rawSource {
@@ -85,6 +99,7 @@
}
- (NSString *)attributionHTMLString {
MGLAssertStyleSourceIsValid();
auto attribution = self.rawSource->getAttribution();
return attribution ? @(attribution->c_str()) : nil;
}

View File

@@ -65,11 +65,13 @@ static const CGFloat MGLRasterTileSourceRetinaTileSize = 512;
}
- (NSURL *)configurationURL {
MGLAssertStyleSourceIsValid();
auto url = self.rawSource->getURL();
return url ? [NSURL URLWithString:@(url->c_str())] : nil;
}
- (NSString *)attributionHTMLString {
MGLAssertStyleSourceIsValid();
auto attribution = self.rawSource->getAttribution();
return attribution ? @(attribution->c_str()) : nil;
}

View File

@@ -12,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface MGLRasterTileSource (Private)
@property (nonatomic, readonly) mbgl::style::RasterSource *rawSource;
@property (nonatomic, readonly, nullable) mbgl::style::RasterSource *rawSource;
- (std::unique_ptr<mbgl::style::RasterSource>)pendingSourceWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL tileSize:(CGFloat)tileSize;

View File

@@ -150,11 +150,13 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary<MGLShap
}
- (NSURL *)URL {
MGLAssertStyleSourceIsValid();
auto url = self.rawSource->getURL();
return url ? [NSURL URLWithString:@(url->c_str())] : nil;
}
- (void)setURL:(NSURL *)url {
MGLAssertStyleSourceIsValid();
if (url) {
self.rawSource->setURL(url.mgl_URLByStandardizingScheme.absoluteString.UTF8String);
_shape = nil;
@@ -164,17 +166,24 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary<MGLShap
}
- (void)setShape:(MGLShape *)shape {
MGLAssertStyleSourceIsValid();
self.rawSource->setGeoJSON({ shape.geoJSONObject });
_shape = shape;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; shape = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.shape];
if (self.rawSource) {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; shape = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.shape];
}
else {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = <unknown>; shape = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.shape];
}
}
- (NSArray<id <MGLFeature>> *)featuresMatchingPredicate:(nullable NSPredicate *)predicate {
MGLAssertStyleSourceIsValid();
mbgl::optional<mbgl::style::Filter> optionalFilter;
if (predicate) {
optionalFilter = predicate.mgl_filter;
@@ -190,6 +199,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary<MGLShap
#pragma mark - MGLCluster management
- (mbgl::optional<mbgl::FeatureExtensionValue>)featureExtensionValueOfCluster:(MGLShape<MGLCluster> *)cluster extension:(std::string)extension options:(const std::map<std::string, mbgl::Value>)options {
MGLAssertStyleSourceIsValid();
mbgl::optional<mbgl::FeatureExtensionValue> extensionValue;
// Check parameters

View File

@@ -1,9 +1,12 @@
#import <Foundation/Foundation.h>
#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
FOUNDATION_EXTERN MGL_EXPORT MGLExceptionName const MGLInvalidStyleSourceException;
/**
`MGLSource` is an abstract base class for map content sources. A map content
source supplies content to be shown on the map. A source is added to an

View File

@@ -7,6 +7,8 @@
#include <mbgl/map/map.hpp>
#include <mbgl/style/source.hpp>
const MGLExceptionName MGLInvalidStyleSourceException = @"MGLInvalidStyleSourceException";
@interface MGLSource ()
// Even though this class is abstract, MGLStyle uses it to represent some
@@ -19,13 +21,14 @@
@implementation MGLSource {
std::unique_ptr<mbgl::style::Source> _pendingSource;
mapbox::base::WeakPtr<mbgl::style::Source> _weakSource;
}
- (instancetype)initWithIdentifier:(NSString *)identifier
{
if (self = [super init]) {
_identifier = identifier;
_identifier = [identifier copy];
}
return self;
}
@@ -33,13 +36,18 @@
- (instancetype)initWithRawSource:(mbgl::style::Source *)rawSource mapView:(MGLMapView *)mapView {
NSString *identifier = @(rawSource->getID().c_str());
if (self = [self initWithIdentifier:identifier]) {
_rawSource = rawSource;
_rawSource->peer = SourceWrapper { self };
_weakSource = rawSource->makeWeakPtr();
rawSource->peer = SourceWrapper { self };
_mapView = mapView;
}
return self;
}
- (mbgl::style::Source *)rawSource
{
return _weakSource.get();
}
- (instancetype)initWithPendingSource:(std::unique_ptr<mbgl::style::Source>)pendingSource {
if (self = [self initWithRawSource:pendingSource.get() mapView:nil]) {
_pendingSource = std::move(pendingSource);
@@ -59,6 +67,7 @@
}
- (BOOL)removeFromMapView:(MGLMapView *)mapView error:(NSError * __nullable * __nullable)outError {
MGLAssertStyleSourceIsValid();
BOOL removed = NO;
if (self.rawSource == mapView.style.rawStyle->getSource(self.identifier.UTF8String)) {

View File

@@ -2,6 +2,7 @@
#include <memory>
NS_ASSUME_NONNULL_BEGIN
namespace mbgl {
@@ -18,6 +19,20 @@ struct SourceWrapper {
__weak MGLSource *source;
};
/**
Assert that the style source is valid.
This macro should be used at the beginning of any public-facing instance method
of `MGLSource` and its subclasses. For private methods, an assertion is more appropriate.
*/
#define MGLAssertStyleSourceIsValid() \
do { \
if (!self.rawSource) { \
[NSException raise:MGLInvalidStyleSourceException \
format:@"This source got invalidated after the style change"]; \
} \
} while (NO);
@class MGLMapView;
@interface MGLSource (Private)

View File

@@ -226,12 +226,23 @@ static_assert(6 == mbgl::util::default_styles::numOrderedStyles,
MGLLogDebug(@"Removing source: %@", source);
if (!source.rawSource) {
[NSException raise:NSInvalidArgumentException format:
@"The source %@ cannot be removed from the style. "
@"Make sure the source was created as a member of a concrete subclass of MGLSource.",
source];
NSString *errorMessage = [NSString stringWithFormat:
@"The source %@ cannot be removed from the style. "
@"Make sure the source was created as a member of a concrete subclass of MGLSource."
@"Automatic re-addition of sources after style changes is not currently supported.",
source];
if (outError) {
*outError = [NSError errorWithDomain:MGLErrorDomain
code:MGLErrorCodeSourceCannotBeRemovedFromStyle
userInfo:@{ NSLocalizedDescriptionKey : errorMessage }];
return NO;
}
else {
[NSException raise:NSInvalidArgumentException format:@"%@", errorMessage];
}
}
return [source removeFromMapView:self.mapView error:outError];
}

View File

@@ -14,13 +14,14 @@ const MGLExceptionName MGLInvalidStyleLayerException = @"MGLInvalidStyleLayerExc
@implementation MGLStyleLayer {
std::unique_ptr<mbgl::style::Layer> _pendingLayer;
mapbox::base::WeakPtr<mbgl::style::Layer> _weakLayer;
}
- (instancetype)initWithRawLayer:(mbgl::style::Layer *)rawLayer {
if (self = [super init]) {
_identifier = @(rawLayer->getID().c_str());
_rawLayer = rawLayer;
_rawLayer->peer = LayerWrapper { self };
_weakLayer = rawLayer->makeWeakPtr();
rawLayer->peer = LayerWrapper { self };
}
return self;
}
@@ -32,6 +33,11 @@ const MGLExceptionName MGLInvalidStyleLayerException = @"MGLInvalidStyleLayerExc
return self;
}
- (mbgl::style::Layer *)rawLayer
{
return _weakLayer.get();
}
- (void)addToStyle:(MGLStyle *)style belowLayer:(MGLStyleLayer *)otherLayer
{
if (_pendingLayer == nullptr) {
@@ -103,9 +109,15 @@ const MGLExceptionName MGLInvalidStyleLayerException = @"MGLInvalidStyleLayerExc
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; visible = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
self.visible ? @"YES" : @"NO"];
if (self.rawLayer) {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; visible = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
self.visible ? @"YES" : @"NO"];
}
else {
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; visible = NO>",
NSStringFromClass([self class]), (void *)self, self.identifier];
}
}
@end

View File

@@ -27,6 +27,7 @@ struct LayerWrapper {
if (!self.rawLayer) { \
[NSException raise:MGLInvalidStyleLayerException \
format: \
@"Either this layer got invalidated after the style change or " \
@"-[MGLStyle removeLayer:] has been called " \
@"with this instance but another style layer instance was added with the same identifer. It is an " \
@"error to send any message to this layer since it cannot be recovered after removal due to the " \

View File

@@ -55,7 +55,9 @@ typedef NS_ENUM(NSInteger, MGLErrorCode) {
/** Source is in use and cannot be removed */
MGLErrorCodeSourceIdentifierMismatch = 8,
/** An error occurred while modifying the offline storage database */
MGLErrorCodeModifyingOfflineStorageFailed = 9
MGLErrorCodeModifyingOfflineStorageFailed = 9,
/** Source is invalid and cannot be removed from the style (e.g. after a style change) */
MGLErrorCodeSourceCannotBeRemovedFromStyle = 10
};
/** Options for enabling debugging features in an `MGLMapView` instance. */

View File

@@ -1,25 +0,0 @@
#import "MGLVectorStyleLayer.h"
@implementation MGLVectorStyleLayer
- (void)setPredicate:(NSPredicate *)predicate {
[NSException raise:MGLAbstractClassException
format:@"MGLVectorStyleLayer is an abstract class"];
}
- (NSPredicate *)predicate {
[NSException raise:MGLAbstractClassException
format:@"MGLVectorStyleLayer is an abstract class"];
return nil;
}
- (NSString *)description {
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; sourceIdentifier = %@; "
@"sourceLayerIdentifier = %@; predicate = %@; visible = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
self.sourceIdentifier, self.sourceLayerIdentifier, self.predicate,
self.visible ? @"YES" : @"NO"];
}
@end

View File

@@ -0,0 +1,34 @@
#import "MGLVectorStyleLayer.h"
#import "MGLStyleLayer_Private.h"
@implementation MGLVectorStyleLayer
- (void)setPredicate:(NSPredicate *)predicate {
[NSException raise:MGLAbstractClassException
format:@"MGLVectorStyleLayer is an abstract class"];
}
- (NSPredicate *)predicate {
[NSException raise:MGLAbstractClassException
format:@"MGLVectorStyleLayer is an abstract class"];
return nil;
}
- (NSString *)description {
if (self.rawLayer) {
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; sourceIdentifier = %@; "
@"sourceLayerIdentifier = %@; predicate = %@; visible = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
self.sourceIdentifier, self.sourceLayerIdentifier, self.predicate,
self.visible ? @"YES" : @"NO"];
}
else {
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; sourceIdentifier = <unknown>; "
@"sourceLayerIdentifier = <unknown>; predicate = <unknown>; visible = <unknown>>",
NSStringFromClass([self class]), (void *)self, self.identifier];
}
}
@end

View File

@@ -38,17 +38,19 @@
}
- (NSURL *)configurationURL {
MGLAssertStyleSourceIsValid();
auto url = self.rawSource->getURL();
return url ? [NSURL URLWithString:@(url->c_str())] : nil;
}
- (NSString *)attributionHTMLString {
MGLAssertStyleSourceIsValid();
auto attribution = self.rawSource->getAttribution();
return attribution ? @(attribution->c_str()) : nil;
}
- (NSArray<id <MGLFeature>> *)featuresInSourceLayersWithIdentifiers:(NSSet<NSString *> *)sourceLayerIdentifiers predicate:(nullable NSPredicate *)predicate {
MGLAssertStyleSourceIsValid();
mbgl::optional<std::vector<std::string>> optionalSourceLayerIDs;
if (sourceLayerIdentifiers) {
__block std::vector<std::string> layerIDs;

View File

@@ -6,6 +6,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
### Styles and rendering
* Fixed crashes triggered when `MGLSource` and `MGLStyleLayer` objects are accessed after having been invalidated after a style change. ([#15539](https://github.com/mapbox/mapbox-gl-native/pull/15539))
* Fixed a rendering issue of `collisionBox` when `MGLSymbolStyleLayer.textTranslate` or `MGLSymbolStyleLayer.iconTranslate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467))
* Fixed an issue where the scale bar text would become illegible if iOS 13 dark mode was enabled. ([#15524](https://github.com/mapbox/mapbox-gl-native/pull/15524))
* Enabled use of `MGLSymbolStyleLayer.textOffset` option together with `MGLSymbolStyleLayer.textVariableAnchor` (if `MGLSymbolStyleLayer.textRadialOffset` option is not provided). ([#15542](https://github.com/mapbox/mapbox-gl-native/pull/15542))

View File

@@ -0,0 +1,45 @@
import XCTest
class MGLSourceTests: MGLMapViewIntegrationTest {
// See testForRaisingExceptionsOnStaleStyleObjects for Obj-C sibling.
func testForRaisingExceptionsOnStaleStyleObjectsOnRemoveFromMapView() {
guard
let configURL = URL(string: "mapbox://examples.2uf7qges") else {
XCTFail()
return
}
let source = MGLVectorTileSource(identifier: "trees", configurationURL: configURL)
mapView.style?.addSource(source)
let bundle = Bundle(for: type(of: self))
guard let styleURL = bundle.url(forResource: "one-liner", withExtension: "json") else {
XCTFail()
return
}
styleLoadingExpectation = nil;
mapView.centerCoordinate = CLLocationCoordinate2D(latitude : 38.897, longitude : -77.039)
mapView.zoomLevel = 10.5
mapView.styleURL = styleURL
waitForMapViewToFinishLoadingStyle(withTimeout: 10.0)
let expect = expectation(description: "Remove source should error")
do {
try mapView.style?.removeSource(source, error: ())
}
catch let error as NSError {
XCTAssertEqual(error.domain, MGLErrorDomain)
XCTAssertEqual(error.code, MGLErrorCode.sourceCannotBeRemovedFromStyle.rawValue)
expect.fulfill()
}
wait(for: [expect], timeout: 0.1)
}
}

View File

@@ -58,4 +58,55 @@
[self waitForMapViewToBeRenderedWithTimeout:10];
}
- (void)testForRaisingExceptionsOnStaleStyleObjects {
self.mapView.centerCoordinate = CLLocationCoordinate2DMake(38.897,-77.039);
self.mapView.zoomLevel = 10.5;
MGLVectorTileSource *source = [[MGLVectorTileSource alloc] initWithIdentifier:@"trees" configurationURL:[NSURL URLWithString:@"mapbox://examples.2uf7qges"]];
[self.mapView.style addSource:source];
self.styleLoadingExpectation = nil;
[self.mapView setStyleURL:[[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"]];
[self waitForMapViewToFinishLoadingStyleWithTimeout:10];
XCTAssertNotNil(source.description);
XCTAssertThrowsSpecificNamed(source.configurationURL, NSException, MGLInvalidStyleSourceException, @"MGLSource should raise an exception if its core peer got invalidated");
}
- (void)testForRaisingExceptionsOnStaleLayerObject {
self.mapView.centerCoordinate = CLLocationCoordinate2DMake(38.897,-77.039);
self.mapView.zoomLevel = 10.5;
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
// Testing generated layers
MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"lineLayerID" source:source];
MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"rasterLayerID" source:source];
[self.mapView.style addSource:source];
[self.mapView.style addLayer:lineLayer];
[self.mapView.style addLayer:rasterLayer];
XCTAssertNoThrow(lineLayer.isVisible);
XCTAssertNoThrow(rasterLayer.isVisible);
XCTAssert(![source.description containsString:@"<unknown>"]);
XCTAssert(![lineLayer.description containsString:@"<unknown>"]);
XCTAssert(![rasterLayer.description containsString:@"<unknown>"]);
self.styleLoadingExpectation = nil;
[self.mapView setStyleURL:[[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"]];
[self waitForMapViewToFinishLoadingStyleWithTimeout:10];
XCTAssert([source.description containsString:@"<unknown>"]);
XCTAssert([lineLayer.description containsString:@"<unknown>"]);
XCTAssert([rasterLayer.description containsString:@"<unknown>"]);
XCTAssertThrowsSpecificNamed(lineLayer.isVisible, NSException, MGLInvalidStyleLayerException, @"Layer should raise an exception if its core peer got invalidated");
XCTAssertThrowsSpecificNamed(rasterLayer.isVisible, NSException, MGLInvalidStyleLayerException, @"Layer should raise an exception if its core peer got invalidated");
XCTAssertThrowsSpecificNamed([self.mapView.style removeLayer:lineLayer], NSException, NSInvalidArgumentException, @"Style should raise an exception when attempting to remove an invalid layer (e.g. if its core peer got invalidated)");
XCTAssertThrowsSpecificNamed([self.mapView.style removeLayer:rasterLayer], NSException, NSInvalidArgumentException, @"Style should raise an exception when attempting to remove an invalid layer (e.g. if its core peer got invalidated)");
}
@end

View File

@@ -506,6 +506,7 @@
CA0C27922076C804001CE5B7 /* MGLShapeSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C27912076C804001CE5B7 /* MGLShapeSourceTests.m */; };
CA0C27942076CA19001CE5B7 /* MGLMapViewIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */; };
CA1B4A512099FB2200EDD491 /* MGLMapSnapshotterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CA1B4A502099FB2200EDD491 /* MGLMapSnapshotterTest.m */; };
CA4C54FE2324948100A81659 /* MGLSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA4C54FD2324948100A81659 /* MGLSourceTests.swift */; };
CA4EB8C720863487006AB465 /* MGLStyleLayerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */; };
CA4F3BDE230F74C3008BAFEA /* MGLMapViewPendingBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA4F3BDD230F74C3008BAFEA /* MGLMapViewPendingBlockTests.m */; };
CA4F3BE223107793008BAFEA /* MGLCameraTransitionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA4F3BE123107793008BAFEA /* MGLCameraTransitionTests.mm */; };
@@ -576,8 +577,8 @@
DA5DB12A1FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5DB1291FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m */; };
DA6408DB1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA6408DC1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */; };
DA6408DE1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */; };
DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.mm */; };
DA6408DE1DA4E7D300908C90 /* MGLVectorStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.mm */; };
DA695426215B1E76002041A4 /* MGLMapCameraTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA695425215B1E75002041A4 /* MGLMapCameraTests.m */; };
DA704CC21F65A475004B3F28 /* MGLMapAccessibilityElement.h in Headers */ = {isa = PBXBuildFile; fileRef = DA704CC01F65A475004B3F28 /* MGLMapAccessibilityElement.h */; };
DA704CC31F65A475004B3F28 /* MGLMapAccessibilityElement.h in Headers */ = {isa = PBXBuildFile; fileRef = DA704CC01F65A475004B3F28 /* MGLMapAccessibilityElement.h */; };
@@ -1198,6 +1199,7 @@
CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewIntegrationTest.m; sourceTree = "<group>"; wrapsLines = 0; };
CA0C27952076CA50001CE5B7 /* MGLMapViewIntegrationTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLMapViewIntegrationTest.h; sourceTree = "<group>"; };
CA1B4A502099FB2200EDD491 /* MGLMapSnapshotterTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapSnapshotterTest.m; sourceTree = "<group>"; };
CA4C54FD2324948100A81659 /* MGLSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MGLSourceTests.swift; sourceTree = "<group>"; };
CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLStyleLayerIntegrationTests.m; sourceTree = "<group>"; };
CA4F3BDD230F74C3008BAFEA /* MGLMapViewPendingBlockTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewPendingBlockTests.m; sourceTree = "<group>"; };
CA4F3BE123107793008BAFEA /* MGLCameraTransitionTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLCameraTransitionTests.mm; sourceTree = "<group>"; };
@@ -1285,7 +1287,7 @@
DA618B261E68920D00CB7F44 /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lt; path = lt.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
DA618B2B1E68932D00CB7F44 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorStyleLayer.h; sourceTree = "<group>"; };
DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLVectorStyleLayer.m; sourceTree = "<group>"; };
DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLVectorStyleLayer.mm; sourceTree = "<group>"; };
DA695425215B1E75002041A4 /* MGLMapCameraTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLMapCameraTests.m; path = ../../darwin/test/MGLMapCameraTests.m; sourceTree = "<group>"; };
DA704CBB1F637311004B3F28 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Foundation.strings; sourceTree = "<group>"; };
DA704CBC1F637405004B3F28 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = uk; path = uk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
@@ -1559,6 +1561,7 @@
077061DB215DA11F000FEF62 /* MGLTestLocationManager.h */,
077061D9215DA00E000FEF62 /* MGLTestLocationManager.m */,
CA4F3BDD230F74C3008BAFEA /* MGLMapViewPendingBlockTests.m */,
CA4C54FD2324948100A81659 /* MGLSourceTests.swift */,
);
path = "Integration Tests";
sourceTree = "<group>";
@@ -1646,7 +1649,7 @@
353933FD1D3FB7DD003F57D7 /* MGLSymbolStyleLayer.h */,
35136D441D42275100C20EFD /* MGLSymbolStyleLayer.mm */,
DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */,
DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */,
DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.mm */,
);
name = Layers;
sourceTree = "<group>";
@@ -3218,6 +3221,7 @@
077061DA215DA00E000FEF62 /* MGLTestLocationManager.m in Sources */,
CA6914B520E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.mm in Sources */,
CA4F3BE223107793008BAFEA /* MGLCameraTransitionTests.mm in Sources */,
CA4C54FE2324948100A81659 /* MGLSourceTests.swift in Sources */,
CA1B4A512099FB2200EDD491 /* MGLMapSnapshotterTest.m in Sources */,
CA4F3BE4231077B9008BAFEA /* MGLCameraTransitionFinishTests.mm in Sources */,
);
@@ -3345,7 +3349,7 @@
35136D3C1D42272500C20EFD /* MGLCircleStyleLayer.mm in Sources */,
DD9BE4F81EB263C50079A3AF /* UIViewController+MGLAdditions.m in Sources */,
350098DE1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */,
DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */,
DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.mm in Sources */,
40834BF71FE05E1800C1BD0D /* MMEUniqueIdentifier.m in Sources */,
3566C7681D4A77BA008152BC /* MGLShapeSource.mm in Sources */,
967C864D210A9D3C004DF794 /* UIDevice+MGLAdditions.m in Sources */,
@@ -3469,7 +3473,7 @@
DD9BE4FA1EB263F40079A3AF /* UIViewController+MGLAdditions.m in Sources */,
AC46EB60225E60510039C013 /* MMEPinningConfigurationProvider.m in Sources */,
350098DF1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */,
DA6408DE1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */,
DA6408DE1DA4E7D300908C90 /* MGLVectorStyleLayer.mm in Sources */,
3566C7691D4A77BA008152BC /* MGLShapeSource.mm in Sources */,
9C6E282722A980AC0056B7BE /* UIKit+MMEMobileEvents.m in Sources */,
40834C0B1FE05E1800C1BD0D /* MMEUniqueIdentifier.m in Sources */,

View File

@@ -25,7 +25,7 @@
"platform/darwin/src/MGLCircleStyleLayer.mm",
"platform/ios/src/UIViewController+MGLAdditions.m",
"platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm",
"platform/darwin/src/MGLVectorStyleLayer.m",
"platform/darwin/src/MGLVectorStyleLayer.mm",
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEUniqueIdentifier.m",
"platform/darwin/src/MGLShapeSource.mm",
"platform/ios/src/UIDevice+MGLAdditions.m",

View File

@@ -2,6 +2,7 @@
## master
* Fixed crashes triggered when `MGLSource` and `MGLStyleLayer` objects are accessed after having been invalidated after a style change. ([#15539](https://github.com/mapbox/mapbox-gl-native/pull/15539))
* Fixed an issue where it was possible to set the map’s content insets then tilt the map enough to see the horizon, causing performance issues. ([#15195](https://github.com/mapbox/mapbox-gl-native/pull/15195))
* Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14816](https://github.com/mapbox/mapbox-gl-native/pull/14816))
* Fixed queryRenderedFeatues bug caused by incorrect sort feature index calculation. ([#14884](https://github.com/mapbox/mapbox-gl-native/pull/14884))

View File

@@ -156,7 +156,7 @@
DA5589771D320C41006B7F64 /* wms.json in Resources */ = {isa = PBXBuildFile; fileRef = DA5589761D320C41006B7F64 /* wms.json */; };
DA57D4B11EBC699800793288 /* MGLDocumentationGuideTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA57D4B01EBC699800793288 /* MGLDocumentationGuideTests.swift */; };
DA6408D71DA4E5DA00908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D51DA4E5DA00908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA6408D81DA4E5DA00908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.m */; };
DA6408D81DA4E5DA00908C90 /* MGLVectorStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.mm */; };
DA695424215B1E6C002041A4 /* MGLMapCameraTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA695423215B1E6C002041A4 /* MGLMapCameraTests.m */; };
DA7262071DEEDD460043BB89 /* MGLOpenGLStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7262051DEEDD460043BB89 /* MGLOpenGLStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA7262081DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA7262061DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm */; };
@@ -516,7 +516,7 @@
DA618B271E68926E00CB7F44 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
DA618B2A1E6892B500CB7F44 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
DA6408D51DA4E5DA00908C90 /* MGLVectorStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorStyleLayer.h; sourceTree = "<group>"; };
DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLVectorStyleLayer.m; sourceTree = "<group>"; };
DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLVectorStyleLayer.mm; sourceTree = "<group>"; };
DA695423215B1E6C002041A4 /* MGLMapCameraTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLMapCameraTests.m; path = ../../darwin/test/MGLMapCameraTests.m; sourceTree = "<group>"; };
DA704CBA1F6372E8004B3F28 /* ru */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Foundation.strings; sourceTree = "<group>"; };
DA704CBE1F637531004B3F28 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -799,7 +799,7 @@
DA8F25911D51CA750010E6B5 /* MGLSymbolStyleLayer.h */,
DA8F25921D51CA750010E6B5 /* MGLSymbolStyleLayer.mm */,
DA6408D51DA4E5DA00908C90 /* MGLVectorStyleLayer.h */,
DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.m */,
DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.mm */,
);
name = Layers;
sourceTree = "<group>";
@@ -1695,7 +1695,7 @@
DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */,
352742821D4C243B00A1ECE6 /* MGLSource.mm in Sources */,
DAE6C3881CC31E2A00DB3429 /* MGLMapCamera.mm in Sources */,
DA6408D81DA4E5DA00908C90 /* MGLVectorStyleLayer.m in Sources */,
DA6408D81DA4E5DA00908C90 /* MGLVectorStyleLayer.mm in Sources */,
1FF4858D2237235300F19727 /* MGLAttributedExpression.m in Sources */,
DA8F25B31D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */,
DAE6C3911CC31E2A00DB3429 /* MGLPolygon.mm in Sources */,

View File

@@ -49,7 +49,7 @@
"platform/darwin/src/MGLCoordinateFormatter.m",
"platform/darwin/src/MGLSource.mm",
"platform/darwin/src/MGLMapCamera.mm",
"platform/darwin/src/MGLVectorStyleLayer.m",
"platform/darwin/src/MGLVectorStyleLayer.mm",
"platform/darwin/src/MGLAttributedExpression.m",
"platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm",
"platform/darwin/src/MGLPolygon.mm",

View File

@@ -143,7 +143,8 @@ generateFileList('vendor/mapbox-base-files.json',
'vendor/mapbox-base/mapbox/optional',
'vendor/mapbox-base/mapbox/supercluster.hpp',
'vendor/mapbox-base/mapbox/geojson.hpp',
'vendor/mapbox-base/mapbox/jni.hpp' ],
'vendor/mapbox-base/mapbox/jni.hpp',
'vendor/mapbox-base/mapbox/weak' ],
vendorRegex, [ "include/*.hpp", "include/**/*.hpp", "include/**/*.h", "optional.hpp", ":!:include/jni/string_conversion.hpp" ]);
generateFileList('vendor/polylabel-files.json', [ 'vendor/polylabel' ], vendorRegex, [ "include/**/*.hpp" ]);
generateFileList('vendor/protozero-files.json', [ 'vendor/protozero' ], vendorRegex, [ "include/**/*.hpp" ]);

View File

@@ -5,17 +5,22 @@
namespace mbgl {
class AnnotationSource : public style::Source {
class AnnotationSource final : public style::Source {
public:
AnnotationSource();
class Impl;
const Impl& impl() const;
mapbox::base::WeakPtr<Source> makeWeakPtr() override {
return weakFactory.makeWeakPtr();
}
private:
void loadDescription(FileSource&) final;
Mutable<Impl> mutableImpl() const;
mapbox::base::WeakPtrFactory<Source> weakFactory {this};
};
class AnnotationSource::Impl : public style::Source::Impl {

View File

@@ -98,7 +98,8 @@
"mapbox/variant.hpp": "vendor/mapbox-base/mapbox/variant/include/mapbox/variant.hpp",
"mapbox/variant_cast.hpp": "vendor/mapbox-base/mapbox/variant/include/mapbox/variant_cast.hpp",
"mapbox/variant_io.hpp": "vendor/mapbox-base/mapbox/variant/include/mapbox/variant_io.hpp",
"mapbox/variant_visitor.hpp": "vendor/mapbox-base/mapbox/variant/include/mapbox/variant_visitor.hpp"
"mapbox/variant_visitor.hpp": "vendor/mapbox-base/mapbox/variant/include/mapbox/variant_visitor.hpp",
"mapbox/weak.hpp": "vendor/mapbox-base/mapbox/weak/include/mapbox/weak.hpp"
},
"private_headers": {}
}