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

MapboxGL Startup Infrastructure #1329

Merged
merged 10 commits into from
May 5, 2015
2 changes: 2 additions & 0 deletions gyp/platform-ios.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
'../platform/ios/MGLMapView.mm',
'../platform/ios/MGLFileCache.h',
'../platform/ios/MGLFileCache.mm',
'../include/mbgl/ios/MGLAccountManager.h',
'../platform/ios/MGLAccountManager.m',
'../include/mbgl/ios/MGLAnnotation.h',
'../include/mbgl/ios/MGLUserLocation.h',
'../platform/ios/MGLUserLocation_Private.h',
Expand Down
6 changes: 6 additions & 0 deletions include/mbgl/ios/MGLAccountManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@interface MGLAccountManager : NSObject

+ (void) setAccessToken:(NSString *) accessToken;
+ (NSString *) accessToken;

@end
7 changes: 5 additions & 2 deletions include/mbgl/ios/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ 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. */
- (instancetype)initWithFrame:(CGRect)frame;

/** 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.
Expand All @@ -33,8 +38,6 @@ IB_DESIGNABLE
* @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;

- (instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("Instantiating an MGLMapView requires setting a style and/or an access token.")));

#pragma mark - Authorizing Access

/** @name Authorizing Access */
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/ios/MapboxGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
#import "MGLMapView.h"
#import "MGLTypes.h"
#import "MGLUserLocation.h"
#import "MGLAccountManager.h"
18 changes: 18 additions & 0 deletions ios/app/MBXAppDelegate.m
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
#import "MBXAppDelegate.h"
#import "MBXViewController.h"
#import <mbgl/ios/MapboxGL.h>
#import <mbgl/ios/MGLAccountManager.h>
#import <mbgl/ios/MGLMapboxEvents.h>

@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"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: A common strategy for user defaults keys is to make them match the names of the constants that define them. So you’d define a constant called MGLMapboxAccessTokenDefaultsKey with the value MGLMapboxAccessToken in MGLTypes.h and use that constant here. Obviously it doesn’t matter as long as you’re consistent, but it’s one less thing to worry about naming.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd be better off putting things in a constant to avoid future potential problems with the @"access_token" magic string, too.

} 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.");

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

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[MBXViewController new]];
[self.window makeKeyAndVisible];
Expand Down
15 changes: 1 addition & 14 deletions ios/app/MBXViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,7 @@ - (void)viewDidLoad
{
[super viewDidLoad];

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.");

self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds accessToken:accessToken];
self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.mapView.showsUserLocation = YES;
self.mapView.delegate = self;
Expand Down
53 changes: 53 additions & 0 deletions platform/ios/MGLAccountManager.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#import <Foundation/Foundation.h>

#import "MGLAccountManager.h"
#import "NSProcessInfo+MGLAdditions.h"
#import "MGLMapboxEvents.h"

@interface MGLAccountManager()

@property (atomic) NSString *accessToken;

@end


@implementation MGLAccountManager

static MGLAccountManager *_sharedManager;

// Can be called from any thread.
//
+ (instancetype) sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if ( ! NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent) {
void (^setupBlock)() = ^{
_sharedManager = [[self alloc] init];
};
if ( ! [[NSThread currentThread] isMainThread]) {
dispatch_sync(dispatch_get_main_queue(), ^{
setupBlock();
});
}
else {
setupBlock();
}
}
});
return _sharedManager;
}

+ (void) setAccessToken:(NSString *) accessToken {
[[MGLAccountManager sharedInstance] setAccessToken:accessToken];

// Update MGLMapboxEvents
// NOTE: This is (likely) the initial setup of MGLMapboxEvents
[MGLMapboxEvents setToken:accessToken];
}

+ (NSString *) accessToken {
return [MGLAccountManager sharedInstance].accessToken;
}


@end
2 changes: 2 additions & 0 deletions platform/ios/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#import "SMCalloutView.h"

#import "MGLMapboxEvents.h"
#import "MapboxGL.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import statement likle

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import statement likely makes some of the other ones redundant.


#import <algorithm>

Expand Down Expand Up @@ -109,6 +110,7 @@ - (instancetype)initWithFrame:(CGRect)frame
if (self && [self commonInit])
{
self.styleURL = nil;
self.accessToken = [MGLAccountManager accessToken];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the other direction? -[MGLMapView setAccessToken:] should update the singleton.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just ticketed it -> #1430

return self;
}

Expand Down