[ios, macos] Key-value compliance for MGLStyle

Replaced -[MGLMapView style] with a property. Keep the MGLStyle object around for the lifetime of the style.

Bracket changes to layers in willChange and didChange calls. The built-in point annotation layer is added after the style is finished loading but before the map is finished loading. Cause a second wave of change notifications to go out, about both sources and layers. Issue change notifications for style layers when shape annotations are added or removed.
This commit is contained in:
Minh Nguyễn
2016-08-19 13:56:46 -07:00
committed by Minh Nguyễn
parent 850b70ff91
commit 9fac640bf3
6 changed files with 108 additions and 33 deletions

View File

@@ -40,8 +40,10 @@
#endif
@interface MGLStyle()
@property (nonatomic, weak) MGLMapView *mapView;
@property (nonatomic, readwrite, weak) MGLMapView *mapView;
@property (readonly, copy, nullable) NSURL *URL;
@end
@implementation MGLStyle
@@ -98,17 +100,24 @@ static NSURL *MGLStyleURL_emerald;
return MGLStyleURL_emerald;
}
#pragma mark Metadata
#pragma mark -
- (NSString *)name {
std::string name = self.mapView.mbglMap->getStyleName();
return name.empty() ? nil : @(name.c_str());
- (instancetype)initWithMapView:(MGLMapView *)mapView {
if (self = [super init]) {
_mapView = mapView;
}
return self;
}
- (NSURL *)URL {
return [NSURL URLWithString:@(self.mapView.mbglMap->getStyleURL().c_str())];
}
- (NSString *)name {
std::string name = self.mapView.mbglMap->getStyleName();
return name.empty() ? nil : @(name.c_str());
}
#pragma mark Sources
- (NS_MUTABLE_SET_OF(MGLSource *) *)sources {
@@ -158,8 +167,7 @@ static NSURL *MGLStyleURL_emerald;
} else if (mbglSource->is<mbgl::style::RasterSource>()) {
source = [[MGLRasterSource alloc] initWithIdentifier:identifier];
} else {
NSAssert(NO, @"Unrecognized source type");
return nil;
source = [[MGLSource alloc] initWithIdentifier:identifier];
}
source.rawSource = mbglSource;
@@ -320,7 +328,9 @@ static NSURL *MGLStyleURL_emerald;
@"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.",
layer];
}
[layer removeFromMapView:self.mapView];
[self willChangeValueForKey:@"layers"];
[layer removeFromMapView:self.mapView];
[self didChangeValueForKey:@"layers"];
}
- (void)addLayer:(MGLStyleLayer *)layer
@@ -331,7 +341,9 @@ static NSURL *MGLStyleURL_emerald;
@"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.",
layer];
}
[self willChangeValueForKey:@"layers"];
[layer addToMapView:self.mapView];
[self didChangeValueForKey:@"layers"];
}
- (void)insertLayer:(MGLStyleLayer *)layer atIndex:(NSUInteger)index {

View File

@@ -6,7 +6,10 @@
#include <mbgl/mbgl.hpp>
@interface MGLStyle (Private)
@property (nonatomic, weak) MGLMapView *mapView;
- (instancetype)initWithMapView:(MGLMapView *)mapView;
@property (nonatomic, readonly, weak) MGLMapView *mapView;
- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration;

View File

@@ -117,6 +117,14 @@ IB_DESIGNABLE
#pragma mark Configuring the Map’s Appearance
/**
The style currently displayed in the receiver.
Unlike the `styleURL` property, this property is set to an object that allows
you to manipulate every aspect of the style locally.
*/
@property (nonatomic, readonly) MGLStyle *style;
/**
URLs of the styles bundled with the library.
@@ -134,6 +142,9 @@ IB_DESIGNABLE
If you set this property to `nil`, the receiver will use the default style
and this property will automatically be set to that style’s URL.
If you want to modify the current style without replacing it outright, or if
you want to introspect individual style attributes, use the `style` property.
*/
@property (nonatomic, null_resettable) NSURL *styleURL;
@@ -1077,10 +1088,6 @@ IB_DESIGNABLE
*/
- (void)removeOverlays:(NS_ARRAY_OF(id <MGLOverlay>) *)overlays;
#pragma mark - Runtime styling API
- (MGLStyle *)style;
#pragma mark Accessing the Underlying Map Data
/**

View File

@@ -236,6 +236,9 @@ public:
@property (nonatomic, readwrite) UIButton *attributionButton;
@property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *attributionButtonConstraints;
@property (nonatomic) UIActionSheet *attributionSheet;
@property (nonatomic, readwrite) MGLStyle *style;
@property (nonatomic) UIPanGestureRecognizer *pan;
@property (nonatomic) UIPinchGestureRecognizer *pinch;
@property (nonatomic) UIRotationGestureRecognizer *rotate;
@@ -284,6 +287,8 @@ public:
std::vector<MGLAnnotationTag> _annotationsNearbyLastTap;
CGPoint _initialImplicitCalloutViewOffset;
NSDate *_userLocationAnimationCompletionDate;
/// True if a willChange notification has been issued for shape annotation layers and a didChange notification is pending.
BOOL _isChangingAnnotationLayers;
BOOL _isWaitingForRedundantReachableNotification;
BOOL _isTargetingInterfaceBuilder;
@@ -355,14 +360,17 @@ public:
- (void)setStyleURL:(nullable NSURL *)styleURL
{
if (_isTargetingInterfaceBuilder) return;
if ( ! styleURL)
{
styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion];
}
styleURL = styleURL.mgl_URLByStandardizingScheme;
[self willChangeValueForKey:@"style"];
_style = [[MGLStyle alloc] initWithMapView:self];
_mbglMap->setStyleURL([[styleURL absoluteString] UTF8String]);
[self didChangeValueForKey:@"style"];
}
- (IBAction)reloadStyle:(__unused id)sender {
@@ -620,13 +628,6 @@ public:
return image;
}
- (MGLStyle *)style
{
MGLStyle *style = [[MGLStyle alloc] init];
style.mapView = self;
return style;
}
- (void)reachabilityChanged:(NSNotification *)notification
{
MGLReachability *reachability = [notification object];
@@ -2895,6 +2896,7 @@ public:
continue;
}
_isChangingAnnotationLayers = YES;
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation([multiPoint annotationObjectWithDelegate:self]);
MGLAnnotationContext context;
context.annotation = annotation;
@@ -2991,6 +2993,10 @@ public:
[self updateAnnotationContainerViewWithAnnotationViews:newAnnotationViews];
[self didChangeValueForKey:@"annotations"];
if (_isChangingAnnotationLayers)
{
[self.style willChangeValueForKey:@"layers"];
}
if ([self.delegate respondsToSelector:@selector(mapView:didAddAnnotationViews:)])
{
@@ -3213,11 +3219,16 @@ public:
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinates" context:(void *)(NSUInteger)annotationTag];
}
_isChangingAnnotationLayers = YES;
_mbglMap->removeAnnotation(annotationTag);
}
[self didChangeValueForKey:@"annotations"];
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
if (_isChangingAnnotationLayers)
{
[self.style willChangeValueForKey:@"layers"];
}
}
- (void)addOverlay:(id <MGLOverlay>)overlay
@@ -4559,6 +4570,10 @@ public:
}
case mbgl::MapChangeDidFinishLoadingMap:
{
[self.style willChangeValueForKey:@"sources"];
[self.style didChangeValueForKey:@"sources"];
[self.style willChangeValueForKey:@"layers"];
[self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)])
{
[self.delegate mapViewDidFinishLoadingMap:self];
@@ -4602,6 +4617,11 @@ public:
case mbgl::MapChangeDidFinishRenderingFrame:
case mbgl::MapChangeDidFinishRenderingFrameFullyRendered:
{
if (_isChangingAnnotationLayers)
{
_isChangingAnnotationLayers = NO;
[self.style didChangeValueForKey:@"layers"];
}
[self updateAnnotationViews];
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)])
{
@@ -4611,6 +4631,11 @@ public:
}
case mbgl::MapChangeDidFinishLoadingStyle:
{
[self.style willChangeValueForKey:@"name"];
[self.style willChangeValueForKey:@"sources"];
[self.style didChangeValueForKey:@"sources"];
[self.style willChangeValueForKey:@"layers"];
[self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
{
[self.delegate mapView:self didFinishLoadingStyle:self.style];

View File

@@ -88,6 +88,14 @@ IB_DESIGNABLE
#pragma mark Configuring the Map’s Appearance
/**
The style currently displayed in the receiver.
Unlike the `styleURL` property, this property is set to an object that allows
you to manipulate every aspect of the style locally.
*/
@property (nonatomic, readonly) MGLStyle *style;
/**
URL of the style currently displayed in the receiver.
@@ -97,6 +105,9 @@ IB_DESIGNABLE
If you set this property to `nil`, the receiver will use the default style and
this property will automatically be set to that style’s URL.
If you want to modify the current style without replacing it outright, or if
you want to introspect individual style attributes, use the `style` property.
*/
@property (nonatomic, null_resettable) NSURL *styleURL;
@@ -926,10 +937,6 @@ IB_DESIGNABLE
*/
@property (nonatomic) MGLMapDebugMaskOptions debugMask;
#pragma mark Runtime styling API
- (MGLStyle *)style;
@end
NS_ASSUME_NONNULL_END

View File

@@ -152,6 +152,8 @@ public:
@property (nonatomic, readwrite) NSImageView *logoView;
@property (nonatomic, readwrite) NSView *attributionView;
@property (nonatomic, readwrite) MGLStyle *style;
/// Mapping from reusable identifiers to annotation images.
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImagesByIdentifier;
/// Currently shown popover representing the selected annotation.
@@ -186,6 +188,8 @@ public:
BOOL _wantsToolTipRects;
/// True if any annotation images that have custom cursors have been installed.
BOOL _wantsCursorRects;
/// True if a willChange notification has been issued for shape annotation layers and a didChange notification is pending.
BOOL _isChangingAnnotationLayers;
// Cached checks for delegate method implementations that may be called from
// MGLMultiPointDelegate methods.
@@ -576,7 +580,7 @@ public:
if (_isTargetingInterfaceBuilder) {
return;
}
// Default to Streets.
if (!styleURL) {
// An access token is required to load any default style, including
@@ -588,7 +592,10 @@ public:
}
styleURL = styleURL.mgl_URLByStandardizingScheme;
[self willChangeValueForKey:@"style"];
_style = [[MGLStyle alloc] initWithMapView:self];
_mbglMap->setStyleURL(styleURL.absoluteString.UTF8String);
[self didChangeValueForKey:@"style"];
}
- (IBAction)reloadStyle:(__unused id)sender {
@@ -849,6 +856,10 @@ public:
}
case mbgl::MapChangeDidFinishLoadingMap:
{
[self.style willChangeValueForKey:@"sources"];
[self.style didChangeValueForKey:@"sources"];
[self.style willChangeValueForKey:@"layers"];
[self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)]) {
[self.delegate mapViewDidFinishLoadingMap:self];
}
@@ -888,6 +899,10 @@ public:
case mbgl::MapChangeDidFinishRenderingFrame:
case mbgl::MapChangeDidFinishRenderingFrameFullyRendered:
{
if (_isChangingAnnotationLayers) {
_isChangingAnnotationLayers = NO;
[self.style didChangeValueForKey:@"layers"];
}
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)]) {
BOOL fullyRendered = change == mbgl::MapChangeDidFinishRenderingFrameFullyRendered;
[self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:fullyRendered];
@@ -896,6 +911,11 @@ public:
}
case mbgl::MapChangeDidFinishLoadingStyle:
{
[self.style willChangeValueForKey:@"name"];
[self.style willChangeValueForKey:@"sources"];
[self.style didChangeValueForKey:@"sources"];
[self.style willChangeValueForKey:@"layers"];
[self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
{
[self.delegate mapView:self didFinishLoadingStyle:self.style];
@@ -1705,6 +1725,7 @@ public:
continue;
}
_isChangingAnnotationLayers = YES;
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation([multiPoint annotationObjectWithDelegate:self]);
MGLAnnotationContext context;
context.annotation = annotation;
@@ -1762,6 +1783,9 @@ public:
}
[self didChangeValueForKey:@"annotations"];
if (_isChangingAnnotationLayers) {
[self.style willChangeValueForKey:@"layers"];
}
[self updateAnnotationTrackingAreas];
}
@@ -1843,10 +1867,14 @@ public:
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinates" context:(void *)(NSUInteger)annotationTag];
}
_isChangingAnnotationLayers = YES;
_mbglMap->removeAnnotation(annotationTag);
}
[self didChangeValueForKey:@"annotations"];
if (_isChangingAnnotationLayers) {
[self.style willChangeValueForKey:@"layers"];
}
[self updateAnnotationTrackingAreas];
}
@@ -2200,13 +2228,6 @@ public:
#pragma mark - Runtime styling
- (MGLStyle *)style
{
MGLStyle *style = [[MGLStyle alloc] init];
style.mapView = self;
return style;
}
- (mbgl::Map *)mbglMap
{
return _mbglMap;