From 70381d2705991b15a1861b3162f50aa56961343c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Thu, 21 May 2015 01:49:53 -0700 Subject: [PATCH 1/5] Fixed up various Info.plist edge cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to look in the main bundle for Info.plist settings, because the developer has no access to the framework’s Info.plist. Need to check MGLMapboxMetricsEnabledSettingShownInApp before MGLMapboxAccessToken; otherwise, `MGLMapboxEvents` inspects the Settings bundle plist before MGLMapboxMetricsEnabledSettingShownInApp is even checked. --- platform/ios/MGLAccountManager.m | 8 +++++--- platform/ios/MGLMapboxEvents.m | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/platform/ios/MGLAccountManager.m b/platform/ios/MGLAccountManager.m index 2f246b7d915..03a90c31b98 100644 --- a/platform/ios/MGLAccountManager.m +++ b/platform/ios/MGLAccountManager.m @@ -15,13 +15,15 @@ @interface MGLAccountManager() @implementation MGLAccountManager + (void)load { - // Read initial configuration from Info.plist. - NSBundle *bundle = [NSBundle bundleForClass:self]; - self.accessToken = [bundle objectForInfoDictionaryKey:@"MGLMapboxAccessToken"]; + // Read the initial configuration from Info.plist. The shown-in-app setting + // preempts the Settings bundle check in -[MGLMapboxEvents init] triggered + // by setting the access token. + NSBundle *bundle = [NSBundle mainBundle]; NSNumber *shownInAppNumber = [bundle objectForInfoDictionaryKey:@"MGLMapboxMetricsEnabledSettingShownInApp"]; if (shownInAppNumber) { [MGLAccountManager sharedManager].mapboxMetricsEnabledSettingShownInApp = [shownInAppNumber boolValue]; } + self.accessToken = [bundle objectForInfoDictionaryKey:@"MGLMapboxAccessToken"]; } // Can be called from any thread. diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index a0e771ad076..1079899ced1 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -177,7 +177,7 @@ @implementation MGLMapboxEvents { + (void)initialize { if (self == [MGLMapboxEvents class]) { - NSBundle *bundle = [NSBundle bundleForClass:self]; + NSBundle *bundle = [NSBundle mainBundle]; NSNumber *accountTypeNumber = [bundle objectForInfoDictionaryKey:@"MGLMapboxAccountType"]; [[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"MGLMapboxAccountType": accountTypeNumber ? accountTypeNumber : @0, @@ -198,7 +198,8 @@ - (instancetype) init { self = [super init]; if (self) { - if (! [MGLAccountManager mapboxMetricsEnabledSettingShownInApp]) { + if (! [MGLAccountManager mapboxMetricsEnabledSettingShownInApp] && + [[NSUserDefaults standardUserDefaults] integerForKey:@"MGLMapboxAccountType"] == 0) { // Opt Out is not configured in UI, so check for Settings.bundle // Put Settings bundle into memory id defaultEnabledValue; From c718d2ea660f4fa3366caad347bb6577a679b968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Thu, 21 May 2015 01:51:18 -0700 Subject: [PATCH 2/5] Made accessToken uninspectable --- include/mbgl/ios/MGLMapView+IBAdditions.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/mbgl/ios/MGLMapView+IBAdditions.h b/include/mbgl/ios/MGLMapView+IBAdditions.h index df9a19a6b7f..69998a47491 100644 --- a/include/mbgl/ios/MGLMapView+IBAdditions.h +++ b/include/mbgl/ios/MGLMapView+IBAdditions.h @@ -8,7 +8,6 @@ // inspectables declared in MGLMapView.h are always sorted before those in // MGLMapView+IBAdditions.h, due to ASCII sort order. -@property (nonatomic) IBInspectable NSString *accessToken; @property (nonatomic) IBInspectable NSString *mapID; // Convenience properties related to the initial viewport. These properties From e74997e2c18a39355bde6caf9754a23c553b6853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Thu, 21 May 2015 08:53:40 -0700 Subject: [PATCH 3/5] Clarified IB designable message Access tokens are only required for showing Mapbox-hosted maps. --- platform/ios/MGLMapView.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 215be14b54a..8df16ce3860 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -2523,7 +2523,7 @@ - (void)prepareForInterfaceBuilder // Explanation UILabel *explanationLabel = [[UILabel alloc] init]; - explanationLabel.text = @"To display a map here, you must provide a Mapbox access token. Get an access token from:"; + explanationLabel.text = @"To display a Mapbox-hosted map here, you must provide an access token. Get an access token from:"; explanationLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; explanationLabel.numberOfLines = 0; explanationLabel.translatesAutoresizingMaskIntoConstraints = NO; From 93f92b7805af1cf7ede158661431f06c67dc5950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Thu, 21 May 2015 10:10:35 -0700 Subject: [PATCH 4/5] Rewrote IB designable message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IB designables inside frameworks have no access whatsoever to the host app’s bundle (especially if the host app lacks any designables of its own). So it has no way of knowing whether the access token is set in Info.plist. We could continue to check whether it was set programmatically, but we’d still have no way of knowing whether the host app has a Settings bundle, the other prerequisite for displaying Mapbox maps. Therefore, this change removes the Mapbox logo from the designable and displays a reworded reminder unconditionally. It now displays the URL of the “First steps with Mapbox GL for iOS” guide. I kept Mapbox blue in the designable, but as a border, so you can easily tell where the view ends (a major usability problem for custom views in IB). --- platform/ios/MGLMapView.mm | 225 +++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 124 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 8df16ce3860..10e85ee5a8c 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -36,7 +36,7 @@ NSString *const MGLDefaultStyleName = @"mapbox-streets"; NSString *const MGLStyleVersion = @"7"; NSString *const MGLDefaultStyleMarkerSymbolName = @"default_marker"; -NSString *const MGLMapboxAccessTokenManagerURLDisplayString = @"mapbox.com/account/apps"; +NSString *const MGLMapboxSetupDocumentationURLDisplayString = @"mapbox.com/guides/first-steps-gl-ios"; const NSTimeInterval MGLAnimationDuration = 0.3; const CGSize MGLAnnotationUpdateViewportOutset = {150, 150}; @@ -2473,129 +2473,106 @@ - (void)prepareForInterfaceBuilder { [super prepareForInterfaceBuilder]; - self.layer.borderColor = [UIColor colorWithWhite:184/255. alpha:1].CGColor; - self.layer.borderWidth = 1; - - if ([MGLAccountManager accessToken]) - { - self.layer.backgroundColor = [UIColor colorWithRed:59/255. - green:178/255. - blue:208/255. - alpha:0.8].CGColor; - - UIImage *image = [[self class] resourceImageNamed:@"mapbox.png"]; - UIImageView *previewView = [[UIImageView alloc] initWithImage:image]; - previewView.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:previewView]; - [self addConstraint: - [NSLayoutConstraint constraintWithItem:previewView - attribute:NSLayoutAttributeCenterXWithinMargins - relatedBy:NSLayoutRelationEqual - toItem:self - attribute:NSLayoutAttributeCenterXWithinMargins - multiplier:1 - constant:0]]; - [self addConstraint: - [NSLayoutConstraint constraintWithItem:previewView - attribute:NSLayoutAttributeCenterYWithinMargins - relatedBy:NSLayoutRelationEqual - toItem:self - attribute:NSLayoutAttributeCenterYWithinMargins - multiplier:1 - constant:0]]; - } - else - { - UIView *diagnosticView = [[UIView alloc] init]; - diagnosticView.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:diagnosticView]; - - // Headline - UILabel *headlineLabel = [[UILabel alloc] init]; - headlineLabel.text = @"No Access Token"; - headlineLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; - headlineLabel.textAlignment = NSTextAlignmentCenter; - headlineLabel.numberOfLines = 1; - headlineLabel.translatesAutoresizingMaskIntoConstraints = NO; - [headlineLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow - forAxis:UILayoutConstraintAxisHorizontal]; - [diagnosticView addSubview:headlineLabel]; - - // Explanation - UILabel *explanationLabel = [[UILabel alloc] init]; - explanationLabel.text = @"To display a Mapbox-hosted map here, you must provide an access token. Get an access token from:"; - explanationLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - explanationLabel.numberOfLines = 0; - explanationLabel.translatesAutoresizingMaskIntoConstraints = NO; - [explanationLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow - forAxis:UILayoutConstraintAxisHorizontal]; - [diagnosticView addSubview:explanationLabel]; - - // Link - UIButton *linkButton = [UIButton buttonWithType:UIButtonTypeSystem]; - [linkButton setTitle:MGLMapboxAccessTokenManagerURLDisplayString forState:UIControlStateNormal]; - linkButton.translatesAutoresizingMaskIntoConstraints = NO; - [linkButton setContentCompressionResistancePriority:UILayoutPriorityDefaultLow - forAxis:UILayoutConstraintAxisHorizontal]; - [diagnosticView addSubview:linkButton]; - - // More explanation - UILabel *explanationLabel2 = [[UILabel alloc] init]; - 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; - [explanationLabel2 setContentCompressionResistancePriority:UILayoutPriorityDefaultLow - forAxis:UILayoutConstraintAxisHorizontal]; - [diagnosticView addSubview:explanationLabel2]; - - // Constraints - NSDictionary *views = @{ - @"container": diagnosticView, - @"headline": headlineLabel, - @"explanation": explanationLabel, - @"link": linkButton, - @"explanation2": explanationLabel2, - }; - [self addConstraint: - [NSLayoutConstraint constraintWithItem:diagnosticView - attribute:NSLayoutAttributeCenterYWithinMargins - relatedBy:NSLayoutRelationEqual - toItem:self - attribute:NSLayoutAttributeCenterYWithinMargins - multiplier:1 - constant:0]]; - [self addConstraints: - [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[container(20@20)]-|" - options:NSLayoutFormatAlignAllCenterY - metrics:nil - views:views]]; - [self addConstraints: - [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[headline]-[explanation]-[link]-[explanation2]|" - options:0 - metrics:nil - views:views]]; - [self addConstraints: - [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[headline]|" - options:0 - metrics:nil - views:views]]; - [self addConstraints: - [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[explanation]|" - options:0 - metrics:nil - views:views]]; - [self addConstraints: - [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[link]|" - options:0 - metrics:nil - views:views]]; - [self addConstraints: - [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[explanation2]|" - options:0 - metrics:nil - views:views]]; - } + self.layer.borderColor = [UIColor colorWithRed:59/255. + green:178/255. + blue:208/255. + alpha:0.8].CGColor; + self.layer.borderWidth = 4; + self.layer.backgroundColor = [UIColor whiteColor].CGColor; + + UIView *diagnosticView = [[UIView alloc] init]; + diagnosticView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:diagnosticView]; + + // Headline + UILabel *headlineLabel = [[UILabel alloc] init]; + headlineLabel.text = @"MGLMapView"; + headlineLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + headlineLabel.textAlignment = NSTextAlignmentCenter; + headlineLabel.numberOfLines = 1; + headlineLabel.translatesAutoresizingMaskIntoConstraints = NO; + [headlineLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow + forAxis:UILayoutConstraintAxisHorizontal]; + [diagnosticView addSubview:headlineLabel]; + + // Explanation + UILabel *explanationLabel = [[UILabel alloc] init]; + explanationLabel.text = (@"To display a Mapbox-hosted map here:\n\n" + @"1. Set MGLMapboxAccessToken to your access token in Info.plist\n" + @"2. Add a Settings bundle that allows the user to turn Mapbox Metrics on and off\n\n" + @"For detailed instructions, see:"); + explanationLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + explanationLabel.numberOfLines = 0; + explanationLabel.translatesAutoresizingMaskIntoConstraints = NO; + [explanationLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow + forAxis:UILayoutConstraintAxisHorizontal]; + [diagnosticView addSubview:explanationLabel]; + + // Link + UIButton *linkButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [linkButton setTitle:MGLMapboxSetupDocumentationURLDisplayString forState:UIControlStateNormal]; + linkButton.translatesAutoresizingMaskIntoConstraints = NO; + linkButton.titleLabel.numberOfLines = 0; + [linkButton setContentCompressionResistancePriority:UILayoutPriorityDefaultLow + forAxis:UILayoutConstraintAxisHorizontal]; + [diagnosticView addSubview:linkButton]; + + // Constraints + NSDictionary *views = @{ + @"container": diagnosticView, + @"headline": headlineLabel, + @"explanation": explanationLabel, + @"link": linkButton, + }; + [self addConstraint: + [NSLayoutConstraint constraintWithItem:diagnosticView + attribute:NSLayoutAttributeCenterYWithinMargins + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterYWithinMargins + multiplier:1 + constant:0]]; + [self addConstraint: + [NSLayoutConstraint constraintWithItem:diagnosticView + attribute:NSLayoutAttributeTopMargin + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:self + attribute:NSLayoutAttributeTopMargin + multiplier:1 + constant:8]]; + [self addConstraint: + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottomMargin + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:diagnosticView + attribute:NSLayoutAttributeBottomMargin + multiplier:1 + constant:8]]; + [self addConstraints: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[container(20@20)]-|" + options:NSLayoutFormatAlignAllCenterY + metrics:nil + views:views]]; + [self addConstraints: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[headline]-[explanation]-[link]|" + options:0 + metrics:nil + views:views]]; + [self addConstraints: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[headline]|" + options:0 + metrics:nil + views:views]]; + [self addConstraints: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[explanation]|" + options:0 + metrics:nil + views:views]]; + [self addConstraints: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[link]|" + options:0 + metrics:nil + views:views]]; } class MBGLView : public mbgl::View From 2200c51a337d8f10bf61037d282645add5622608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Thu, 21 May 2015 13:29:46 -0700 Subject: [PATCH 5/5] Removed unavailable method implementation This class method is marked unavailable in MGLAccountManager.h, so this code can never be reached. --- platform/ios/MGLAccountManager.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform/ios/MGLAccountManager.m b/platform/ios/MGLAccountManager.m index 03a90c31b98..71987786c95 100644 --- a/platform/ios/MGLAccountManager.m +++ b/platform/ios/MGLAccountManager.m @@ -50,10 +50,6 @@ + (instancetype) sharedManager { return _sharedManager; } -+ (void) setMapboxMetricsEnabledSettingShownInApp:(BOOL)shown { - [MGLAccountManager sharedManager].mapboxMetricsEnabledSettingShownInApp = shown; -} - + (BOOL) mapboxMetricsEnabledSettingShownInApp { return [MGLAccountManager sharedManager].mapboxMetricsEnabledSettingShownInApp; }