From b8f92acb70e65a9d32e23538ac8878882597d9e5 Mon Sep 17 00:00:00 2001 From: Julian Rex Date: Tue, 12 Feb 2019 14:02:45 -0500 Subject: BROKEN WIP --- platform/darwin/src/MGLMapSnapshotter.h | 4 +- platform/darwin/src/MGLMapSnapshotter.mm | 12 +++++- platform/darwin/src/MGLOfflinePack.mm | 47 ++++++++++++++++------ platform/darwin/src/MGLOfflinePack_Private.h | 4 +- platform/darwin/src/MGLOfflineStorage.mm | 34 +++++++++++----- platform/darwin/src/MGLRendererConfiguration.h | 2 +- platform/darwin/src/MGLRendererConfiguration.mm | 10 +++-- .../darwin/test/MGLDocumentationExampleTests.swift | 2 +- platform/ios/app/MBXSnapshotsViewController.m | 3 +- platform/ios/src/MGLMapView.mm | 7 +++- 10 files changed, 89 insertions(+), 36 deletions(-) diff --git a/platform/darwin/src/MGLMapSnapshotter.h b/platform/darwin/src/MGLMapSnapshotter.h index 146cbd2e15..7236d4502f 100644 --- a/platform/darwin/src/MGLMapSnapshotter.h +++ b/platform/darwin/src/MGLMapSnapshotter.h @@ -5,6 +5,8 @@ NS_ASSUME_NONNULL_BEGIN +@class MGLOfflineStorage; + /** The options to use when creating images with the `MGLMapSnapshotter`. */ @@ -182,7 +184,7 @@ MGL_EXPORT @param options The options to use when generating a map snapshot. @return An initialized map snapshotter. */ -- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options offlineStorage:(MGLOfflineStorage*)offlineStorage NS_DESIGNATED_INITIALIZER; /** Starts the snapshot creation and executes the specified block with the result. diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm index afcfc91109..e12ff43113 100644 --- a/platform/darwin/src/MGLMapSnapshotter.mm +++ b/platform/darwin/src/MGLMapSnapshotter.mm @@ -119,6 +119,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; @property (nonatomic) BOOL terminated; @property (nonatomic) dispatch_queue_t resultQueue; @property (nonatomic, copy) MGLMapSnapshotCompletionHandler completion; +@property (nonatomic) MGLOfflineStorage *offlineStorage; + (void)completeWithErrorCode:(MGLErrorCode)errorCode description:(nonnull NSString*)description onQueue:(dispatch_queue_t)queue completion:(MGLMapSnapshotCompletionHandler)completion; @end @@ -148,11 +149,12 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; return nil; } -- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options +- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options offlineStorage:(MGLOfflineStorage *)offlineStorage { MGLLogDebug(@"Initializing withOptions: %@", options); self = [super init]; if (self) { + _offlineStorage = offlineStorage; [self setOptions:options]; #if TARGET_OS_IPHONE [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil]; @@ -587,7 +589,13 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; _cancelled = NO; _options = options; - mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource; + mbgl::DefaultFileSource *mbglFileSource = self.offlineStorage.mbglFileSource; + + if (!mbglFileSource) { + [self cancel]; + } + + _mbglThreadPool = mbgl::sharedThreadPool(); std::string styleURL = std::string([options.styleURL.absoluteString UTF8String]); diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index a8f807374c..6e30316f98 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -53,6 +53,7 @@ private: @property (nonatomic, nullable, readwrite) mbgl::OfflineRegion *mbglOfflineRegion; @property (nonatomic, readwrite) MGLOfflinePackProgress progress; +@property (atomic, weak) MGLOfflineStorage *offlineStorage; @end @@ -69,13 +70,17 @@ private: return self; } -- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region { +- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region offlineStorage:(MGLOfflineStorage *)offlineStorage { if (self = [super init]) { _mbglOfflineRegion = region; _state = MGLOfflinePackStateUnknown; - - mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique(self)); + _offlineStorage = offlineStorage; + + mbgl::DefaultFileSource *mbglFileSource = [offlineStorage mbglFileSource]; + + if (mbglFileSource) { + mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique(self)); + } } return self; } @@ -113,10 +118,17 @@ private: MGLLogInfo(@"Resuming pack download."); MGLAssertOfflinePackIsValid(); - self.state = MGLOfflinePackStateActive; - mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active); + mbgl::DefaultFileSource *mbglFileSource = [self.offlineStorage mbglFileSource]; + if (mbglFileSource) { + self.state = MGLOfflinePackStateActive; + mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active); + } + else { + // What state should be we in? + self.state = MGLOfflinePackStateInvalid; + + } } - (void)suspend { @@ -128,8 +140,10 @@ private: _isSuspending = YES; } - mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive); + mbgl::DefaultFileSource *mbglFileSource = [self.offlineStorage mbglFileSource]; + if (mbglFileSource) { + mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive); + } } - (void)invalidate { @@ -137,8 +151,12 @@ private: MGLAssert(_state != MGLOfflinePackStateInvalid, @"Cannot invalidate an already invalid offline pack."); self.state = MGLOfflinePackStateInvalid; - mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr); + mbgl::DefaultFileSource *mbglFileSource = [self.offlineStorage mbglFileSource]; + + if (mbglFileSource) { + mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr); + } + self.mbglOfflineRegion = nil; } @@ -164,8 +182,13 @@ private: MGLLogInfo(@"Requesting pack progress."); MGLAssertOfflinePackIsValid(); - mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; + mbgl::DefaultFileSource *mbglFileSource = [self.offlineStorage mbglFileSource]; + if (!mbglFileSource) { + return; + } + + __weak MGLOfflinePack *weakSelf = self; mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](mbgl::expected status) { if (status) { diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h index 8a63152dca..f4623e62c1 100644 --- a/platform/darwin/src/MGLOfflinePack_Private.h +++ b/platform/darwin/src/MGLOfflinePack_Private.h @@ -3,14 +3,14 @@ #include NS_ASSUME_NONNULL_BEGIN - +@class MGLOfflineStorage; @interface MGLOfflinePack (Private) @property (nonatomic, nullable) mbgl::OfflineRegion *mbglOfflineRegion; @property (nonatomic, readwrite) MGLOfflinePackState state; -- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region; +- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region offlineStorage:(MGLOfflineStorage *)offlineStorage; /** Invalidates the pack and ensures that no future progress update can ever diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 17c1ff3d29..b6c196e3d2 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -59,10 +59,6 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio static MGLOfflineStorage *sharedOfflineStorage; dispatch_once(&onceToken, ^{ sharedOfflineStorage = [[self alloc] init]; -#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR - [[NSNotificationCenter defaultCenter] addObserver:sharedOfflineStorage selector:@selector(unpauseFileSource:) name:UIApplicationWillEnterForegroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:sharedOfflineStorage selector:@selector(pauseFileSource:) name:UIApplicationDidEnterBackgroundNotification object:nil]; -#endif [sharedOfflineStorage reloadPacks]; }); @@ -204,11 +200,19 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio } - (instancetype)init { + NSURL *cacheURL = [[self class] cacheURLIncludingSubdirectory:YES]; + NSString *cachePath = cacheURL.path ?: @""; + + NSString *assetPath = [NSBundle mainBundle].resourceURL.path; + + return [self initWithCachePath:cachePath assetPath:assetPath]; +} + + +- (instancetype)initWithCachePath:(NSString *)cachePath assetPath:(NSString *)assetPath { MGLInitializeRunLoop(); if (self = [super init]) { - NSURL *cacheURL = [[self class] cacheURLIncludingSubdirectory:YES]; - NSString *cachePath = cacheURL.path ?: @""; // Move the offline cache from v3.2.0-beta.1 to a location that can also // be used for ambient caching. @@ -224,7 +228,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio [[NSFileManager defaultManager] moveItemAtPath:subdirectorylessCacheURL.path toPath:cachePath error:NULL]; } - _mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String); + _mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, assetPath.UTF8String); // Observe for changes to the API base URL (and find out the current one). [[MGLNetworkConfiguration sharedManager] addObserver:self @@ -239,6 +243,12 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:NULL]; + +#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(unpauseFileSource:) name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseFileSource:) name:UIApplicationDidEnterBackgroundNotification object:nil]; +#endif + } return self; } @@ -347,7 +357,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio auto& regions = result.value(); packs = [NSMutableArray arrayWithCapacity:regions.size()]; for (auto ®ion : regions) { - MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region))]; + MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region)) offlineStorage:self]; [packs addObject:pack]; } } @@ -404,7 +414,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio } : nil]; } if (completion) { - MGLOfflinePack *pack = mbglOfflineRegion ? [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(mbglOfflineRegion.value()))] : nil; + MGLOfflinePack *pack = mbglOfflineRegion ? [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(mbglOfflineRegion.value())) offlineStorage:self] : nil; dispatch_async(dispatch_get_main_queue(), [&, completion, error, pack](void) { completion(pack, error); }); @@ -456,7 +466,11 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio } - (void)getPacksWithCompletionHandler:(void (^)(NSArray *packs, NSError * _Nullable error))completion { + + __typeof__(self) strongSelf = self; + self.mbglFileSource->listOfflineRegions([&, completion](mbgl::expected result) { + NSError *error; NSMutableArray *packs; if (!result) { @@ -467,7 +481,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio auto& regions = result.value(); packs = [NSMutableArray arrayWithCapacity:regions.size()]; for (auto ®ion : regions) { - MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region))]; + MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region)) offlineStorage:strongSelf]; [packs addObject:pack]; } } diff --git a/platform/darwin/src/MGLRendererConfiguration.h b/platform/darwin/src/MGLRendererConfiguration.h index ea13582488..96919e0593 100644 --- a/platform/darwin/src/MGLRendererConfiguration.h +++ b/platform/darwin/src/MGLRendererConfiguration.h @@ -16,7 +16,7 @@ MGL_EXPORT @property (class, nonatomic, readonly) MGLRendererConfiguration *currentConfiguration; /** The file source to use. Defaults to `mbgl::DefaultFileSource` */ -@property (nonatomic, readonly) mbgl::DefaultFileSource *fileSource; +//@property (nonatomic, readonly) mbgl::DefaultFileSource *fileSource; /** The GL context mode to use. Defaults to `mbgl::GLContextMode::Unique` */ @property (nonatomic, readonly) mbgl::GLContextMode contextMode; diff --git a/platform/darwin/src/MGLRendererConfiguration.mm b/platform/darwin/src/MGLRendererConfiguration.mm index 90778ea86d..769aab78ef 100644 --- a/platform/darwin/src/MGLRendererConfiguration.mm +++ b/platform/darwin/src/MGLRendererConfiguration.mm @@ -12,6 +12,7 @@ static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPr @interface MGLRendererConfiguration () @property (nonatomic, readwrite) BOOL perSourceCollisions; +//@property (nonatomic) MGLOfflineStorage *offlineStorage; @end @@ -25,10 +26,11 @@ static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPr return [self initWithPropertyDictionary:[[NSBundle mainBundle] infoDictionary]]; } -- (instancetype)initWithPropertyDictionary:(nonnull NSDictionary *)properties { +- (instancetype)initWithPropertyDictionary:(nonnull NSDictionary *)properties{ self = [super init]; if (self) { + // Set the collision behaviour. A value set in `NSUserDefaults.standardUserDefaults` // should override anything in the application's info.plist NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; @@ -57,9 +59,9 @@ static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPr return self; } -- (mbgl::DefaultFileSource *)fileSource { - return [MGLOfflineStorage sharedOfflineStorage].mbglFileSource; -} +//- (mbgl::DefaultFileSource *)fileSource { +// return self.offlineStorage.mbglFileSource; +//} - (mbgl::GLContextMode)contextMode { return mbgl::GLContextMode::Unique; diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift index 9d1d848868..9aaaf4664e 100644 --- a/platform/darwin/test/MGLDocumentationExampleTests.swift +++ b/platform/darwin/test/MGLDocumentationExampleTests.swift @@ -459,7 +459,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate { let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL, camera: camera, size: CGSize(width: 320, height: 480)) options.zoomLevel = 10 - let snapshotter = MGLMapSnapshotter(options: options) + let snapshotter = MGLMapSnapshotter(options: options, offlineStorage: MGLOfflineStorage.shared) snapshotter.start { (snapshot, error) in if let error = error { fatalError(error.localizedDescription) diff --git a/platform/ios/app/MBXSnapshotsViewController.m b/platform/ios/app/MBXSnapshotsViewController.m index 95d3251e2e..dd88d199d3 100644 --- a/platform/ios/app/MBXSnapshotsViewController.m +++ b/platform/ios/app/MBXSnapshotsViewController.m @@ -51,7 +51,8 @@ // Create and start the snapshotter __weak UIImageView *weakImageView = imageView; - MGLMapSnapshotter* snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options]; + MGLMapSnapshotter* snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options + offlineStorage:[MGLOfflineStorage sharedOfflineStorage]]; [snapshotter startWithCompletionHandler: ^(MGLMapSnapshot* snapshot, NSError *error) { if (error) { NSLog(@"Could not load snapshot: %@", [error localizedDescription]); diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 752a1a780b..81f9b70bbf 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -469,12 +469,15 @@ public: MGLRendererConfiguration *config = [MGLRendererConfiguration currentConfiguration]; _mbglThreadPool = mbgl::sharedThreadPool(); - auto renderer = std::make_unique(*_mbglView, config.scaleFactor, *config.fileSource, *_mbglThreadPool, config.contextMode, config.cacheDir, config.localFontFamilyName); + + mbgl::DefaultFileSource *fileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource; + + auto renderer = std::make_unique(*_mbglView, config.scaleFactor, *fileSource, *_mbglThreadPool, config.contextMode, config.cacheDir, config.localFontFamilyName); BOOL enableCrossSourceCollisions = !config.perSourceCollisions; _rendererFrontend = std::make_unique(std::move(renderer), self, *_mbglView); NSAssert(!_mbglMap, @"_mbglMap should be NULL"); - _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *[config fileSource], *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default, enableCrossSourceCollisions); + _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *fileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default, enableCrossSourceCollisions); // start paused if in IB if (_isTargetingInterfaceBuilder || background) { -- cgit v1.2.1