From e9f101a52f626744991ee73c3ced9c48bc013a51 Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Tue, 6 Dec 2016 11:48:36 +0100 Subject: [PATCH] [ios, macos] handle duplicate layer error --- platform/darwin/src/MGLStyle.mm | 38 ++++++++++++++++++++++----- platform/darwin/test/MGLStyleTests.mm | 27 +++++++++++++++++++ platform/ios/src/MGLMapView.mm | 10 ++++--- 3 files changed, 65 insertions(+), 10 deletions(-) diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 6116f4df2..7d7ca73a5 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -271,10 +271,18 @@ static NSURL *MGLStyleURL_emerald; [NSException raise:NSRangeException format:@"Cannot insert style layer at out-of-bounds index %lu.", (unsigned long)index]; } else if (index == 0) { - [styleLayer addToMapView:self.mapView]; + try { + [styleLayer addToMapView:self.mapView]; + } catch (const std::runtime_error & err) { + [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; + } } else { - MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(layers.size() - index)]; - [styleLayer addToMapView:self.mapView belowLayer:sibling]; + try { + MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(layers.size() - index)]; + [styleLayer addToMapView:self.mapView belowLayer:sibling]; + } catch (std::runtime_error & err) { + [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; + } } } @@ -350,7 +358,11 @@ static NSURL *MGLStyleURL_emerald; layer]; } [self willChangeValueForKey:@"layers"]; - [layer addToMapView:self.mapView]; + try { + [layer addToMapView:self.mapView]; + } catch (std::runtime_error & err) { + [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; + } [self didChangeValueForKey:@"layers"]; } @@ -375,7 +387,11 @@ static NSURL *MGLStyleURL_emerald; sibling]; } [self willChangeValueForKey:@"layers"]; - [layer addToMapView:self.mapView belowLayer:sibling]; + try { + [layer addToMapView:self.mapView belowLayer:sibling]; + } catch (std::runtime_error & err) { + [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; + } [self didChangeValueForKey:@"layers"]; } @@ -413,10 +429,18 @@ static NSURL *MGLStyleURL_emerald; @"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].", sibling]; } else if (index + 1 == layers.size()) { - [layer addToMapView:self.mapView]; + try { + [layer addToMapView:self.mapView]; + } catch (std::runtime_error & err) { + [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; + } } else { MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(index + 1)]; - [layer addToMapView:self.mapView belowLayer:sibling]; + try { + [layer addToMapView:self.mapView belowLayer:sibling]; + } catch (std::runtime_error & err) { + [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; + } } [self didChangeValueForKey:@"layers"]; } diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm index 4c0c163b3..5231d2dcf 100644 --- a/platform/darwin/test/MGLStyleTests.mm +++ b/platform/darwin/test/MGLStyleTests.mm @@ -1,5 +1,8 @@ #import "MGLMapView.h" #import "MGLStyle_Private.h" +#if TARGET_OS_IPHONE +#import "MGLMapView+MGLCustomStyleLayerAdditions.h" +#endif #import "MGLGeoJSONSource.h" #import "MGLRasterSource.h" @@ -165,6 +168,30 @@ XCTAssertThrowsSpecificNamed([self.style addLayer:symbolLayer], NSException, @"MGLRedundantLayerException"); } +- (void)testAddingLayersWithDuplicateIdentifiers { + //Just some source + MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; + [self.mapView.style addSource: source]; + + //Add initial layer + MGLFillStyleLayer *initial = [[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]; + [self.mapView.style addLayer:initial]; + + //Try to add the duplicate + XCTAssertThrowsSpecificNamed([self.mapView.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); + +#if TARGET_OS_IPHONE + //Try to insert a duplicate custom layer + MGLCustomStyleLayerDrawingHandler drawingHandler = ^(CGSize size, CLLocationCoordinate2D centerCoordinate, double zoomLevel, CLLocationDirection direction, CGFloat pitch, CGFloat perspectiveSkew) { + }; + + XCTAssertThrowsSpecific([self.mapView insertCustomStyleLayerWithIdentifier:@"my-layer" preparationHandler:^{} drawingHandler:drawingHandler completionHandler: ^{} belowStyleLayerWithIdentifier:nil], NSException); +#endif +} + - (NSString *)stringWithContentsOfStyleHeader { NSURL *styleHeaderURL = [[[NSBundle mgl_frameworkBundle].bundleURL URLByAppendingPathComponent:@"Headers" isDirectory:YES] diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 3c019d472..fad354013 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -5353,9 +5353,13 @@ void MGLFinishCustomStyleLayer(void *context) { NSAssert(identifier, @"Style layer needs an identifier"); MGLCustomStyleLayerHandlers *context = new MGLCustomStyleLayerHandlers(preparation, drawing, completion); - _mbglMap->addLayer(std::make_unique(identifier.UTF8String, MGLPrepareCustomStyleLayer, - MGLDrawCustomStyleLayer, MGLFinishCustomStyleLayer, context), - otherIdentifier ? mbgl::optional(otherIdentifier.UTF8String) : mbgl::optional()); + try { + _mbglMap->addLayer(std::make_unique(identifier.UTF8String, MGLPrepareCustomStyleLayer, + MGLDrawCustomStyleLayer, MGLFinishCustomStyleLayer, context), + otherIdentifier ? mbgl::optional(otherIdentifier.UTF8String) : mbgl::optional()); + } catch (std::runtime_error & err) { + [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; + } } - (void)removeCustomStyleLayerWithIdentifier:(NSString *)identifier