summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-03-05 18:00:11 -0800
committerMinh Nguyễn <mxn@1ec5.org>2016-03-10 17:08:58 -0800
commite36218a8668316e8c1b0bcc06d43dad31461615c (patch)
tree04d5e58ae0c4dea4b0a50e034a8a630564cb7a53 /platform/darwin
parent081ee9fbefbdb37f116a5bf2c0383586bce6608a (diff)
downloadqtlocation-mapboxgl-e36218a8668316e8c1b0bcc06d43dad31461615c.tar.gz
[osx] Added OS X support for offline downloads
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/include/MGLAccountManager.h49
-rw-r--r--platform/darwin/src/MGLAccountManager.m123
-rw-r--r--platform/darwin/src/MGLAccountManager_Private.h11
-rw-r--r--platform/darwin/src/MGLDownloadController.mm20
-rw-r--r--platform/darwin/src/MGLTilePyramidDownloadRegion.mm4
-rw-r--r--platform/darwin/src/NSBundle+MGLAdditions.h24
-rw-r--r--platform/darwin/src/NSBundle+MGLAdditions.m40
-rw-r--r--platform/darwin/src/NSProcessInfo+MGLAdditions.h13
-rw-r--r--platform/darwin/src/NSProcessInfo+MGLAdditions.m17
9 files changed, 299 insertions, 2 deletions
diff --git a/platform/darwin/include/MGLAccountManager.h b/platform/darwin/include/MGLAccountManager.h
new file mode 100644
index 0000000000..5cf729ef3a
--- /dev/null
+++ b/platform/darwin/include/MGLAccountManager.h
@@ -0,0 +1,49 @@
+#import <Foundation/Foundation.h>
+
+#import "MGLTypes.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ The MGLAccountManager object provides a global way to set a Mapbox API access
+ token, as well as other settings used framework-wide.
+ */
+@interface MGLAccountManager : NSObject
+
+#pragma mark Authorizing Access
+
+/**
+ Set the [Mapbox access token](https://www.mapbox.com/help/define-access-token/)
+ to be used by all instances of MGLMapView in the current application.
+
+ Mapbox-hosted vector tiles and styles require an API access token, which you
+ can obtain from the
+ [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). Access
+ tokens associate requests to Mapbox’s vector tile and style APIs with your
+ Mapbox account. They also deter other developers from using your styles without
+ your permission.
+
+ @param accessToken A Mapbox access token. Calling this method with a value of
+ `nil` has no effect.
+
+ @note You must set the access token before attempting to load any Mapbox-hosted
+ style. Therefore, you should generally set it before creating an instance of
+ MGLMapView. The recommended way to set an access token is to add an entry to
+ your application’s Info.plist file with the key `MGLMapboxAccessToken` and
+ the type String. Alternatively, you may call this method from your
+ application delegate’s `-applicationDidFinishLaunching:` method.
+ */
++ (void)setAccessToken:(nullable NSString *)accessToken;
+
+/**
+ Returns the
+ [Mapbox access token](https://www.mapbox.com/help/define-access-token/) in use
+ by instances of MGLMapView in the current application.
+ */
++ (nullable NSString *)accessToken;
+
++ (BOOL)mapboxMetricsEnabledSettingShownInApp __attribute__((deprecated("Telemetry settings are now always shown in the ℹ️ menu.")));
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLAccountManager.m b/platform/darwin/src/MGLAccountManager.m
new file mode 100644
index 0000000000..bfaf9faae9
--- /dev/null
+++ b/platform/darwin/src/MGLAccountManager.m
@@ -0,0 +1,123 @@
+#import "MGLAccountManager_Private.h"
+#import "MGLMapView.h"
+#import "NSBundle+MGLAdditions.h"
+#import "NSProcessInfo+MGLAdditions.h"
+#import "NSString+MGLAdditions.h"
+
+#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+#import "MGLMapboxEvents.h"
+
+#import "FABKitProtocol.h"
+#import "Fabric+FABKits.h"
+
+@interface MGLAccountManager () <FABKit>
+
+@property (atomic) NSString *accessToken;
+
+@end
+#else
+@interface MGLAccountManager ()
+
+@property (atomic) NSString *accessToken;
+
+@end
+#endif
+
+@implementation MGLAccountManager
+
+#pragma mark - Internal
+
++ (void)load {
+ // Read the initial configuration from Info.plist.
+ NSString *accessToken = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLMapboxAccessToken"];
+ if (accessToken.length) {
+ self.accessToken = accessToken;
+ }
+}
+
++ (instancetype)sharedManager {
+ if (NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent) {
+ return nil;
+ }
+ static dispatch_once_t onceToken;
+ static MGLAccountManager *_sharedManager;
+ void (^setupBlock)() = ^{
+ dispatch_once(&onceToken, ^{
+ _sharedManager = [[self alloc] init];
+ });
+ };
+ if (![[NSThread currentThread] isMainThread]) {
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ setupBlock();
+ });
+ } else {
+ setupBlock();
+ }
+ return _sharedManager;
+}
+
++ (BOOL)mapboxMetricsEnabledSettingShownInApp {
+ NSLog(@"mapboxMetricsEnabledSettingShownInApp is no longer necessary; the Mapbox iOS SDK has changed to always provide a telemetry setting in-app.");
+ return YES;
+}
+
++ (void)setAccessToken:(NSString *)accessToken {
+ accessToken = [accessToken stringByTrimmingCharactersInSet:
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if (!accessToken.length) {
+ return;
+ }
+
+ [MGLAccountManager sharedManager].accessToken = accessToken;
+
+#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+ // Update MGLMapboxEvents
+ // NOTE: This is (likely) the initial setup of MGLMapboxEvents
+ [MGLMapboxEvents sharedManager];
+#endif
+}
+
++ (NSString *)accessToken {
+ return [MGLAccountManager sharedManager].accessToken;
+}
+
+#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+
+#pragma mark - Fabric
+
++ (NSString *)bundleIdentifier {
+ return [NSBundle mgl_frameworkBundleIdentifier];
+}
+
++ (NSString *)kitDisplayVersion {
+ return [NSBundle mgl_frameworkInfoDictionary][@"CFBundleShortVersionString"];
+}
+
++ (void)initializeIfNeeded {
+ Class fabric = NSClassFromString(@"Fabric");
+
+ if (fabric) {
+ NSDictionary *configuration = [fabric configurationDictionaryForKitClass:[MGLAccountManager class]];
+ if (!configuration || !configuration[@"accessToken"]) {
+ NSLog(@"Configuration dictionary returned by Fabric was nil or doesn’t have accessToken. Can’t initialize MGLAccountManager.");
+ return;
+ }
+ [self setAccessToken:configuration[@"accessToken"]];
+ MGLAccountManager *sharedAccountManager = [self sharedManager];
+ NSLog(@"MGLAccountManager was initialized with access token: %@", sharedAccountManager.accessToken);
+ } else {
+ NSLog(@"MGLAccountManager is used in a project that doesn’t have Fabric.");
+ }
+
+ // https://github.com/mapbox/mapbox-gl-native/issues/2966
+ mgl_linkBundleCategory();
+ mgl_linkStringCategory();
+ mgl_linkProcessInfoCategory();
+
+ // https://github.com/mapbox/mapbox-gl-native/issues/3113
+ [MGLMapView class];
+}
+
+#endif
+
+@end
diff --git a/platform/darwin/src/MGLAccountManager_Private.h b/platform/darwin/src/MGLAccountManager_Private.h
new file mode 100644
index 0000000000..655af08f20
--- /dev/null
+++ b/platform/darwin/src/MGLAccountManager_Private.h
@@ -0,0 +1,11 @@
+#import "MGLAccountManager.h"
+
+@interface MGLAccountManager (Private)
+
+/// Returns the shared instance of the `MGLAccountManager` class.
++ (instancetype)sharedManager;
+
+/// The current global access token.
+@property (atomic) NSString *accessToken;
+
+@end
diff --git a/platform/darwin/src/MGLDownloadController.mm b/platform/darwin/src/MGLDownloadController.mm
index e4dd273032..95eae86b53 100644
--- a/platform/darwin/src/MGLDownloadController.mm
+++ b/platform/darwin/src/MGLDownloadController.mm
@@ -29,9 +29,25 @@
- (instancetype)initWithFileName:(NSString *)fileName {
if (self = [super init]) {
+#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *fileCachePath = [paths.firstObject stringByAppendingPathComponent:fileName];
- _mbglFileSource = new mbgl::DefaultFileSource(fileCachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String);
+ NSString *cachePath = [paths.firstObject stringByAppendingPathComponent:fileName];
+#elif TARGET_OS_MAC
+ NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
+ inDomain:NSUserDomainMask
+ appropriateForURL:nil
+ create:YES
+ error:nil];
+ cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:
+ [NSBundle mainBundle].bundleIdentifier];
+ [[NSFileManager defaultManager] createDirectoryAtURL:cacheDirectoryURL
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:nil];
+ NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:fileName];
+ NSString *cachePath = cacheURL ? cacheURL.path : @"";
+#endif
+ _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).
[[MGLAccountManager sharedManager] addObserver:self
diff --git a/platform/darwin/src/MGLTilePyramidDownloadRegion.mm b/platform/darwin/src/MGLTilePyramidDownloadRegion.mm
index 942450c0c2..94c0ac6358 100644
--- a/platform/darwin/src/MGLTilePyramidDownloadRegion.mm
+++ b/platform/darwin/src/MGLTilePyramidDownloadRegion.mm
@@ -1,5 +1,9 @@
#import "MGLTilePyramidDownloadRegion.h"
+#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+ #import <Cocoa/Cocoa.h>
+#endif
+
#import "MGLDownloadRegion_Private.h"
#import "MGLGeometry_Private.h"
#import "MGLStyle.h"
diff --git a/platform/darwin/src/NSBundle+MGLAdditions.h b/platform/darwin/src/NSBundle+MGLAdditions.h
new file mode 100644
index 0000000000..52ef7fbfa7
--- /dev/null
+++ b/platform/darwin/src/NSBundle+MGLAdditions.h
@@ -0,0 +1,24 @@
+#import <Foundation/Foundation.h>
+
+#import "MGLTypes.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+void mgl_linkBundleCategory();
+
+@interface NSBundle (MGLAdditions)
+
+/// Returns the bundle containing the SDK’s classes and Info.plist file.
++ (instancetype)mgl_frameworkBundle;
+
++ (nullable NSString *)mgl_frameworkBundleIdentifier;
+
++ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary;
+
+/// The relative path to the directory containing the SDK’s resource files, or
+/// `nil` if the files are located directly within the bundle’s root directory.
+@property (readonly, copy, nullable) NSString *mgl_resourcesDirectory;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSBundle+MGLAdditions.m b/platform/darwin/src/NSBundle+MGLAdditions.m
new file mode 100644
index 0000000000..e1f3e7c720
--- /dev/null
+++ b/platform/darwin/src/NSBundle+MGLAdditions.m
@@ -0,0 +1,40 @@
+#import "NSBundle+MGLAdditions.h"
+
+#import "MGLAccountManager.h"
+
+void mgl_linkBundleCategory() {}
+
+@implementation NSBundle (MGLAdditions)
+
++ (instancetype)mgl_frameworkBundle {
+ NSBundle *bundle = [self bundleForClass:[MGLAccountManager class]];
+ if (![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"] && !bundle.mgl_resourcesDirectory) {
+ // For static frameworks, the bundle is the containing application
+ // bundle but the resources are still in the framework bundle.
+ bundle = [NSBundle bundleWithPath:[bundle.privateFrameworksPath
+ stringByAppendingPathComponent:@"Mapbox.framework"]];
+ }
+ return bundle;
+}
+
++ (nullable NSString *)mgl_frameworkBundleIdentifier {
+ return self.mgl_frameworkInfoDictionary[@"CFBundleIdentifier"];
+}
+
++ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary {
+ NSBundle *bundle = self.mgl_frameworkBundle;
+ if (bundle.mgl_resourcesDirectory) {
+ NSString *infoPlistPath = [bundle pathForResource:@"Info"
+ ofType:@"plist"
+ inDirectory:bundle.mgl_resourcesDirectory];
+ return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
+ } else {
+ return bundle.infoDictionary;
+ }
+}
+
+- (NSString *)mgl_resourcesDirectory {
+ return [self pathForResource:@"Mapbox" ofType:@"bundle"] ? @"Mapbox.bundle" : nil;
+}
+
+@end
diff --git a/platform/darwin/src/NSProcessInfo+MGLAdditions.h b/platform/darwin/src/NSProcessInfo+MGLAdditions.h
new file mode 100644
index 0000000000..ea231d4e6a
--- /dev/null
+++ b/platform/darwin/src/NSProcessInfo+MGLAdditions.h
@@ -0,0 +1,13 @@
+#import <Foundation/Foundation.h>
+
+void mgl_linkProcessInfoCategory();
+
+@interface NSProcessInfo (MGLAdditions)
+
+/**
+ Returns YES if the current process is Interface Builder’s helper process for
+ rendering designables.
+ */
+- (BOOL)mgl_isInterfaceBuilderDesignablesAgent;
+
+@end
diff --git a/platform/darwin/src/NSProcessInfo+MGLAdditions.m b/platform/darwin/src/NSProcessInfo+MGLAdditions.m
new file mode 100644
index 0000000000..3da2bf73ed
--- /dev/null
+++ b/platform/darwin/src/NSProcessInfo+MGLAdditions.m
@@ -0,0 +1,17 @@
+#import "NSProcessInfo+MGLAdditions.h"
+
+void mgl_linkProcessInfoCategory() {}
+
+#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+ static NSString * const MGLIBDesignablesAgentProcessName = @"IBDesignablesAgentCocoaTouch";
+#elif TARGET_OS_MAC
+ static NSString * const MGLIBDesignablesAgentProcessName = @"IBDesignablesAgent";
+#endif
+
+@implementation NSProcessInfo (MGLAdditions)
+
+- (BOOL)mgl_isInterfaceBuilderDesignablesAgent {
+ return [self.processName isEqualToString:MGLIBDesignablesAgentProcessName];
+}
+
+@end