-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Style API cleanup, designables, inspectables #1184
Conversation
Some details from individual commits:
|
NSNumber *pendingLongitude; | ||
if ((pendingLongitude = objc_getAssociatedObject(self, @selector(longitude)))) | ||
{ | ||
objc_setAssociatedObject(self, @selector(latitude), nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this associated object stuff is crazy, but I wanted two separate numeric inspectables instead of one comma-separated string inspectable (since it wouldn’t be clear whether latitude or longitude comes first). Setting only longitude or latitude has no effect: the coordinate remains (NaN, NaN).
This is why these properties are strictly IB-only. Maybe I should assert that the coordinate is still invalid before proceeding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Distinct latitude and longitude fields seems like the right way to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is why these properties are strictly IB-only. Maybe I should assert that the coordinate is still invalid before proceeding?
I think this might be a good idea, so that you never get someone trying to set these via KVC or something.
Will take a look shortly. |
Just seeing this now and will look into it. First Impression though is that customizing Xcode for Access Tokens is awesome! 👍 |
}; | ||
if ( ! [[NSThread currentThread] isMainThread]) { | ||
dispatch_sync(dispatch_get_main_queue(), ^{ | ||
if ( ! NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what wrapping this in a "not IBDesignableAgent" means. I assume this is some extra process that is only run when Xcode is working with the code via IB?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s correct. Whenever you modify an instance of MGLMapView
in a storyboard (for instance by resizing it), Interface Builder spawns an IBDesignablesAgentCocoaTouch process in the background that instantiates an MGLMapView
and calls methods like -drawRect:
on it. There are two hooks for IB-only code that should never run in front of a user: TARGET_INTERFACE_BUILDER
(which we can’t use) and -prepareForInterfaceBuilder
. Here’s more information about designables, in two flavors: corporate, hipster.
In NSProcessInfo+MGLAdditions, I added a category method that cheaply determines whether the MGLMapView
is being run inside of IBDesignablesAgentCocoaTouch. I’m using it here to prevent the shared MGLMapboxEvents
instance from ever being created. The assumption is that you’d never release an app named IBDesignablesAgentCocoaTouch. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's really cool! I didn't realize IB could do that. Thanks for info @1ec5!
@1ec5 Just the one question ^^. Other than that just please make sure |
'../platform/ios/NSString+MGLAdditions.h', | ||
'../platform/ios/NSString+MGLAdditions.m', | ||
'../include/mbgl/ios/MGLMapView_IBAdditions.h', | ||
'../platform/ios/MGLMapView_IBAdditions.m', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not name these with the same convention? (MGLMapView+IBAdditions.h
etc.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one question @1ec5 while I'm still testing things out. Can you, like the |
It does, but do we need them when they are intended for IB and not code? They are purely visual. |
I see that the case is no, but it's an easy fix that I'm putting in now. |
I think functionality-wise we are good here now. I think we should shoot for the following API cleanups though:
|
|
In other words, your proposed code above passes a NaN longitude into |
Ah, right. Sorry, I know you've been through the trenches on the order of operations here. Just ideas.
This does sound more standard. |
BTW on this front, I'm hesitant to expose |
Rather than enumerating the styles at runtime, the most Cocoa-like way of doing this would be to define a series of For now I’ve done as you suggest above but we should definitely revisit this method for beta 2. |
Cool, I think b376fa6 is a good first step solution here.
Not sure I follow. Just because of the two-part setup? I do think something like |
I think this is good if you're happy with testing @1ec5. Want to squash and push a new branch or force-push here? |
Not exactly. The demo apps all list the styles by name, so you have to do some parsing to get a human-readable name, meaning even tighter coupling to the nascent asset: URL standard.
We have that already, as a private |
else | ||
{ | ||
mbglMap->setStyleURL(styleURLString); | ||
styleURLString = std::string("asset://") + styleURLString; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should get rid of this case. We can easily be consistent internally about using the asset: scheme. If the developer then passes in a relative URL, we can treat it as being relative to the main bundle rather than MapboxGL.bundle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
`Map` should be able to deal with having no access token or JSON even while it’s running. Most of `Map` accounts for this situation, but `reloadStyle()` incorrectly assumes that one or the other is set. This change corrects the assumption in `reloadStyle()`. Also expose the access token and style name to clients as ordinary KVO-compliant properties. Actually, they’re not so ordinary because they’re inspectable! Ref #1070, #1147
This change removes most of the ways you used to be able to apply a style to the map. Building on #1163, `styleURL` (HTTP(S), mapbox:, asset:) is the canonical way to apply a style, and `mapID` is a convenient shorthand for Mapbox-hosted styles. A relative style URL is interpreted as a path relative to the app’s main bundle. We now construct asset: URLs in lieu of “bundled style names”.
When an access token is set in the Attributes inspector (or as a user-defined runtime attribute), we draw some lovely Mapbox branding so the view shows up. (Manipulating invisible rectangles is a frustrating exercise, I’m told.) In the absence of an access token, the view displays a helpful message with directions for obtaining and setting the access token. Along the way, completely opt out of `MGLMapboxEvents` when targeting Interface Builder, because touching Core Location throws an exception in that environment and it doesn’t make sense to record any metrics when designing on the Interface Builder canvas. Also, don’t start `mbgl::Map` at all (and don’t update it) because none of the runtime drawing code should ever be run in the designable. Normally these chunks of code would be excluded in IB using the TARGET_INTERFACE_BUILDER preprocessor macro. However, Mapbox GL is being packaged as a static library, so the macro is only evaluated when the library is prebuilt, even if the library eventually makes its way into the CocoaPods-generated framework. Instead, we detect that we’re being run by the IBDesignablesAgentCocoaTouch process. Overrode `-[MGLMapView initWithFrame:]` to call `-commonInit`. We’ve marked this initializer unavailable in the header, but IB still calls it regardless. Fixes #929.
Ran this through `./ios/docs/install_docs.sh` to double-check things. * Less-specific initializers above more-specific per Apple convention. * Shores up `accessToken` docs as property, not a method. * Edited comments for consistency and/or to keep them out of the docs.
Added inspectables for toggling zooming, panning, rotating, and showing the user location for parity with `MKMapView`.
Style API cleanup, designables, inspectables
@DavidChouinard How are you integrating Mapbox GL into your project? We’re planning to distribute a prebuilt static library via CocoaPods but haven’t uploaded the binary yet; in the meantime, you can follow these steps to use Mapbox GL as it’ll be used once it’s officially released:
m.source = { :http => "file:///absolute/path/to/mapbox-gl-native/build/ios/pkg/mapbox-gl-ios-#{m.version.to_s}.zip" }
source 'file:///absolute/path/to/pods/'
pod 'MapboxGL', '~> 0.1.0'
use_frameworks!
If all that’s too much, there’s also the option of building from source (via |
To clarify, GL has to be included as a framework (even if built statically) right now in order for the IB stuff to work. |
@DavidChouinard Before you go through the rigmarole above, though, I wonder if your project has |
#1184 added `-[NSProcessInfo(MGLAdditions) mgl_isInterfaceBuilderDesignablesAgent]`, which only gets pulled in if you add `-ObjC` to `OTHER_LDFLAGS`.
@1ec5 Sorry for taking so long to try this. After a bit of fiddling with Cocoapods, it works. I get the blue Mapbox view in Interface Builder. However, when running the application, I get the following console messages and the view is completely white:
|
@DavidChouinard It looks like MapboxGL.framework or MapboxGL.a inside it still aren’t getting linked into your app for some reason. If you instantiate the |
This PR addresses the following:
So, what’s the easiest way to get started with Mapbox GL?
pod install
.UIViewController
in a storyboard.Will squash before merging.