Skip to content

Commit

Permalink
Merge branch 'release' into tripomatic
Browse files Browse the repository at this point in the history
* release:
  1.4.1 bumps
  bring back & properly deprecate marker sort properties
  tweak changelog for deprecations
  bump podspec version
  update changelog for 1.4.0
  remove v4 API support
  closes route-me#160 route-me#164 #491: annotation layer sorting delegate method
  fix inconsistent doc
  fixes #239: properly close interior polygons
  Fix memory leak in RMShape by holding a weak reference to the map view.
  fixes #486: assert different great circle coordinates
  refs #386: remember early tile source setups
  • Loading branch information
username0x0a committed Oct 10, 2014
2 parents b6030f7 + 509fa7d commit 6ad679d
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 53 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
Changelog
---------

### 1.4.1
#### September 5, 2014

- Properly deprecated `-[RMMapView orderMarkersByYPosition]` and `-[RMMapView orderClusterMarkersAboveOthers]`.

### 1.4.0
#### September 4, 2014

- Temporarily removed support for Mapbox `v4` API and [access tokens](https://www.mapbox.com/developers/api/#access-tokens) in tile and metadata requests.
- Added a new `-[RMMapViewDelegate annotationSortingComparatorForMapView:]` callback allowing customization of annotation layer stacking order. This deprecates `-[RMMapView orderMarkersByYPosition]` and `-[RMMapView orderClusterMarkersAboveOthers]`.
- Fixed a bug with tile source initialization in `-viewDidLoad` and/or from storyboards.
- Better enforce proper `RMGreatCircleAnnotation` initialization.
- Fixed a memory leak in `RMShape`.
- Fixed a bug with drawing of `RMPolygonAnnotation` interior polygons.
- Documentation fixes.

### 1.3.0
#### August 14, 2014

Expand Down
8 changes: 7 additions & 1 deletion MapView/Map/RMAnnotation.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@

#import "RMFoundation.h"

#define kRMTrackingHaloAnnotationTypeName @"RMTrackingHaloAnnotation"
#define kRMAccuracyCircleAnnotationTypeName @"RMAccuracyCircleAnnotation"

@class RMMapView, RMMapLayer, RMQuadTreeNode;

/** An RMAnnotation defines a container for annotation data to be placed on a map. At a future point in time, depending on map use, a visible layer may be requested and displayed for the annotation. The layer is provided by an RMMapView's delegate when first needed for display.
Expand Down Expand Up @@ -76,9 +79,12 @@
@property (nonatomic, strong) UIImage *badgeIcon;
@property (nonatomic, assign) CGPoint anchorPoint;

/** The annotation's current location on screen. Do not set this directly unless during temporary operations such as animations, but rather use the coordinate property to permanently change the annotation's location on the map. */
/** The annotation's current location on screen relative to the map. Do not set this directly unless during temporary operations such as animations, but rather use the coordinate property to permanently change the annotation's location on the map. */
@property (nonatomic, assign) CGPoint position;

/** The annotation's absolute location on screen taking into account possible map rotation. */
@property (nonatomic, readonly, assign) CGPoint absolutePosition;

@property (nonatomic, assign) RMProjectedPoint projectedLocation; // in projected meters
@property (nonatomic, assign) RMProjectedRect projectedBoundingBox;
@property (nonatomic, assign) BOOL hasBoundingBox;
Expand Down
5 changes: 5 additions & 0 deletions MapView/Map/RMAnnotation.m
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ - (void)setPosition:(CGPoint)aPosition
[self setPosition:aPosition animated:YES];
}

- (CGPoint)absolutePosition
{
return [self.mapView.layer convertPoint:self.position fromLayer:self.layer.superlayer];
}

- (RMMapLayer *)layer
{
return layer;
Expand Down
6 changes: 4 additions & 2 deletions MapView/Map/RMConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@

/** @name Authorizing Access */

/** A Mapbox API access token. Obtain an access token on your [Mapbox account page](https://www.mapbox.com/account/apps/). Setting an access token will use Mapbox's `v4` API, otherwise `v3` will be used. At a future date, `v3` support will be phased out of the library. */
@property (nonatomic, retain) NSString *accessToken;
/** A Mapbox API access token. Obtain an access token on your [Mapbox account page](https://www.mapbox.com/account/apps/). Setting an access token will use Mapbox's `v4` API, otherwise `v3` will be used. At a future date, `v3` support will be phased out of the library.
*
* @warning Use of the Mapbox `v4` API is currently not supported. */
@property (nonatomic, readonly, retain) NSString *accessToken;

/** @name Cache Configuration */

Expand Down
2 changes: 2 additions & 0 deletions MapView/Map/RMGreatCircleAnnotation.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ @implementation RMGreatCircleAnnotation

- (id)initWithMapView:(RMMapView *)aMapView coordinate1:(CLLocationCoordinate2D)coordinate1 coordinate2:(CLLocationCoordinate2D)coordinate2
{
NSAssert(coordinate1.latitude != coordinate2.latitude || coordinate1.longitude != coordinate2.longitude, @"Start and end coordinates must differ.");

if (!(self = [super initWithMapView:aMapView points:@[ [[CLLocation alloc] initWithLatitude:coordinate1.latitude longitude:coordinate1.longitude], [[CLLocation alloc] initWithLatitude:coordinate2.latitude longitude:coordinate2.longitude]]]))
return nil;

Expand Down
16 changes: 10 additions & 6 deletions MapView/Map/RMMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ typedef enum : NSUInteger {
/** Remove all annotations from the map. This does not remove user location annotations, if any. */
- (void)removeAllAnnotations;

/** The screen position for a given annotation.
* @param annotation The annotation for which to return the current screen position.
/** The relative map position for a given annotation.
* @param annotation The annotation for which to return the current position.
* @return The screen position of the annotation. */
- (CGPoint)mapPositionForAnnotation:(RMAnnotation *)annotation;

Expand Down Expand Up @@ -357,14 +357,18 @@ typedef enum : NSUInteger {
/** Whether to enable clustering of map point annotations. Defaults to `NO`. */
@property (nonatomic, assign) BOOL clusteringEnabled;

/** Whether to order markers on the z-axis according to increasing y-position. Defaults to `YES`. */
@property (nonatomic, assign) BOOL orderMarkersByYPosition;
/** Whether to order markers on the z-axis according to increasing y-position. Defaults to `YES`.
*
* @warning This property has been deprecated in favor of [RMMapViewDelegate annotationSortingComparatorForMapView:]. */
@property (nonatomic, assign) BOOL orderMarkersByYPosition __attribute__((deprecated("use -[RMMapViewDelegate annotationSortingComparatorForMapView:] for annotation sorting")));

/** Whether to position cluster markers at the weighted center of the points they represent. If `YES`, position clusters in weighted fashion. If `NO`, position them on a rectangular grid. Defaults to `YES`. */
@property (nonatomic, assign) BOOL positionClusterMarkersAtTheGravityCenter;

/** Whether to order cluster markers above non-clustered markers. Defaults to `NO`. */
@property (nonatomic, assign) BOOL orderClusterMarkersAboveOthers;
/** Whether to order cluster markers above non-clustered markers. Defaults to `YES`.
*
* @warning This property has been deprecated in favor of [RMMapViewDelegate annotationSortingComparatorForMapView:]. */
@property (nonatomic, assign) BOOL orderClusterMarkersAboveOthers __attribute__((deprecated("use -[RMMapViewDelegate annotationSortingComparatorForMapView:] for annotation sorting")));

@property (nonatomic, assign) CGSize clusterMarkerSize;
@property (nonatomic, assign) CGSize clusterAreaSize;
Expand Down
168 changes: 127 additions & 41 deletions MapView/Map/RMMapView.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@
#define kDefaultMaximumZoomLevel 25.0
#define kDefaultInitialZoomLevel 11.0

#define kRMTrackingHaloAnnotationTypeName @"RMTrackingHaloAnnotation"
#define kRMAccuracyCircleAnnotationTypeName @"RMAccuracyCircleAnnotation"

#pragma mark --- end constants ----

@interface RMMapView (PrivateMethods) <UIScrollViewDelegate,
Expand Down Expand Up @@ -150,6 +147,7 @@ @implementation RMMapView
BOOL _delegateHasShouldDragAnnotation;
BOOL _delegateHasDidChangeDragState;
BOOL _delegateHasLayerForAnnotation;
BOOL _delegateHasAnnotationSorting;
BOOL _delegateHasWillHideLayerForAnnotation;
BOOL _delegateHasDidHideLayerForAnnotation;
BOOL _delegateHasDidSelectAnnotation;
Expand All @@ -170,6 +168,8 @@ @implementation RMMapView
RMFractalTileProjection *_mercatorToTileProjection;
RMTileSourcesContainer *_tileSourcesContainer;

NSMutableArray *_earlyTileSources;

NSMutableSet *_annotations;
NSMutableSet *_visibleAnnotations;

Expand Down Expand Up @@ -300,13 +300,33 @@ - (void)performInitializationWithTilesource:(id <RMTileSource>)newTilesource
[self setBackgroundView:nil];
}

if (initialTileSourceMinZoomLevel < newTilesource.minZoom) initialTileSourceMinZoomLevel = newTilesource.minZoom;
if (initialTileSourceMaxZoomLevel > newTilesource.maxZoom) initialTileSourceMaxZoomLevel = newTilesource.maxZoom;
if ([_earlyTileSources count])
{
for (id<RMTileSource>earlyTileSource in _earlyTileSources)
{
if (initialTileSourceMinZoomLevel < earlyTileSource.minZoom) initialTileSourceMinZoomLevel = earlyTileSource.minZoom;
if (initialTileSourceMaxZoomLevel > earlyTileSource.maxZoom) initialTileSourceMaxZoomLevel = earlyTileSource.maxZoom;
}
}
else
{
if (initialTileSourceMinZoomLevel < newTilesource.minZoom) initialTileSourceMinZoomLevel = newTilesource.minZoom;
if (initialTileSourceMaxZoomLevel > newTilesource.maxZoom) initialTileSourceMaxZoomLevel = newTilesource.maxZoom;
}
[self setTileSourcesMinZoom:initialTileSourceMinZoomLevel];
[self setTileSourcesMaxZoom:initialTileSourceMaxZoomLevel];
[self setTileSourcesZoom:initialTileSourceZoomLevel];

[self setTileSource:newTilesource];
if ([_earlyTileSources count])
{
[self setTileSources:_earlyTileSources];
[_earlyTileSources removeAllObjects];
}
else
{
[self setTileSource:newTilesource];
}

[self setCenterCoordinate:initialCenterCoordinate animated:NO];

[self setDecelerationMode:RMMapDecelerationFast];
Expand Down Expand Up @@ -381,6 +401,8 @@ - (id)initWithFrame:(CGRect)frame
if (!newTilesource || !(self = [super initWithFrame:frame]))
return nil;

_earlyTileSources = [NSMutableArray array];

[self performInitializationWithTilesource:newTilesource
centerCoordinate:initialCenterCoordinate
zoomLevel:initialZoomLevel
Expand All @@ -391,6 +413,16 @@ - (id)initWithFrame:(CGRect)frame
return self;
}

- (id)initWithCoder:(NSCoder *)decoder
{
if (![super initWithCoder:decoder])
return nil;

_earlyTileSources = [NSMutableArray array];

return self;
}

- (void)setFrame:(CGRect)frame
{
CGRect r = self.frame;
Expand Down Expand Up @@ -679,6 +711,7 @@ - (void)setDelegate:(id <RMMapViewDelegate>)aDelegate
_delegateHasDidChangeDragState = [_delegate respondsToSelector:@selector(mapView:annotation:didChangeDragState:fromOldState:)];

_delegateHasLayerForAnnotation = [_delegate respondsToSelector:@selector(mapView:layerForAnnotation:)];
_delegateHasAnnotationSorting = [_delegate respondsToSelector:@selector(annotationSortingComparatorForMapView:)];
_delegateHasWillHideLayerForAnnotation = [_delegate respondsToSelector:@selector(mapView:willHideLayerForAnnotation:)];
_delegateHasDidHideLayerForAnnotation = [_delegate respondsToSelector:@selector(mapView:didHideLayerForAnnotation:)];

Expand Down Expand Up @@ -2124,6 +2157,16 @@ - (void)setTileSource:(id <RMTileSource>)tileSource

- (void)setTileSources:(NSArray *)tileSources
{
if ( ! _tileSourcesContainer)
{
// If we've reached this point, it's because our scroll view etc.
// aren't yet setup. So let's remember the tile source(s) set so that
// we can apply them later on once we're properly initialized.
//
[_earlyTileSources setArray:tileSources];
return;
}

if ( ! [_tileSourcesContainer setTileSources:tileSources])
return;

Expand Down Expand Up @@ -2152,6 +2195,16 @@ - (void)addTileSource:(id <RMTileSource>)tileSource

- (void)addTileSource:(id<RMTileSource>)newTileSource atIndex:(NSUInteger)index
{
if ( ! _tileSourcesContainer)
{
// If we've reached this point, it's because our scroll view etc.
// aren't yet setup. So let's remember the tile source(s) set so that
// we can apply them later on once we're properly initialized.
//
[_earlyTileSources insertObject:newTileSource atIndex:(index > [_earlyTileSources count] ? 0 : index)];
return;
}

if ([_tileSourcesContainer.tileSources containsObject:newTileSource])
return;

Expand Down Expand Up @@ -2957,7 +3010,6 @@ - (void)correctPositionOfAllAnnotationsIncludingInvisibles:(BOOL)correctAllAnnot
if ([annotation.layer isKindOfClass:[RMMarker class]])
annotation.layer.transform = _annotationTransform;

// Use the zPosition property to order the layer hierarchy
if ( ! [_visibleAnnotations containsObject:annotation])
{
[_overlayView addSublayer:annotation.layer];
Expand Down Expand Up @@ -3063,54 +3115,90 @@ - (void)correctPositionOfAllAnnotations

- (void)correctOrderingOfAllAnnotations
{
if ( ! _orderMarkersByYPosition)
return;

// sort annotation layer z-indexes so that they overlap properly
//
NSMutableArray *sortedAnnotations = [NSMutableArray arrayWithArray:[_visibleAnnotations allObjects]];

[sortedAnnotations filterUsingPredicate:[NSPredicate predicateWithFormat:@"isUserLocationAnnotation = NO"]];
NSComparator comparator;

[sortedAnnotations sortUsingComparator:^(id obj1, id obj2)
if (_delegateHasAnnotationSorting && (comparator = [_delegate annotationSortingComparatorForMapView:self]))
{
RMAnnotation *annotation1 = (RMAnnotation *)obj1;
RMAnnotation *annotation2 = (RMAnnotation *)obj2;

// clusters above/below non-clusters (based on _orderClusterMarkersAboveOthers)
// Sort using the custom comparator.
//
[sortedAnnotations sortUsingComparator:comparator];
}
else
{
// Sort using the default comparator.
//
if ( annotation1.isClusterAnnotation && ! annotation2.isClusterAnnotation)
return (_orderClusterMarkersAboveOthers ? NSOrderedDescending : NSOrderedAscending);
[sortedAnnotations sortUsingComparator:^(RMAnnotation *annotation1, RMAnnotation *annotation2)
{
// Sort user location annotations below all.
//
if ( annotation1.isUserLocationAnnotation && ! annotation2.isUserLocationAnnotation)
return NSOrderedAscending;

if ( ! annotation1.isClusterAnnotation && annotation2.isClusterAnnotation)
return (_orderClusterMarkersAboveOthers ? NSOrderedAscending : NSOrderedDescending);
if ( ! annotation1.isUserLocationAnnotation && annotation2.isUserLocationAnnotation)
return NSOrderedDescending;

// markers above shapes
//
if ( [annotation1.layer isKindOfClass:[RMMarker class]] && ! [annotation2.layer isKindOfClass:[RMMarker class]])
return NSOrderedDescending;
// Amongst user location annotations, sort properly.
//
if (annotation1.isUserLocationAnnotation && annotation2.isUserLocationAnnotation)
{
// User dot on top.
//
if ([annotation1 isKindOfClass:[RMUserLocation class]])
return NSOrderedDescending;

if ( ! [annotation1.layer isKindOfClass:[RMMarker class]] && [annotation2.layer isKindOfClass:[RMMarker class]])
return NSOrderedAscending;
if ([annotation2 isKindOfClass:[RMUserLocation class]])
return NSOrderedAscending;

// the rest in increasing y-position
//
CGPoint obj1Point = [self convertPoint:annotation1.position fromView:_overlayView];
CGPoint obj2Point = [self convertPoint:annotation2.position fromView:_overlayView];
// Halo above accuracy circle.
//
if ([annotation1.annotationType isEqualToString:kRMTrackingHaloAnnotationTypeName])
return NSOrderedDescending;

if (obj1Point.y > obj2Point.y)
return NSOrderedDescending;
if ([annotation2.annotationType isEqualToString:kRMTrackingHaloAnnotationTypeName])
return NSOrderedAscending;
}

if (obj1Point.y < obj2Point.y)
return NSOrderedAscending;
// Return early if we're not otherwise sorting annotations.
//
if ( ! _orderMarkersByYPosition)
return NSOrderedSame;

return NSOrderedSame;
}];
// Sort clusters above non-clusters (factoring in orderClusterMarkersAboveOthers).
//
if ( annotation1.isClusterAnnotation && ! annotation2.isClusterAnnotation)
return (_orderClusterMarkersAboveOthers ? NSOrderedDescending : NSOrderedAscending);

if ( ! annotation1.isClusterAnnotation && annotation2.isClusterAnnotation)
return (_orderClusterMarkersAboveOthers ? NSOrderedAscending : NSOrderedDescending);

// Sort markers above shapes.
//
if ( [annotation1.layer isKindOfClass:[RMMarker class]] && ! [annotation2.layer isKindOfClass:[RMMarker class]])
return NSOrderedDescending;

if ( ! [annotation1.layer isKindOfClass:[RMMarker class]] && [annotation2.layer isKindOfClass:[RMMarker class]])
return NSOrderedAscending;

// Sort the rest in increasing y-position.
//
if (annotation1.absolutePosition.y > annotation2.absolutePosition.y)
return NSOrderedDescending;

if (annotation1.absolutePosition.y < annotation2.absolutePosition.y)
return NSOrderedAscending;

return NSOrderedSame;
}];
}

// Apply layering values based on sort order.
//
for (CGFloat i = 0; i < [sortedAnnotations count]; i++)
((RMAnnotation *)[sortedAnnotations objectAtIndex:i]).layer.zPosition = (CGFloat)i;

// bring any active callout annotation to the front
// Bring any active callout annotation to the front.
//
if (_currentAnnotation)
_currentAnnotation.layer.zPosition = _currentCallout.layer.zPosition = MAXFLOAT;
Expand Down Expand Up @@ -3501,7 +3589,6 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLoca
_accuracyCircleAnnotation.clusteringEnabled = NO;
_accuracyCircleAnnotation.enabled = NO;
_accuracyCircleAnnotation.layer = [[RMCircle alloc] initWithView:self radiusInMeters:newLocation.horizontalAccuracy];
_accuracyCircleAnnotation.layer.zPosition = -MAXFLOAT;
_accuracyCircleAnnotation.isUserLocationAnnotation = YES;

((RMCircle *)_accuracyCircleAnnotation.layer).lineColor = (RMPreVersion7 ? [UIColor colorWithRed:0.378 green:0.552 blue:0.827 alpha:0.7] : [UIColor clearColor]);
Expand Down Expand Up @@ -3552,7 +3639,6 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLoca
// create image marker
//
_trackingHaloAnnotation.layer = [[RMMarker alloc] initWithUIImage:[self trackingDotHaloImage]];
_trackingHaloAnnotation.layer.zPosition = -MAXFLOAT + 1;
_trackingHaloAnnotation.isUserLocationAnnotation = YES;

[CATransaction begin];
Expand Down
Loading

0 comments on commit 6ad679d

Please sign in to comment.