Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Unify offline and ambient caches #4377

Merged
merged 1 commit into from
Mar 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ Known issues:
- Black Screen On Ice Cream Sandwich and Jelly Bean devices ([#2802](https://github.com/mapbox/mapbox-gl-native/issues/2802))
- Resolved in 2.2.0

## iOS master
## iOS 3.2.0

- Offline packs can now be downloaded to allow users to view specific regions of the map offline. A new MGLOfflineStorage class provides APIs for managing MGLOfflinePacks. ([#4221](https://github.com/mapbox/mapbox-gl-native/pull/4221))
- Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377))
- The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275))
- The map no longer recoils when panning quickly at low zoom levels. ([#4214](https://github.com/mapbox/mapbox-gl-native/pull/4214))
- An icon laid out along a line no longer appears if it would extend past the end of the line. Some one-way arrows no longer point the wrong way. ([#3839](https://github.com/mapbox/mapbox-gl-native/pull/3839))
Expand Down
41 changes: 35 additions & 6 deletions platform/darwin/src/MGLOfflineStorage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,20 @@ + (instancetype)sharedOfflineStorage {
static dispatch_once_t onceToken;
static MGLOfflineStorage *sharedOfflineStorage;
dispatch_once(&onceToken, ^{
sharedOfflineStorage = [[self alloc] initWithFileName:@"offline.db"];
sharedOfflineStorage = [[self alloc] initWithFileName:@"cache.db"];
});
return sharedOfflineStorage;
}

// This method can’t be called -init, because that selector has been marked
// unavailable in MGLOfflineStorage.h.
- (instancetype)initWithFileName:(NSString *)fileName {
if (self = [super init]) {
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *cachePath = [paths.firstObject stringByAppendingPathComponent:fileName];
#elif TARGET_OS_MAC
NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
// Place the cache in a location specific to the application, so that
// packs downloaded by other applications don’t count toward this
// application’s limits.
// ~/Library/Application Support/tld.app.bundle.id/cache.db
NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
Expand All @@ -46,7 +48,34 @@ - (instancetype)initWithFileName:(NSString *)fileName {
error:nil];
NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:fileName];
NSString *cachePath = cacheURL ? cacheURL.path : @"";

// Move the offline cache from v3.2.0-beta.1 to a location that can also
// be used for ambient caching.
NSString *legacyCacheFileName = @"offline.db";
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
// ~/Documents/offline.db
NSArray *legacyPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:legacyCacheFileName];
#elif TARGET_OS_MAC
// ~/Library/Caches/tld.app.bundle.id/offline.db
NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:nil];
legacyCacheDirectoryURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:
[NSBundle mainBundle].bundleIdentifier];
[[NSFileManager defaultManager] createDirectoryAtURL:legacyCacheDirectoryURL
withIntermediateDirectories:YES
attributes:nil
error:nil];
NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:legacyCacheFileName];
NSString *legacyCachePath = legacyCacheURL ? legacyCacheURL.path : @"";
#endif
if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath]) {
[[NSFileManager defaultManager] moveItemAtPath:legacyCachePath toPath:cachePath error:NULL];
}

_mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String);

// Observe for changes to the global access token (and find out the current one).
Expand Down
42 changes: 8 additions & 34 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
#import "Mapbox.h"
#import "../../darwin/src/MGLGeometry_Private.h"
#import "../../darwin/src/MGLMultiPoint_Private.h"
#import "../../darwin/src/MGLOfflineStorage_Private.h"

#import "NSBundle+MGLAdditions.h"
#import "NSString+MGLAdditions.h"
#import "NSProcessInfo+MGLAdditions.h"
#import "NSException+MGLAdditions.h"
#import "MGLUserLocationAnnotationView.h"
#import "MGLUserLocation_Private.h"
#import "MGLAccountManager_Private.h"
#import "MGLAnnotationImage_Private.h"
#import "MGLMapboxEvents.h"
#import "MGLCompactCalloutView.h"
Expand Down Expand Up @@ -187,7 +187,6 @@ @implementation MGLMapView
{
mbgl::Map *_mbglMap;
MBGLView *_mbglView;
mbgl::DefaultFileSource *_mbglFileSource;

BOOL _opaque;

Expand Down Expand Up @@ -303,32 +302,22 @@ - (void)commonInit
// setup mbgl view
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
_mbglView = new MBGLView(self, scaleFactor);

// setup mbgl cache & file source
NSString *fileCachePath = @"";

// Delete the pre-offline ambient cache at ~/Library/Caches/cache.db.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
if ([paths count] != 0) {
NSString *libraryDirectory = [paths objectAtIndex:0];
fileCachePath = [libraryDirectory stringByAppendingPathComponent:@"cache.db"];
}
_mbglFileSource = new mbgl::DefaultFileSource([fileCachePath UTF8String], [[[[NSBundle mainBundle] resourceURL] path] UTF8String]);
NSString *fileCachePath = [paths.firstObject stringByAppendingPathComponent:@"cache.db"];
[[NSFileManager defaultManager] removeItemAtPath:fileCachePath error:NULL];

// setup mbgl map
_mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None);
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
_mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None);

// start paused if in IB
if (_isTargetingInterfaceBuilder || background) {
self.dormant = YES;
_mbglMap->pause();
}

// Observe for changes to the global access token (and find out the current one).
[[MGLAccountManager sharedManager] addObserver:self
forKeyPath:@"accessToken"
options:(NSKeyValueObservingOptionInitial |
NSKeyValueObservingOptionNew)
context:NULL];

// Notify map object when network reachability status changes.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
Expand Down Expand Up @@ -506,7 +495,6 @@ - (void)reachabilityChanged:(NSNotification *)notification
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"];
[_attributionButton removeObserver:self forKeyPath:@"hidden"];

[self validateDisplayLink];
Expand All @@ -517,12 +505,6 @@ - (void)dealloc
_mbglMap = nullptr;
}

if (_mbglFileSource)
{
delete _mbglFileSource;
_mbglFileSource = nullptr;
}

if (_mbglView)
{
delete _mbglView;
Expand Down Expand Up @@ -1606,15 +1588,7 @@ - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(__unused void *)context
{
// Synchronize mbgl::Map’s access token with the global one in MGLAccountManager.
if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager])
{
NSString *accessToken = change[NSKeyValueChangeNewKey];
if (![accessToken isKindOfClass:[NSNull class]]) {
_mbglFileSource->setAccessToken((std::string)[accessToken UTF8String]);
}
}
else if ([keyPath isEqualToString:@"hidden"] && object == _attributionButton)
if ([keyPath isEqualToString:@"hidden"] && object == _attributionButton)
{
NSNumber *hiddenNumber = change[NSKeyValueChangeNewKey];
BOOL attributionButtonWasHidden = [hiddenNumber boolValue];
Expand Down
60 changes: 19 additions & 41 deletions platform/osx/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
#import "MGLOpenGLLayer.h"
#import "MGLStyle.h"

#import "../../darwin/src/MGLAccountManager_Private.h"
#import "../../darwin/src/MGLGeometry_Private.h"
#import "../../darwin/src/MGLMultiPoint_Private.h"
#import "../../darwin/src/MGLOfflineStorage_Private.h"

#import "MGLAccountManager.h"
#import "MGLMapCamera.h"
#import "MGLPolygon.h"
#import "MGLPolyline.h"
Expand Down Expand Up @@ -151,7 +152,6 @@ @implementation MGLMapView {
/// Cross-platform map view controller.
mbgl::Map *_mbglMap;
MGLMapViewImpl *_mbglView;
mbgl::DefaultFileSource *_mbglFileSource;

NSPanGestureRecognizer *_panGestureRecognizer;
NSMagnificationGestureRecognizer *_magnificationGestureRecognizer;
Expand Down Expand Up @@ -232,36 +232,25 @@ - (void)commonInit {
// Set up cross-platform controllers and resources.
_mbglView = new MGLMapViewImpl(self, [NSScreen mainScreen].backingScaleFactor);

// Place the cache in a location that can be shared among all the
// applications that embed the Mapbox OS X SDK.
NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:nil];
cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:
[[NSBundle mgl_frameworkBundle] bundleIdentifier]];
[[NSFileManager defaultManager] createDirectoryAtURL:cacheDirectoryURL
withIntermediateDirectories:YES
attributes:nil
error:nil];
NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:@"cache.db"];
NSString *cachePath = cacheURL ? cacheURL.path : @"";
_mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [[[[NSBundle mainBundle] resourceURL] path] UTF8String]);

_mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None);
// Delete the pre-offline ambient cache at
// ~/Library/Caches/com.mapbox.sdk.ios/cache.db.
NSURL *cachesDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:NO
error:nil];
cachesDirectoryURL = [cachesDirectoryURL URLByAppendingPathComponent:
[NSBundle mgl_frameworkBundle].bundleIdentifier];
NSURL *legacyCacheURL = [cachesDirectoryURL URLByAppendingPathComponent:@"cache.db"];
[[NSFileManager defaultManager] removeItemAtURL:legacyCacheURL error:NULL];

mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
_mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None);

// Install the OpenGL layer. Interface Builder’s synchronous drawing means
// we can’t display a map, so don’t even bother to have a map layer.
self.layer = _isTargetingInterfaceBuilder ? [CALayer layer] : [MGLOpenGLLayer layer];

// Observe for changes to the global access token (and find out the current one).
[[MGLAccountManager sharedManager] addObserver:self
forKeyPath:@"accessToken"
options:(NSKeyValueObservingOptionInitial |
NSKeyValueObservingOptionNew)
context:NULL];

// Notify map object when network reachability status changes.
MGLReachability *reachability = [MGLReachability reachabilityForInternetConnection];
reachability.reachableBlock = ^(MGLReachability *) {
Expand Down Expand Up @@ -443,7 +432,6 @@ - (void)updateAttributionView {
}

- (void)dealloc {
[[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"];
[self.window removeObserver:self forKeyPath:@"contentLayoutRect"];
[self.window removeObserver:self forKeyPath:@"titlebarAppearsTransparent"];

Expand All @@ -455,25 +443,15 @@ - (void)dealloc {
delete _mbglMap;
_mbglMap = nullptr;
}
if (_mbglFileSource) {
delete _mbglFileSource;
_mbglFileSource = nullptr;
}
if (_mbglView) {
delete _mbglView;
_mbglView = nullptr;
}
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(__unused void *)context {
// Synchronize mbgl::Map’s access token with the global one in MGLAccountManager.
if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager]) {
NSString *accessToken = change[NSKeyValueChangeNewKey];
if (![accessToken isKindOfClass:[NSNull class]]) {
_mbglFileSource->setAccessToken((std::string)accessToken.UTF8String);
}
} else if ([keyPath isEqualToString:@"contentLayoutRect"] ||
[keyPath isEqualToString:@"titlebarAppearsTransparent"]) {
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(__unused id)object change:(__unused NSDictionary *)change context:(__unused void *)context {
if ([keyPath isEqualToString:@"contentLayoutRect"] ||
[keyPath isEqualToString:@"titlebarAppearsTransparent"]) {
[self adjustContentInsets];
}
}
Expand Down