Authored by Justin R. Miller

Merge branch 'develop' into release

Pod::Spec.new do |m|
m.name = 'MapBox'
m.version = '0.5.1'
m.version = '0.5.2'
m.summary = 'Open source alternative to MapKit.'
m.description = 'Open source alternative to MapKit supporting custom tile sources, offline use, and complete cache control.'
... ...
... ... @@ -67,7 +67,7 @@
{
if ( ! _imageURLString)
{
NSString *imagerySetString;
NSString *imagerySetString = nil;
if (_imagerySet == RMBingImagerySetAerial)
imagerySetString = @"Aerial";
... ...
... ... @@ -70,6 +70,8 @@
circlePath = NULL;
[self updateCirclePathAnimated:NO];
self.masksToBounds = NO;
return self;
}
... ... @@ -132,6 +134,11 @@
#pragma mark - Accessors
- (BOOL)containsPoint:(CGPoint)thePoint
{
return CGPathContainsPoint(shapeLayer.path, nil, thePoint, [shapeLayer.fillRule isEqualToString:kCAFillRuleEvenOdd]);
}
- (void)setLineColor:(UIColor *)newLineColor
{
if (lineColor != newLineColor)
... ...
... ... @@ -103,7 +103,7 @@
[[NSNotificationCenter defaultCenter] postNotificationName:RMTileRequested object:[NSNumber numberWithUnsignedLongLong:RMTileKey(tile)]];
});
__block UIImage *image;
__block UIImage *image = nil;
[queue inDatabase:^(FMDatabase *db)
{
... ... @@ -250,7 +250,7 @@
- (NSString *)legend
{
__block NSString *legend;
__block NSString *legend = nil;
[queue inDatabase:^(FMDatabase *db)
{
... ... @@ -332,7 +332,7 @@
- (NSString *)shortName
{
__block NSString *shortName;
__block NSString *shortName = nil;
[queue inDatabase:^(FMDatabase *db)
{
... ... @@ -353,7 +353,7 @@
- (NSString *)longDescription
{
__block NSString *description;
__block NSString *description = nil;
[queue inDatabase:^(FMDatabase *db)
{
... ... @@ -374,7 +374,7 @@
- (NSString *)shortAttribution
{
__block NSString *attribution;
__block NSString *attribution = nil;
[queue inDatabase:^(FMDatabase *db)
{
... ...
... ... @@ -70,7 +70,7 @@
options:0
error:nil] retain];
id dataObject;
id dataObject = nil;
if (mapView && (dataObject = [_infoDictionary objectForKey:@"data"]) && dataObject)
{
... ... @@ -80,7 +80,7 @@
{
NSURL *dataURL = [NSURL URLWithString:[dataObject objectAtIndex:0]];
NSMutableString *jsonString;
NSMutableString *jsonString = nil;
if (dataURL && (jsonString = [NSMutableString stringWithContentsOfURL:dataURL encoding:NSUTF8StringEncoding error:nil]) && jsonString)
{
... ... @@ -90,7 +90,7 @@
[jsonString replaceCharactersInRange:NSMakeRange([jsonString length] - 2, 2) withString:@""];
}
id jsonObject;
id jsonObject = nil;
if ((jsonObject = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]) && [jsonObject isKindOfClass:[NSDictionary class]])
{
... ... @@ -146,7 +146,7 @@
- (id)initWithReferenceURL:(NSURL *)referenceURL enablingDataOnMapView:(RMMapView *)mapView
{
id dataObject;
id dataObject = nil;
if ([[referenceURL pathExtension] isEqualToString:@"jsonp"])
referenceURL = [NSURL URLWithString:[[referenceURL absoluteString] stringByReplacingOccurrencesOfString:@".jsonp"
... ... @@ -198,7 +198,7 @@
if ([self.infoDictionary objectForKey:@"scheme"] && [[self.infoDictionary objectForKey:@"scheme"] isEqual:@"tms"])
y = pow(2, zoom) - tile.y - 1;
NSString *tileURLString;
NSString *tileURLString = nil;
if ([self.infoDictionary objectForKey:@"tiles"])
tileURLString = [[self.infoDictionary objectForKey:@"tiles"] objectAtIndex:0];
... ... @@ -212,7 +212,7 @@
if (_imageQuality != RMMapBoxSourceQualityFull)
{
NSString *qualityExtension;
NSString *qualityExtension = nil;
switch (_imageQuality)
{
... ... @@ -282,7 +282,7 @@
{
id bounds = [self.infoDictionary objectForKey:@"bounds"];
NSArray *parts;
NSArray *parts = nil;
if ([bounds isKindOfClass:[NSArray class]])
parts = bounds;
... ...
... ... @@ -67,6 +67,11 @@
* If the value of this property is `NO`, the value of the title string is ignored and the annotation remains enabled by default. You can still disable the annotation explicitly using the enabled property. */
@property (nonatomic, assign) BOOL canShowCallout;
/** The offset (in pixels) at which to place the callout bubble.
*
* This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the annotation view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left. */
@property (nonatomic, assign) CGPoint calloutOffset;
/** The view to display on the left side of the standard callout bubble.
*
* The default value of this property is `nil`. The left callout view is typically used to display information about the annotation or to link to custom information provided by your application. The height of your view should be 32 pixels or less.
... ...
... ... @@ -35,6 +35,7 @@
@synthesize enableDragging;
@synthesize userInfo;
@synthesize canShowCallout;
@synthesize calloutOffset;
@synthesize leftCalloutAccessoryView;
@synthesize rightCalloutAccessoryView;
... ... @@ -45,6 +46,7 @@
self.annotation = nil;
self.enableDragging = NO;
self.calloutOffset = CGPointZero;
return self;
}
... ... @@ -56,6 +58,7 @@
self.annotation = nil;
self.userInfo = nil;
self.calloutOffset = CGPointZero;
return self;
}
... ...
... ... @@ -330,6 +330,21 @@ typedef enum : NSUInteger {
* @return The screen position of the annotation. */
- (CGPoint)mapPositionForAnnotation:(RMAnnotation *)annotation;
/** Selects the specified annotation and displays a callout view for it.
*
* If the specified annotation is not onscreen, and therefore does not have an associated annotation layer, this method has no effect.
* @param annotation The annotation object to select.
* @param animated If `YES`, the callout view is animated into position. */
- (void)selectAnnotation:(RMAnnotation *)annotation animated:(BOOL)animated;
/** Deselects the specified annotation and hides its callout view.
* @param annotation The annotation object to deselect.
* @param animated If `YES`, the callout view is animated offscreen. */
- (void)deselectAnnotation:(RMAnnotation *)annotation animated:(BOOL)animated;
/** The annotation that is currently selected. */
@property (nonatomic, retain) RMAnnotation *selectedAnnotation;
#pragma mark - TileSources
@property (nonatomic, retain) RMQuadTree *quadTree;
... ...
... ... @@ -1472,6 +1472,22 @@
else
{
[self correctPositionOfAllAnnotationsIncludingInvisibles:NO animated:(_mapScrollViewIsZooming && !_mapScrollView.zooming)];
if (_currentAnnotation && ! [_currentAnnotation isKindOfClass:[RMMarker class]])
{
// adjust shape annotation callouts for frame changes during zoom
//
_currentCallout.delegate = nil;
[_currentCallout presentCalloutFromRect:_currentAnnotation.layer.bounds
inLayer:_currentAnnotation.layer
constrainedToLayer:self.layer
permittedArrowDirections:SMCalloutArrowDirectionDown
animated:NO];
_currentCallout.delegate = self;
}
_lastZoom = _zoom;
}
... ... @@ -1511,19 +1527,7 @@
if (_currentAnnotation && ! [hit isEqual:_currentAnnotation.layer])
{
[self correctPositionOfAllAnnotations];
BOOL animated = ( ! [hit isKindOfClass:[RMMarker class]]);
[_currentCallout dismissCalloutAnimated:animated];
if (animated)
[self performSelector:@selector(correctPositionOfAllAnnotations) withObject:nil afterDelay:1.0/3.0];
else
[self correctPositionOfAllAnnotations];
[_currentAnnotation release]; _currentAnnotation = nil;
[_currentCallout release]; _currentCallout = nil;
[self deselectAnnotation:_currentAnnotation animated:( ! [hit isKindOfClass:[RMMarker class]])];
}
if ( ! hit)
... ... @@ -1699,33 +1703,8 @@
- (void)tapOnAnnotation:(RMAnnotation *)anAnnotation atPoint:(CGPoint)aPoint
{
if (anAnnotation.layer && anAnnotation.layer.canShowCallout && anAnnotation.title && ! [anAnnotation isEqual:_currentAnnotation])
if (anAnnotation.layer && anAnnotation.isAnnotationOnScreen && anAnnotation.layer.canShowCallout && anAnnotation.title && ! [anAnnotation isEqual:_currentAnnotation])
{
_currentAnnotation = [anAnnotation retain];
_currentCallout = [SMCalloutView new];
_currentCallout.title = anAnnotation.title;
_currentCallout.subtitle = anAnnotation.subtitle;
if (anAnnotation.layer.leftCalloutAccessoryView)
{
if ([anAnnotation.layer.leftCalloutAccessoryView isKindOfClass:[UIControl class]])
[anAnnotation.layer.leftCalloutAccessoryView addGestureRecognizer:[[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOnCalloutAccessoryWithGestureRecognizer:)] autorelease]];
_currentCallout.leftAccessoryView = anAnnotation.layer.leftCalloutAccessoryView;
}
if (anAnnotation.layer.rightCalloutAccessoryView)
{
if ([anAnnotation.layer.rightCalloutAccessoryView isKindOfClass:[UIControl class]])
[anAnnotation.layer.rightCalloutAccessoryView addGestureRecognizer:[[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOnCalloutAccessoryWithGestureRecognizer:)] autorelease]];
_currentCallout.rightAccessoryView = anAnnotation.layer.rightCalloutAccessoryView;
}
_currentCallout.delegate = self;
[self performSelector:@selector(popupCalloutViewForAnnotation:) withObject:anAnnotation afterDelay:1.0/3.0]; // allows for MapKit-like delay
}
... ... @@ -1753,8 +1732,76 @@
return [super hitTest:point withEvent:event];
}
- (void)selectAnnotation:(RMAnnotation *)annotation animated:(BOOL)animated
{
if (annotation.isAnnotationOnScreen && ! [annotation isEqual:_currentAnnotation])
{
[self deselectAnnotation:_currentAnnotation animated:NO];
[self popupCalloutViewForAnnotation:annotation animated:animated];
}
}
- (void)deselectAnnotation:(RMAnnotation *)annotation animated:(BOOL)animated
{
if ([annotation isEqual:_currentAnnotation] && _currentCallout)
{
[_currentCallout dismissCalloutAnimated:animated];
if (animated)
[self performSelector:@selector(correctPositionOfAllAnnotations) withObject:nil afterDelay:1.0/3.0];
else
[self correctPositionOfAllAnnotations];
[_currentAnnotation release]; _currentAnnotation = nil;
[_currentCallout release]; _currentCallout = nil;
}
}
- (void)setSelectedAnnotation:(RMAnnotation *)selectedAnnotation
{
if ( ! [selectedAnnotation isEqual:_currentAnnotation])
[self selectAnnotation:selectedAnnotation animated:YES];
}
- (RMAnnotation *)selectedAnnotation
{
return _currentAnnotation;
}
- (void)popupCalloutViewForAnnotation:(RMAnnotation *)anAnnotation
{
[self popupCalloutViewForAnnotation:anAnnotation animated:YES];
}
- (void)popupCalloutViewForAnnotation:(RMAnnotation *)anAnnotation animated:(BOOL)animated
{
_currentAnnotation = [anAnnotation retain];
_currentCallout = [SMCalloutView new];
_currentCallout.title = anAnnotation.title;
_currentCallout.subtitle = anAnnotation.subtitle;
_currentCallout.calloutOffset = anAnnotation.layer.calloutOffset;
if (anAnnotation.layer.leftCalloutAccessoryView)
{
if ([anAnnotation.layer.leftCalloutAccessoryView isKindOfClass:[UIControl class]])
[anAnnotation.layer.leftCalloutAccessoryView addGestureRecognizer:[[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOnCalloutAccessoryWithGestureRecognizer:)] autorelease]];
_currentCallout.leftAccessoryView = anAnnotation.layer.leftCalloutAccessoryView;
}
if (anAnnotation.layer.rightCalloutAccessoryView)
{
if ([anAnnotation.layer.rightCalloutAccessoryView isKindOfClass:[UIControl class]])
[anAnnotation.layer.rightCalloutAccessoryView addGestureRecognizer:[[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOnCalloutAccessoryWithGestureRecognizer:)] autorelease]];
_currentCallout.rightAccessoryView = anAnnotation.layer.rightCalloutAccessoryView;
}
_currentCallout.delegate = self;
[self correctPositionOfAllAnnotations];
anAnnotation.layer.zPosition = _currentCallout.layer.zPosition = MAXFLOAT;
... ... @@ -1763,7 +1810,7 @@
inLayer:anAnnotation.layer
constrainedToLayer:self.layer
permittedArrowDirections:SMCalloutArrowDirectionDown
animated:YES];
animated:animated];
}
- (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset
... ... @@ -2822,6 +2869,9 @@
{
@synchronized (_annotations)
{
if ([_annotations containsObject:annotation])
return;
[_annotations addObject:annotation];
[self.quadTree addAnnotation:annotation];
}
... ...
... ... @@ -94,7 +94,7 @@
- (id)initWithMapBoxMarkerImage:(NSString *)symbolName tintColor:(UIColor *)color size:(RMMarkerMapBoxImageSize)size
{
NSString *sizeString;
NSString *sizeString = nil;
switch (size)
{
... ... @@ -112,7 +112,7 @@
break;
}
NSString *colorHex;
NSString *colorHex = nil;
if (color)
{
... ... @@ -140,7 +140,7 @@
(colorHex ? [@"+" stringByAppendingString:[colorHex stringByReplacingOccurrencesOfString:@"#" withString:@""]] : @"+ff0000"),
(useRetina ? @"@2x" : @"")]];
UIImage *image;
UIImage *image = nil;
NSString *cachePath = [NSString stringWithFormat:@"%@/%@", kCachesPath, [imageURL lastPathComponent]];
... ...
... ... @@ -631,7 +631,8 @@
{
@synchronized (self)
{
[_rootNode addAnnotation:annotation];
if ( ! [_rootNode.annotations containsObject:annotation])
[_rootNode addAnnotation:annotation];
}
}
... ... @@ -643,9 +644,8 @@
@synchronized (self)
{
for (RMAnnotation *annotation in annotations)
{
[_rootNode addAnnotation:annotation];
}
if ( ! [_rootNode.annotations containsObject:annotation])
[_rootNode addAnnotation:annotation];
}
}
... ...
... ... @@ -85,7 +85,7 @@
previousBounds = CGRectZero;
lastScale = 0.0;
self.masksToBounds = YES;
self.masksToBounds = NO;
scaleLineWidth = NO;
scaleLineDash = NO;
... ... @@ -187,7 +187,7 @@
// Clip bound rect to screen bounds.
// If bounds are not clipped, they won't display when you zoom in too much.
CGRect screenBounds = [mapView frame];
CGRect screenBounds = [mapView bounds];
// we start with the non-clipped bounds and clip them
CGRect clippedBounds = nonClippedBounds;
... ... @@ -435,6 +435,11 @@
#pragma mark - Accessors
- (BOOL)containsPoint:(CGPoint)thePoint
{
return CGPathContainsPoint(shapeLayer.path, nil, thePoint, [shapeLayer.fillRule isEqualToString:kCAFillRuleEvenOdd]);
}
- (void)closePath
{
if ([points count])
... ...
... ... @@ -90,3 +90,12 @@ To report bugs and help fix them, please use the [issue tracker][tracker].
[support]: http://support.mapbox.com/discussions/mapbox-ios-sdk
[docs]: http://mapbox.com/mapbox-ios-sdk/
[tracker]: https://github.com/mapbox/mapbox-ios-sdk/issues
Dependent Libraries
-------------------
The MapBox iOS SDK makes use of several sub-libraries, listed below. See License.txt for more detailed information about Route-Me and Proj4 and see the individual license files in the sub-libraries for more information on each.
FMDB by Gus Mueller (SQLite for caching and MBTiles)
GRMustache by Gwendal Roué (Mustache templates)
SMCalloutView by Nick Farina (annotation callouts)
... ...