[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:
committed by
Minh Nguyễn
parent
850b70ff91
commit
9fac640bf3
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user