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

Grab app-wide data from Info.plist #1553

Merged
merged 8 commits into from
May 20, 2015
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
1 change: 1 addition & 0 deletions gyp/platform-ios.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
'../platform/ios/MGLFileCache.h',
'../platform/ios/MGLFileCache.mm',
'../include/mbgl/ios/MGLAccountManager.h',
'../platform/ios/MGLAccountManager_Private.h',
'../platform/ios/MGLAccountManager.m',
'../include/mbgl/ios/MGLAnnotation.h',
'../include/mbgl/ios/MGLUserLocation.h',
Expand Down
2 changes: 1 addition & 1 deletion include/mbgl/ios/MGLAccountManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

/** Certain Mapbox plans require the collection of user metrics. If you aren't using a preference switch in an existing or new `Settings.bundle` in your application, set this value to `YES` to indicate that you are providing a metrics opt-out for users within your app's interface directly.
* @param showsOptOut Whether your application's interface provides a user opt-out preference. The default value is `NO`, meaning a `Settings.bundle` is expected for providing a user opt-out preference. */
+ (void)setMapboxMetricsEnabledSettingShownInApp:(BOOL)showsOptOut;
+ (void)setMapboxMetricsEnabledSettingShownInApp:(BOOL)showsOptOut __attribute__((unavailable("Set MGLMapboxMetricsEnabledSettingShownInApp in Info.plist.")));

/** Whether in-app user metrics opt-out is configured. If set to the default value of `NO`, a user opt-out preference is expected in a `Settings.bundle` that shows in the application's section within the system Settings app. */
+ (BOOL)mapboxMetricsEnabledSettingShownInApp;
Expand Down
27 changes: 11 additions & 16 deletions include/mbgl/ios/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,25 @@ IB_DESIGNABLE

/** @name Initializing a Map View */

/** Initialize a map view with the default style, given frame, and access token set in MapboxGL singleton.
* @param frame The frame with which to initialize the map view.
* @return An initialized map view, or `nil` if the map view was unable to be initialized. */
/** Initializes and returns a newly allocated map view with the specified frame and the default style.
* @param frame The frame for the view, measured in points.
* @return An initialized map view or `nil` if the map view couldn’t be created. */
- (instancetype)initWithFrame:(CGRect)frame;
- (instancetype)initWithFrame:(CGRect)frame accessToken:(NSString *)accessToken __attribute__((unavailable("Use -initWithFrame:. Set MGLMapboxAccessToken in the Info.plist or call +[MGLAccountManager setAccessToken:].")));

/** Initialize a map view with the default style and a given frame and access token.
* @param frame The frame with which to initialize the map view.
* @param accessToken A Mapbox API access token.
* @return An initialized map view, or `nil` if the map view was unable to be initialized. */
- (instancetype)initWithFrame:(CGRect)frame accessToken:(NSString *)accessToken;

/** Initialize a map view with a given frame, access token, and style URL.
* @param frame The frame with which to initialize the map view.
* @param accessToken A Mapbox API access token.
* @param styleURL The map style URL to use. Can be either an HTTP/HTTPS URL or a Mapbox map ID style URL (`mapbox://<user.style>`).
* @return An initialized map view, or `nil` if the map view was unable to be initialized. */
- (instancetype)initWithFrame:(CGRect)frame accessToken:(NSString *)accessToken styleURL:(NSURL *)styleURL;
/** Initializes and returns a newly allocated map view with the specified frame and style URL.
* @param frame The frame for the view, measured in points.
* @param styleURL The map style URL to use. Can be either an HTTP/HTTPS URL or a Mapbox map ID style URL (`mapbox://<user.style>`).
* @return An initialized map view or `nil` if the map view couldn’t be created. */
- (instancetype)initWithFrame:(CGRect)frame styleURL:(NSURL *)styleURL;
- (instancetype)initWithFrame:(CGRect)frame accessToken:(NSString *)accessToken styleURL:(NSURL *)styleURL __attribute__((unavailable("Use -initWithFrame:styleURL:. Set MGLMapboxAccessToken in the Info.plist or call +[MGLAccountManager setAccessToken:].")));

#pragma mark - Authorizing Access

/** @name Authorizing Access */

/** Mapbox API access token for the map view. */
@property (nonatomic) NSString *accessToken;
@property (nonatomic) NSString *accessToken __attribute__((unavailable("Use +[MGLAccountManager accessToken] and +[MGLAccountManager setAccessToken:].")));

#pragma mark - Managing Constraints

Expand Down
32 changes: 15 additions & 17 deletions ios/app/MBXAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,22 @@ @implementation MBXAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Set Access Token
NSString *accessToken = [[NSProcessInfo processInfo] environment][@"MAPBOX_ACCESS_TOKEN"];
if (accessToken) {
// Store to preferences so that we can launch the app later on without having to specify
// token.
[[NSUserDefaults standardUserDefaults] setObject:accessToken forKey:@"access_token"];
} else {
// Try to retrieve from preferences, maybe we've stored them there previously and can reuse
// the token.
accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"];
// Set access token, unless MGLAccountManager already read it in from Info.plist.
if ( ! [MGLAccountManager accessToken]) {
NSString *accessToken = [[NSProcessInfo processInfo] environment][@"MAPBOX_ACCESS_TOKEN"];
if (accessToken) {
// Store to preferences so that we can launch the app later on without having to specify
// token.
[[NSUserDefaults standardUserDefaults] setObject:accessToken forKey:@"access_token"];
} else {
// Try to retrieve from preferences, maybe we've stored them there previously and can reuse
// the token.
accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"];
}
if ( ! accessToken) NSLog(@"No access token set. Mapbox vector tiles won't work.");

[MGLAccountManager setAccessToken:accessToken];
}
if ( ! accessToken) NSLog(@"No access token set. Mapbox vector tiles won't work.");

// Signal To SDK That Opt Out Is In App UI
// [MGLAccountManager setMapboxMetricsEnabledSettingShownInApp:YES];

// Start Mapbox GL SDK
[MGLAccountManager setAccessToken:accessToken];

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[MBXViewController new]];
Expand Down
17 changes: 14 additions & 3 deletions platform/ios/MGLAccountManager.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#import <Foundation/Foundation.h>

#import "MGLAccountManager.h"
#import "MGLAccountManager_Private.h"
#import "MGLMapboxEvents_Private.h"
#import "NSProcessInfo+MGLAdditions.h"

Expand All @@ -14,6 +14,16 @@ @interface MGLAccountManager()

@implementation MGLAccountManager

+ (void)load {
// Read initial configuration from Info.plist.
NSBundle *bundle = [NSBundle bundleForClass:self];
self.accessToken = [bundle objectForInfoDictionaryKey:@"MGLMapboxAccessToken"];
NSNumber *shownInAppNumber = [bundle objectForInfoDictionaryKey:@"MGLMapboxMetricsEnabledSettingShownInApp"];
if (shownInAppNumber) {
[MGLAccountManager sharedManager].mapboxMetricsEnabledSettingShownInApp = [shownInAppNumber boolValue];
}
}

// Can be called from any thread.
//
+ (instancetype) sharedManager {
Expand All @@ -25,7 +35,6 @@ + (instancetype) sharedManager {
void (^setupBlock)() = ^{
dispatch_once(&onceToken, ^{
_sharedManager = [[self alloc] init];
_sharedManager.mapboxMetricsEnabledSettingShownInApp = NO;
});
};
if ( ! [[NSThread currentThread] isMainThread]) {
Expand All @@ -48,7 +57,9 @@ + (BOOL) mapboxMetricsEnabledSettingShownInApp {
}

+ (void) setAccessToken:(NSString *) accessToken {
[[MGLAccountManager sharedManager] setAccessToken:accessToken];
if ( ! [accessToken length]) return;

[MGLAccountManager sharedManager].accessToken = accessToken;

// Update MGLMapboxEvents
// NOTE: This is (likely) the initial setup of MGLMapboxEvents
Expand Down
10 changes: 10 additions & 0 deletions platform/ios/MGLAccountManager_Private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#import "MGLAccountManager.h"

@interface MGLAccountManager (Private)

/** Returns the shared instance of the `MGLAccountManager` class. */
+ (instancetype)sharedManager;

@property (atomic) NSString *accessToken;

@end
43 changes: 27 additions & 16 deletions platform/ios/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#import "NSString+MGLAdditions.h"
#import "NSProcessInfo+MGLAdditions.h"
#import "NSException+MGLAdditions.h"
#import "MGLAccountManager.h"
#import "MGLAccountManager_Private.h"
#import "MGLAnnotation.h"
#import "MGLUserLocationAnnotationView.h"
#import "MGLUserLocation_Private.h"
Expand Down Expand Up @@ -113,25 +113,18 @@ - (instancetype)initWithFrame:(CGRect)frame
if (self && [self commonInit])
{
self.styleURL = nil;
self.accessToken = [MGLAccountManager accessToken];
return self;
}

return nil;
}

- (instancetype)initWithFrame:(CGRect)frame accessToken:(NSString *)accessToken
{
return [self initWithFrame:frame accessToken:accessToken styleURL:nil];
}

- (instancetype)initWithFrame:(CGRect)frame accessToken:(NSString *)accessToken styleURL:(NSURL *)styleURL
- (instancetype)initWithFrame:(CGRect)frame styleURL:(NSURL *)styleURL
{
self = [super initWithFrame:frame];

if (self && [self commonInit])
{
self.accessToken = accessToken;
self.styleURL = styleURL;
}

Expand All @@ -153,18 +146,18 @@ - (instancetype)initWithCoder:(NSCoder *)decoder

- (NSString *)accessToken
{
return @(_mbglMap->getAccessToken().c_str()).mgl_stringOrNilIfEmpty;
NSAssert(NO, @"-[MGLMapView accessToken] has been removed. Use +[MGLAccountManager accessToken] or get MGLMapboxAccessToken from the Info.plist.");
return nil;
}

- (void)setAccessToken:(NSString *)accessToken
{
_mbglMap->setAccessToken(accessToken ? (std::string)[accessToken UTF8String] : "");
[MGLAccountManager setAccessToken:accessToken.mgl_stringOrNilIfEmpty];
NSAssert(NO, @"-[MGLMapView setAccessToken:] has been replaced by +[MGLAccountManager setAccessToken:].\n\nIf you previously set this access token in a storyboard inspectable, select the MGLMapView in Interface Builder and delete the “accessToken” entry from the User Defined Runtime Attributes section of the Identity inspector. Then go to the Info.plist file and set MGLMapboxAccessToken to “%@”.", accessToken);
}

+ (NSSet *)keyPathsForValuesAffectingStyleURL
{
return [NSSet setWithObjects:@"mapID", @"accessToken", nil];
return [NSSet setWithObjects:@"mapID", nil];
}

- (NSURL *)styleURL
Expand Down Expand Up @@ -273,6 +266,13 @@ - (BOOL)commonInit
}
_mbglMap->resize(self.bounds.size.width, self.bounds.size.height, _glView.contentScaleFactor);

// 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 @@ -413,6 +413,7 @@ - (void)dealloc
[_regionChangeDelegateQueue cancelAllOperations];

[[NSNotificationCenter defaultCenter] removeObserver:self];
[[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"];

if (_mbglMap)
{
Expand Down Expand Up @@ -1295,6 +1296,16 @@ - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSIn

#pragma mark - Properties -

- (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];
_mbglMap->setAccessToken(accessToken ? (std::string)[accessToken UTF8String] : "");
}
}

+ (NSSet *)keyPathsForValuesAffectingZoomEnabled
{
return [NSSet setWithObject:@"allowsZooming"];
Expand Down Expand Up @@ -1556,7 +1567,7 @@ - (NSArray *)bundledStyleURLs

+ (NSSet *)keyPathsForValuesAffectingMapID
{
return [NSSet setWithObjects:@"styleURL", @"accessToken", nil];
return [NSSet setWithObjects:@"styleURL", nil];
}

- (NSString *)mapID
Expand Down Expand Up @@ -2494,7 +2505,7 @@ - (void)prepareForInterfaceBuilder
self.layer.borderColor = [UIColor colorWithWhite:184/255. alpha:1].CGColor;
self.layer.borderWidth = 1;

if (self.accessToken)
if ([MGLAccountManager accessToken])
{
self.layer.backgroundColor = [UIColor colorWithRed:59/255.
green:178/255.
Expand Down Expand Up @@ -2559,7 +2570,7 @@ - (void)prepareForInterfaceBuilder

// More explanation
UILabel *explanationLabel2 = [[UILabel alloc] init];
explanationLabel2.text = @"and enter it into the Access Token field in the Attributes inspector.";
explanationLabel2.text = @"and set it as the value of MGLMapboxAccessToken in the Info.plist file.";
explanationLabel2.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
explanationLabel2.numberOfLines = 0;
explanationLabel2.translatesAutoresizingMaskIntoConstraints = NO;
Expand Down
6 changes: 4 additions & 2 deletions platform/ios/MGLMapboxEvents.m
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,10 @@ @implementation MGLMapboxEvents {

+ (void)initialize {
if (self == [MGLMapboxEvents class]) {
NSBundle *bundle = [NSBundle bundleForClass:self];
NSNumber *accountTypeNumber = [bundle objectForInfoDictionaryKey:@"MGLMapboxAccountType"];
[[NSUserDefaults standardUserDefaults] registerDefaults:@{
@"MGLMapboxAccountType": @0,
@"MGLMapboxAccountType": accountTypeNumber ? accountTypeNumber : @0,
@"MGLMapboxMetricsEnabled": @YES,
}];
}
Expand Down Expand Up @@ -213,7 +215,7 @@ - (instancetype) init {
}
}

NSAssert(defaultEnabledValue, @"End users must be able to opt out of Metrics in your app, either inside Settings (via Settings.bundle) or inside this app. If you implement the opt-out control inside this app, disable this assertion by setting [MGLAccountManager setMapboxMetricsEnabledSettingShownInApp:YES] before the app initializes any Mapbox GL classes.");
NSAssert(defaultEnabledValue, @"End users must be able to opt out of Metrics in your app, either inside Settings (via Settings.bundle) or inside this app. If you implement the opt-out control inside this app, disable this assertion by setting MGLMapboxMetricsEnabledSettingShownInApp to YES in Info.plist.");
[[NSUserDefaults standardUserDefaults] registerDefaults:@{
@"MGLMapboxMetricsEnabled": defaultEnabledValue,
}];
Expand Down