diff options
author | m-stephen <truestyle2005@163.com> | 2019-09-17 10:46:33 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-17 10:46:33 +0800 |
commit | eb1f8eb32286dd7b89ae76b839b774b0071ca5a5 (patch) | |
tree | 0db6df1811ffb8c9a5139687817386dee23cfef1 /platform/darwin/src | |
parent | b0018568b84f9bb1c185f0441a41741e9fde5a84 (diff) | |
parent | a99240a54ffd5eb77568d41e10186411b1b759eb (diff) | |
download | qtlocation-mapboxgl-eb1f8eb32286dd7b89ae76b839b774b0071ca5a5.tar.gz |
Merge branch 'master' into stephen-ios-error-report
Diffstat (limited to 'platform/darwin/src')
26 files changed, 305 insertions, 96 deletions
diff --git a/platform/darwin/src/MGLAccountManager.m b/platform/darwin/src/MGLAccountManager.m index 69170459bc..c37195967a 100644 --- a/platform/darwin/src/MGLAccountManager.m +++ b/platform/darwin/src/MGLAccountManager.m @@ -13,6 +13,8 @@ static NSString * const MGLAccountManagerExternalClassName = @"MBXAccounts"; static NSString * const MGLAccountManagerExternalMethodName = @"skuToken"; #endif +NSString * const MGLMapboxAccountTypeKey = @"MGLMapboxAccountType"; + @interface MGLAccountManager () @property (atomic) NSString *accessToken; diff --git a/platform/darwin/src/MGLAccountManager_Private.h b/platform/darwin/src/MGLAccountManager_Private.h index 3fd45f1ae8..4bf7963182 100644 --- a/platform/darwin/src/MGLAccountManager_Private.h +++ b/platform/darwin/src/MGLAccountManager_Private.h @@ -2,6 +2,9 @@ NS_ASSUME_NONNULL_BEGIN +/// NSUserDefaults key that controls developer account type +FOUNDATION_EXTERN NSString * const MGLMapboxAccountTypeKey; + @interface MGLAccountManager (Private) /// Returns the shared instance of the `MGLAccountManager` class. diff --git a/platform/darwin/src/MGLComputedShapeSource.mm b/platform/darwin/src/MGLComputedShapeSource.mm index 5110435b03..a04181af2f 100644 --- a/platform/darwin/src/MGLComputedShapeSource.mm +++ b/platform/darwin/src/MGLComputedShapeSource.mm @@ -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)); } diff --git a/platform/darwin/src/MGLForegroundStyleLayer.mm b/platform/darwin/src/MGLForegroundStyleLayer.mm index 76700d6f77..eaa5e83e59 100644 --- a/platform/darwin/src/MGLForegroundStyleLayer.mm +++ b/platform/darwin/src/MGLForegroundStyleLayer.mm @@ -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 diff --git a/platform/darwin/src/MGLImageSource.mm b/platform/darwin/src/MGLImageSource.mm index 351247e901..421cc7a155 100644 --- a/platform/darwin/src/MGLImageSource.mm +++ b/platform/darwin/src/MGLImageSource.mm @@ -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; } diff --git a/platform/darwin/src/MGLMapSnapshotter.h b/platform/darwin/src/MGLMapSnapshotter.h index 1ee9bd99bb..0f20cf1bb2 100644 --- a/platform/darwin/src/MGLMapSnapshotter.h +++ b/platform/darwin/src/MGLMapSnapshotter.h @@ -6,6 +6,30 @@ NS_ASSUME_NONNULL_BEGIN /** + An overlay that is placed within a `MGLMapSnapshot`. + To access this object, use `-[MGLMapSnapshotter startWithOverlayHandler:completionHandler:]`. + */ + +MGL_EXPORT +@interface MGLMapSnapshotOverlay : NSObject + +/** + The current `CGContext` that snapshot is drawing within. You may use this context + to perform additional custom drawing. + */ +@property (nonatomic, readonly) CGContextRef context; + +@end + +/** +A block provided during the snapshot drawing process, enabling the ability to +draw custom overlays rendered with Core Graphics. + + @param snapshotOverlay The `MGLMapSnapshotOverlay` provided during snapshot drawing. + */ +typedef void (^MGLMapSnapshotOverlayHandler)(MGLMapSnapshotOverlay * snapshotOverlay); + +/** The options to use when creating images with the `MGLMapSnapshotter`. */ MGL_EXPORT @@ -201,6 +225,16 @@ MGL_EXPORT - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completionHandler; /** + Starts the snapshot creation and executes the specified blocks with the result + on the specified queue. Use this option if you want to add custom drawing on top of the + resulting `MGLMapSnapShot`. + @param queue The queue to handle the result on. + @param overlayHandler The block to handle manipulation of the `MGLMapSnapshotter`'s `CGContext`. + @param completionHandler The block to handle the result in. + */ +- (void)startWithOverlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler completionHandler:(MGLMapSnapshotCompletionHandler)completionHandler; + +/** Cancels the snapshot creation request, if any. Once you call this method, you cannot resume the snapshot. In order to obtain diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm index 9ba0cbebfe..85619a780b 100644 --- a/platform/darwin/src/MGLMapSnapshotter.mm +++ b/platform/darwin/src/MGLMapSnapshotter.mm @@ -32,6 +32,26 @@ const CGPoint MGLLogoImagePosition = CGPointMake(8, 8); const CGFloat MGLSnapshotterMinimumPixelSize = 64; + +@interface MGLMapSnapshotOverlay() + +- (instancetype)initWithContext:(CGContextRef)context; + +@end + +@implementation MGLMapSnapshotOverlay + +- (instancetype) initWithContext:(CGContextRef)context { + self = [super init]; + if (self) { + _context = context; + } + + return self; +} + +@end + @implementation MGLMapSnapshotOptions - (instancetype _Nonnull)initWithStyleURL:(nullable NSURL *)styleURL camera:(MGLMapCamera *)camera size:(CGSize)size @@ -183,7 +203,15 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; [self startWithQueue:dispatch_get_main_queue() completionHandler:completion]; } -- (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completion +- (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completionHandler { + [self startWithQueue:queue overlayHandler:nil completionHandler:completionHandler]; +} + +- (void)startWithOverlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler completionHandler:(MGLMapSnapshotCompletionHandler)completion { + [self startWithQueue:dispatch_get_main_queue() overlayHandler:overlayHandler completionHandler:completion]; +} + +- (void)startWithQueue:(dispatch_queue_t)queue overlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler completionHandler:(MGLMapSnapshotCompletionHandler)completion { if (!mbgl::Scheduler::GetCurrent()) { [NSException raise:NSInvalidArgumentException @@ -210,8 +238,8 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; // capture weakSelf to avoid retain cycle if callback is never called (ie snapshot cancelled) _snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>( - *mbgl::Scheduler::GetCurrent(), - [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image, mbgl::MapSnapshotter::Attributions attributions, mbgl::MapSnapshotter::PointForFn pointForFn, mbgl::MapSnapshotter::LatLngForFn latLngForFn) { + *mbgl::Scheduler::GetCurrent(), + [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image, mbgl::MapSnapshotter::Attributions attributions, mbgl::MapSnapshotter::PointForFn pointForFn, mbgl::MapSnapshotter::LatLngForFn latLngForFn) { __typeof__(self) strongSelf = weakSelf; // If self had died, _snapshotCallback would have been destroyed and this block would not be executed @@ -227,12 +255,12 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR [[MMEEventsManager sharedManager] reportError:error]; #endif - // Dispatch to result queue dispatch_async(queue, ^{ strongSelf.completion(nil, error); strongSelf.completion = nil; }); + } else { #if TARGET_OS_IPHONE MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image) scale:strongSelf.options.scale]; @@ -241,11 +269,12 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; mglImage.size = NSMakeSize(mglImage.size.width / strongSelf.options.scale, mglImage.size.height / strongSelf.options.scale); #endif - [strongSelf drawAttributedSnapshot:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn]; + + [strongSelf drawAttributedSnapshot:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn overlayHandler:overlayHandler]; } strongSelf->_snapshotCallback = NULL; - }); + }); // Launches snapshot on background Thread owned by mbglMapSnapshotter // _snapshotCallback->self() is an ActorRef: if the callback is destroyed, further messages @@ -253,7 +282,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; _mbglMapSnapshotter->snapshot(_snapshotCallback->self()); } -+ (MGLImage*)drawAttributedSnapshotWorker:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn scale:(CGFloat)scale size:(CGSize)size { ++ (MGLImage*)drawAttributedSnapshotWorker:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn scale:(CGFloat)scale size:(CGSize)size overlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler { NSArray<MGLAttributionInfo *>* attributionInfo = [MGLMapSnapshotter generateAttributionInfos:attributions]; @@ -295,7 +324,23 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, scale); [mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)]; - + + CGContextRef currentContext = UIGraphicsGetCurrentContext(); + + if (currentContext && overlayHandler) { + MGLMapSnapshotOverlay *snapshotOverlay = [[MGLMapSnapshotOverlay alloc] initWithContext:currentContext]; + CGContextSaveGState(snapshotOverlay.context); + overlayHandler(snapshotOverlay); + CGContextRestoreGState(snapshotOverlay.context); + currentContext = UIGraphicsGetCurrentContext(); + } + + if (!currentContext && overlayHandler) { + // If the current context has been corrupted by the user, + // return nil so we can generate an error later. + return nil; + } + [logoImage drawInRect:logoImageRect]; UIImage *currentImage = UIGraphicsGetImageFromCurrentImageContext(); @@ -362,6 +407,21 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; [sourceImageRep drawInRect: targetFrame]; + NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; + if (currentContext && overlayHandler) { + MGLMapSnapshotOverlay *snapshotOverlay = [[MGLMapSnapshotOverlay alloc] initWithContext:currentContext.CGContext]; + [currentContext saveGraphicsState]; + overlayHandler(snapshotOverlay); + [currentContext restoreGraphicsState]; + currentContext = [NSGraphicsContext currentContext]; + } + + if (!currentContext && overlayHandler) { + // If the current context has been corrupted by the user, + // return nil so we can generate an error later. + return nil; + } + if (logoImage) { [logoImage drawInRect:logoImageRect]; } @@ -382,8 +442,8 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; #endif } -- (void)drawAttributedSnapshot:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn { - +- (void)drawAttributedSnapshot:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn overlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler { + // Process image watermark in a work queue dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_queue_t resultQueue = self.resultQueue; @@ -397,19 +457,30 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; dispatch_async(workQueue, ^{ // Call a class method to ensure we're not accidentally capturing self - MGLImage *compositedImage = [MGLMapSnapshotter drawAttributedSnapshotWorker:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn scale:scale size:size]; + MGLImage *compositedImage = [MGLMapSnapshotter drawAttributedSnapshotWorker:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn scale:scale size:size overlayHandler:overlayHandler]; // Dispatch result to origin queue dispatch_async(resultQueue, ^{ __typeof__(self) strongself = weakself; if (strongself.completion) { - MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage - scale:scale - pointForFn:pointForFn - latLngForFn:latLngForFn]; - strongself.completion(snapshot, nil); - strongself.completion = nil; + + if (!compositedImage) { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Failed to generate composited snapshot."}; + NSError *error = [NSError errorWithDomain:MGLErrorDomain + code:MGLErrorCodeSnapshotFailed + userInfo:userInfo]; + + strongself.completion(nil, error); + strongself.completion = nil; + } else { + MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage + scale:scale + pointForFn:pointForFn + latLngForFn:latLngForFn]; + strongself.completion(snapshot, nil); + strongself.completion = nil; + } } }); }); @@ -630,7 +701,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; // Create the snapshotter _mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>( - style, size, pixelRatio, cameraOptions, coordinateBounds, config.cacheDir, config.localFontFamilyName, resourceOptions); + style, size, pixelRatio, cameraOptions, coordinateBounds, config.localFontFamilyName, resourceOptions); } @end diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h index 1ed364ddf3..d093bb938a 100644 --- a/platform/darwin/src/MGLOfflineStorage.h +++ b/platform/darwin/src/MGLOfflineStorage.h @@ -173,6 +173,11 @@ typedef NS_ENUM(NSUInteger, MGLResourceKind) { packs and ambient caching. All of this class’s instance methods are asynchronous, reflecting the fact that offline resources are stored in a database. The shared object maintains a canonical collection of offline packs in its `packs` property. + + Mapbox resources downloaded via this API are subject to separate Vector Tile and + Raster Tile API pricing and are not included in the Maps SDK’s “unlimited” requests. + See <a href="https://www.mapbox.com/pricing/">our pricing page</a> for more + information. #### Related examples See the <a href="https://docs.mapbox.com/ios/maps/examples/offline-pack/"> @@ -341,8 +346,7 @@ MGL_EXPORT attempt to download additional tiles until already downloaded tiles are removed by calling the `-removePack:withCompletionHandler:` method. - @note The <a href="https://www.mapbox.com/tos/">Mapbox Terms of Service</a> - prohibits changing or bypassing this limit without permission from Mapbox. + @param maximumCount The maximum number of tiles allowed to be downloaded. */ - (void)setMaximumAllowedMapboxTiles:(uint64_t)maximumCount; @@ -420,7 +424,7 @@ MGL_EXPORT - (void)resetDatabaseWithCompletionHandler:(void (^)(NSError *_Nullable error))completion; -/* +/** Inserts the provided resource into the ambient cache. This method mimics the caching that would take place if the equivalent resource diff --git a/platform/darwin/src/MGLRasterTileSource.mm b/platform/darwin/src/MGLRasterTileSource.mm index 61e9ef97fd..e89367711e 100644 --- a/platform/darwin/src/MGLRasterTileSource.mm +++ b/platform/darwin/src/MGLRasterTileSource.mm @@ -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; } diff --git a/platform/darwin/src/MGLRasterTileSource_Private.h b/platform/darwin/src/MGLRasterTileSource_Private.h index 128dcb447d..8502b811e2 100644 --- a/platform/darwin/src/MGLRasterTileSource_Private.h +++ b/platform/darwin/src/MGLRasterTileSource_Private.h @@ -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; diff --git a/platform/darwin/src/MGLRendererConfiguration.h b/platform/darwin/src/MGLRendererConfiguration.h index bfe88b7209..0c539f86f1 100644 --- a/platform/darwin/src/MGLRendererConfiguration.h +++ b/platform/darwin/src/MGLRendererConfiguration.h @@ -20,9 +20,6 @@ MGL_EXPORT Based on the native scale where available, otherwise the standard screen scale. */ @property (nonatomic, readonly) const float scaleFactor; -/** The cache dir to use. */ -@property (nonatomic, readonly) mbgl::optional<std::string> cacheDir; - /** The name of the font family to use for client-side text rendering of CJK ideographs. Set MGLIdeographicFontFamilyName in your containing application's Info.plist to diff --git a/platform/darwin/src/MGLRendererConfiguration.mm b/platform/darwin/src/MGLRendererConfiguration.mm index 54bdcaa691..136dc929a6 100644 --- a/platform/darwin/src/MGLRendererConfiguration.mm +++ b/platform/darwin/src/MGLRendererConfiguration.mm @@ -66,10 +66,6 @@ static NSString * const MGLIdeographicFontFamilyNameKey = @"MGLIdeographicFontFa #endif } -- (mbgl::optional<std::string>)cacheDir { - return mbgl::optional<std::string>(); -} - - (mbgl::optional<std::string>)localFontFamilyName { return [self _localFontFamilyNameWithPropertyDictionary:[[NSBundle mainBundle] infoDictionary]]; } diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm index fc526f9850..3628a0eb74 100644 --- a/platform/darwin/src/MGLShapeSource.mm +++ b/platform/darwin/src/MGLShapeSource.mm @@ -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 diff --git a/platform/darwin/src/MGLSource.h b/platform/darwin/src/MGLSource.h index 7bbf02fa7c..dc92e652e8 100644 --- a/platform/darwin/src/MGLSource.h +++ b/platform/darwin/src/MGLSource.h @@ -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 diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm index 62308ce5e1..1d7b46e1cc 100644 --- a/platform/darwin/src/MGLSource.mm +++ b/platform/darwin/src/MGLSource.mm @@ -11,6 +11,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 @@ -23,13 +25,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; } @@ -37,13 +40,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); @@ -63,6 +71,7 @@ } - (BOOL)removeFromMapView:(MGLMapView *)mapView error:(NSError * __nullable * __nullable)outError { + MGLAssertStyleSourceIsValid(); BOOL removed = NO; if (self.rawSource == mapView.style.rawStyle->getSource(self.identifier.UTF8String)) { diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h index af14c11b90..4a7c31694d 100644 --- a/platform/darwin/src/MGLSource_Private.h +++ b/platform/darwin/src/MGLSource_Private.h @@ -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) diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 5768a7aaa7..cab0eaae28 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -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]; } diff --git a/platform/darwin/src/MGLStyleLayer.mm b/platform/darwin/src/MGLStyleLayer.mm index 05885bc63e..7847cbb319 100644 --- a/platform/darwin/src/MGLStyleLayer.mm +++ b/platform/darwin/src/MGLStyleLayer.mm @@ -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 diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h index 314f61f680..52254f78c6 100644 --- a/platform/darwin/src/MGLStyleLayer_Private.h +++ b/platform/darwin/src/MGLStyleLayer_Private.h @@ -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 " \ diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index fb00b0d165..53bc488a41 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -1404,8 +1404,7 @@ MGL_EXPORT ems downward. Set this property to `nil` to reset it to the default value. This property is only applied to the style if `text` is non-`nil`, and - `textRadialOffset` is set to `nil`, and `textVariableAnchor` is set to `nil`. - Otherwise, it is ignored. + `textRadialOffset` is set to `nil`. Otherwise, it is ignored. You can set this property to an expression containing any of the following: @@ -1428,8 +1427,7 @@ MGL_EXPORT ems upward. Set this property to `nil` to reset it to the default value. This property is only applied to the style if `text` is non-`nil`, and - `textRadialOffset` is set to `nil`, and `textVariableAnchor` is set to `nil`. - Otherwise, it is ignored. + `textRadialOffset` is set to `nil`. Otherwise, it is ignored. You can set this property to an expression containing any of the following: @@ -1521,8 +1519,8 @@ MGL_EXPORT /** Radial offset of text, in the direction of the symbol's anchor. Useful in - combination with `textVariableAnchor`, which doesn't support the - two-dimensional `textOffset`. + combination with `textVariableAnchor`, which defaults to using the + two-dimensional `textOffset` if present. This property is measured in ems. @@ -1634,8 +1632,7 @@ MGL_EXPORT provide an array of `textAnchor` locations: the render will attempt to place the label at each location, in order, before moving onto the next label. Use `textJustify: auto` to choose justification based on anchor position. To apply - an offset, use the `textRadialOffset` instead of the two-dimensional - `textOffset`. + an offset, use the `textRadialOffset` or the two-dimensional `textOffset`. This property is only applied to the style if `text` is non-`nil`, and `symbolPlacement` is set to an expression that evaluates to or diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h index df3c61a61c..963eda384b 100644 --- a/platform/darwin/src/MGLTypes.h +++ b/platform/darwin/src/MGLTypes.h @@ -56,8 +56,10 @@ typedef NS_ENUM(NSInteger, MGLErrorCode) { MGLErrorCodeSourceIdentifierMismatch = 8, /** An error occurred while modifying the offline storage database */ MGLErrorCodeModifyingOfflineStorageFailed = 9, + /** Source is invalid and cannot be removed from the style (e.g. after a style change) */ + MGLErrorCodeSourceCannotBeRemovedFromStyle = 10, /** An error occurred while rendering */ - MGLErrorCodeRenderingError = 10, + MGLErrorCodeRenderingError = 11, }; /** Options for enabling debugging features in an `MGLMapView` instance. */ diff --git a/platform/darwin/src/MGLVectorStyleLayer.m b/platform/darwin/src/MGLVectorStyleLayer.m deleted file mode 100644 index 23f3556e0b..0000000000 --- a/platform/darwin/src/MGLVectorStyleLayer.m +++ /dev/null @@ -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 diff --git a/platform/darwin/src/MGLVectorStyleLayer.mm b/platform/darwin/src/MGLVectorStyleLayer.mm new file mode 100644 index 0000000000..691668629a --- /dev/null +++ b/platform/darwin/src/MGLVectorStyleLayer.mm @@ -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 diff --git a/platform/darwin/src/MGLVectorTileSource.mm b/platform/darwin/src/MGLVectorTileSource.mm index f7a6869ade..85270c4a49 100644 --- a/platform/darwin/src/MGLVectorTileSource.mm +++ b/platform/darwin/src/MGLVectorTileSource.mm @@ -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; diff --git a/platform/darwin/src/http_file_source.mm b/platform/darwin/src/http_file_source.mm index 5737d8b999..b0f69f4a7f 100644 --- a/platform/darwin/src/http_file_source.mm +++ b/platform/darwin/src/http_file_source.mm @@ -88,15 +88,14 @@ class HTTPFileSource::Impl { public: Impl() { @autoreleasepool { - - NSURLSessionConfiguration *sessionConfig = - [MGLNetworkConfiguration sharedManager].sessionConfiguration; - + NSURLSessionConfiguration *sessionConfig = [MGLNetworkConfiguration sharedManager].sessionConfiguration; session = [NSURLSession sessionWithConfiguration:sessionConfig]; userAgent = getUserAgent(); - accountType = [[NSUserDefaults standardUserDefaults] integerForKey:@"MGLMapboxAccountType"]; +#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR + accountType = [[NSUserDefaults standardUserDefaults] integerForKey:MGLMapboxAccountTypeKey]; +#endif } } @@ -205,13 +204,13 @@ NSURL *resourceURLWithAccountType(const Resource& resource, NSInteger accountTyp if (accountType == 0 && ([url.host isEqualToString:@"mapbox.com"] || [url.host hasSuffix:@".mapbox.com"])) { NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; - NSURLQueryItem *accountsQueryItem = [NSURLQueryItem queryItemWithName:@"sku" value:MGLAccountManager.skuToken]; - - NSMutableArray *queryItems = [NSMutableArray arrayWithObject:accountsQueryItem]; - - // offline here + NSMutableArray *queryItems = [NSMutableArray array]; + if (resource.usage == Resource::Usage::Offline) { [queryItems addObject:[NSURLQueryItem queryItemWithName:@"offline" value:@"true"]]; + } else { + // Only add SKU token to requests not tagged as "offline" usage. + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"sku" value:MGLAccountManager.skuToken]]; } if (components.queryItems) { diff --git a/platform/darwin/src/string_nsstring.mm b/platform/darwin/src/string_nsstring.mm index 096ed2b212..382a2acf33 100644 --- a/platform/darwin/src/string_nsstring.mm +++ b/platform/darwin/src/string_nsstring.mm @@ -43,6 +43,10 @@ std::string formatNumber(double number, const std::string& localeId, const std:: numberFormatter.maximumFractionDigits = maxFractionDigits; numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; } else { + // Reset fraction digits to NSNumberFormatter's default values, so that the + // system will choose formatting based on number formatter locale. + numberFormatter.minimumFractionDigits = 0; + numberFormatter.maximumFractionDigits = 0; numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; } NSString *formatted = [numberFormatter stringFromNumber:@(number)]; |