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

Provide "mapType"-like abstraction for built-in styles #1640

Closed
friedbunny opened this issue May 26, 2015 · 13 comments
Closed

Provide "mapType"-like abstraction for built-in styles #1640

friedbunny opened this issue May 26, 2015 · 13 comments
Labels
feature iOS Mapbox Maps SDK for iOS

Comments

@friedbunny
Copy link
Contributor

MapKit and Google Maps both specify enumerate type constants for map styles, which makes setting and comparing trivial. I think MBGL should provide a similar abstraction for built-in styles.

// MapKit

typedef NS_ENUM(NSUInteger, MKMapType) {
    MKMapTypeStandard = 0,
    MKMapTypeSatellite,
    MKMapTypeHybrid
} NS_ENUM_AVAILABLE(10_9, 3_0);

// MKMapView property setting that end-developer uses
mapView.mapType = MKMapTypeStandard;
// Google Maps

/**
 * Display types for GMSMapView.
 */
typedef enum {
  /** Basic maps.  The default. */
  kGMSTypeNormal = 1,

  /** Satellite maps with no labels. */
  kGMSTypeSatellite,

  /** Terrain maps. */
  kGMSTypeTerrain,

  /** Satellite maps with a transparent label overview. */
  kGMSTypeHybrid,

  /** No maps, no labels.  Display of traffic data is not supported. */
  kGMSTypeNone,

} GMSMapViewType;

// GMSMapView property setting that end-developer uses
mapView.mapType = kGMSTypeNormal;

We currently ask developers to implement their own style infrastructure, even for built-in styles:

// paraphrased from MBXViewController.mm (iOS demo app)

// not part of the library
static NSArray *const kStyleNames = @[
    @"Mapbox Streets",
    @"Emerald",
    @"Light",
    @"Dark",
    @"Bright",
    @"Basic",
    @"Outdoors",
    @"Satellite",
];

static NSString *const kStyleVersion = @"7";

// ... 

NSString *styleName = [kStyleNames firstObject];// "Mapbox Streets"
NSString *url = [NSString stringWithFormat:@"asset://styles/%@-v%@.json",
                     [[styleName lowercaseString] stringByReplacingOccurrencesOfString:@" " withString:@"-"],
                     kStyleVersion];
mapView.styleURL = [NSURL URLWithString:url];// "asset://styles/mapbox-streets-v7.json"
@1ec5
Copy link
Contributor

1ec5 commented May 26, 2015

I’d be comfortable requiring developers to pass a simple string into -[MGLMapView setStyleID:], like mapbox.satellite, rather than hard-coding a special set of styles just because MapKit has them.

Hybrid is a bit trickier, however, since you need to set style classes, and we’d want to avoid digressing into a discussion of style classes just to set up hybrid. In #935, we implemented a shortcut so that passing hybrid into -[MGLMapView useBundledStyleNamed:] switched to satellite-v7 plus the labels and contours classes. We ended up removing that API entirely as part of the big refactoring in #1184 – since satellite-v7 wasn’t going to be bundled with beta 1. For beta 2, though, we’ll definitely need something simpler than passing an asset: URL into -[MGLMapView setStyleID:].

@friedbunny
Copy link
Contributor Author

@1ec5 Any sort of tokenization of the asset URL for our styles would be great, it doesn't necessarily have to exactly resemble MapKit/Google — though MGLMapView.mapType would provide a dead-easy path for switching devs. Our use of the word "style" is initially a little confusing, perhaps?

Definitely necessary for hybrid to be abstracted, yeah. We should also provide a help topic/FAQ for how it's implemented with style classes, which is a powerful feature that isn't immediately obvious.

I was thinking about this larger issue today because of friedbunny/treble@0b491cc, where I wanted to compare the current map style in the three maps and set the status bar style based on the map style (satellite/hybrid/dark get white text).

As with the three different cycleStyles methods, MBGL was the least elegant. 😞

@1ec5 1ec5 added feature iOS Mapbox Maps SDK for iOS labels May 26, 2015
@friedbunny
Copy link
Contributor Author

Thinking more about this, the consistent semantics of style is fine, no need to pedantically follow mapType.

I do think a key point here is the discoverability of public-header constants — it'd be friendly to be able to autocomplete MGLMapStyle... or ⌘-click MGLMapStyleSatellite and see the rest of the defined types.

@jfirebaugh
Copy link
Contributor

I think mapbox:// URLs should be our abstraction -- #2239.

@1ec5
Copy link
Contributor

1ec5 commented Oct 2, 2015

It's unusual for an iOS framework to expect a developer to use literal URLs this way for preset options. For a select group of styles we want all developers to know about and have access to, we should provide constants that map to mapbox:// URL strings (if not the URLs themselves). This would be consistent with how UIKit provides constant strings for things like standardized dictionary keys. For any custom styles, the developer would construct their own URLs as usual.

@1ec5 1ec5 reopened this Oct 2, 2015
@1ec5
Copy link
Contributor

1ec5 commented Oct 2, 2015

The upshot is that we would have no additional APIs to maintain, just a list of styles in a header that could be generated at build time if need be.

@ljbade
Copy link
Contributor

ljbade commented Oct 2, 2015

@1ec5 @jfirebaugh What about something along the lines of what I am going to do for #2500 in Android?

Basically the SDK will expose a set of static String values, currently set to the correct asset:// path.

The developer then feeds one of them into setStyleUrl(MapView.StyleUrls.MAPBOX_STREETS);

Main advantages:

  • simple - no need for code to switch a int enum into a URL string
  • independence - apps no longer hardcode the default styles freeing up us from having to convert from v7 to v8 URLs, and makes unbundle default Mapbox styles from SDKs #2239 easy to implement (just switch out the string values in next release)

@ljbade
Copy link
Contributor

ljbade commented Oct 2, 2015

@1ec5 I'm also dropping styleId on Android (never got implemented but did have a ticket open) in favour of clear documentation of the mapbox://user.style format and having the Mapbox Studio UI directly give a mapbox:// formatted URL (or even https://?) URL.

@1ec5
Copy link
Contributor

1ec5 commented Oct 2, 2015

In the iOS SDK, MGLMapView.styleURL is an instance of NSURL, while MGLMapView.styleID is an instance of NSString. (It’s conventional to use NSURL instead of NSString for URIs.) We at least need a separate styleID property for the inspectable in Interface Builder, because IB doesn’t support inspectable NSURLs. (However, it would be possible to move that property to the IB-specific header, hiding it from those trying to set up an MGLMapView programmatically.)

Basically the SDK will expose a set of static String values, currently set to the correct asset:// path.

This is essentially what I’m proposing for the iOS SDK, though I’m undecided as to which type would be more elegant:

  • static NSString * const MGLMapStyleIDEmerald (would need to provide a convenience initializer for style IDs or expect developers to wrap the string in an NSURL before passing into -initWithFrame:styleURL:)
  • static NSURL *MGLMapStyleURLEmerald (can’t be constant because of how NSURLs are initialized)

@ljbade
Copy link
Contributor

ljbade commented Oct 2, 2015

Yeah moving to IB would make both APIs parity and stop people getting confused as to which method to use.

@1ec5 what about a static method that returns a NSURL? I don't really know much about Apple land so that might sound silly.

@1ec5
Copy link
Contributor

1ec5 commented Oct 2, 2015

That would be unfortunate, but maybe necessary if we provide NSURLs instead of strings.

@friedbunny
Copy link
Contributor Author

I'm still in favor of constants, as @1ec5 is pushing for. For a developer who only sees MGLMapStyleStreets, switching to unbundled styles in #2239 would be a transparent change.

@friedbunny
Copy link
Contributor Author

We essentially got this #2746.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature iOS Mapbox Maps SDK for iOS
Projects
None yet
Development

No branches or pull requests

4 participants