Authored by Justin R. Miller

Merge branch 'develop' into arc

... ... @@ -3,12 +3,28 @@ MapBox iOS SDK copyright (c) 2012, MapBox.
The Route-Me library is copyright (c) 2008-2012, Route-Me Contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Route-Me depends on the Proj4 Library. [ http://trac.osgeo.org/proj/wiki/WikiStart ]
... ... @@ -31,4 +47,3 @@ Proj4 is copyright (c) 2000, Frank Warmerdam
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
... ...
... ... @@ -32,6 +32,7 @@
#import "RMCacheObject.h"
#import "RMCircle.h"
#import "RMCompositeSource.h"
#import "RMConfiguration.h"
#import "RMCoordinateGridSource.h"
#import "RMDatabaseCache.h"
#import "RMInteractiveSource.h"
... ...
... ... @@ -26,7 +26,9 @@
// POSSIBILITY OF SUCH DAMAGE.
#import "RMAbstractWebMapSource.h"
#import "RMTileCache.h"
#import "RMConfiguration.h"
#define HTTP_404_NOT_FOUND 404
... ... @@ -106,7 +108,7 @@
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:currentURL];
[request setTimeoutInterval:(self.requestTimeoutSeconds / (CGFloat)self.retryCount)];
tileData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
tileData = [NSURLConnection sendBrandedSynchronousRequest:request returningResponse:nil error:nil];
}
if (tileData)
... ... @@ -155,7 +157,7 @@
NSHTTPURLResponse *response = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[URLs objectAtIndex:0]];
[request setTimeoutInterval:(self.requestTimeoutSeconds / (CGFloat)self.retryCount)];
image = [UIImage imageWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]];
image = [UIImage imageWithData:[NSURLConnection sendBrandedSynchronousRequest:request returningResponse:&response error:nil]];
if (response.statusCode == HTTP_404_NOT_FOUND)
break;
... ...
... ... @@ -86,9 +86,6 @@
/** Whether touch events for the annotation's layer are recognized. Defaults to `YES`. */
@property (nonatomic, assign) BOOL enabled;
/** Whether the annotation should be clustered when map view clustering is enabled. Defaults to `YES`. */
@property (nonatomic, assign) BOOL clusteringEnabled;
/** @name Representing an Annotation Visually */
/** An object representing the annotation's visual appearance.
... ... @@ -97,7 +94,17 @@
* @see RMCircle */
@property (nonatomic, strong) RMMapLayer *layer;
// This is for the QuadTree. Don't mess this up.
/** @name Annotation Clustering */
/** Whether the annotation should be clustered when map view clustering is enabled. Defaults to `YES`. */
@property (nonatomic, assign) BOOL clusteringEnabled;
/** Whether an annotation is an automatically-managed cluster annotation. */
@property (nonatomic, readonly, assign) BOOL isClusterAnnotation;
/** If the annotation is a cluster annotation, returns an array containing the annotations in the cluster. Returns `nil` if the annotation is not a cluster annotation. */
@property (nonatomic, readonly, assign) NSArray *clusteredAnnotations;
@property (nonatomic, weak) RMQuadTreeNode *quadTreeNode;
/** @name Filtering Types of Annotations */
... ... @@ -109,7 +116,7 @@
/** @name Initializing Annotations */
/** Create an initialize an annotation.
/** Create and initialize an annotation.
* @param aMapView The map view on which to place the annotation.
* @param aCoordinate The location for the annotation.
* @param aTitle The annotation's title.
... ...
... ... @@ -51,6 +51,8 @@
@synthesize enabled, clusteringEnabled;
@synthesize position;
@synthesize quadTreeNode;
@synthesize isClusterAnnotation=_isClusterAnnotation;
@synthesize clusteredAnnotations;
@synthesize isUserLocationAnnotation;
+ (id)annotationWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle
... ... @@ -172,6 +174,16 @@
return (layer != nil && [self isAnnotationOnScreen]);
}
- (void)setIsClusterAnnotation:(BOOL)isClusterAnnotation
{
_isClusterAnnotation = isClusterAnnotation;
}
- (NSArray *)clusteredAnnotations
{
return (self.isClusterAnnotation ? ((RMQuadTreeNode *)self.userInfo).clusteredAnnotations : nil);
}
- (void)setIsUserLocationAnnotation:(BOOL)flag
{
isUserLocationAnnotation = flag;
... ...
... ... @@ -27,6 +27,8 @@
#import "RMBingSource.h"
#import "RMConfiguration.h"
@implementation RMBingSource
{
NSString *_mapsKey;
... ... @@ -71,7 +73,7 @@
NSURL *metadataURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://dev.virtualearth.net/REST/v1/Imagery/Metadata/%@?key=%@", imagerySetString, _mapsKey]];
NSData *metadataData = [NSData dataWithContentsOfURL:metadataURL];
NSData *metadataData = [NSData brandedDataWithContentsOfURL:metadataURL];
id metadata = [NSJSONSerialization JSONObjectWithData:metadataData options:0 error:nil];
... ...
... ... @@ -65,7 +65,6 @@
fillColor = kDefaultFillColor;
scaleLineWidth = NO;
enableDragging = YES;
circlePath = NULL;
[self updateCirclePathAnimated:NO];
... ...
... ... @@ -27,12 +27,52 @@
#import <UIKit/UIKit.h>
/** The RMConfiguration object is a shared instance of the configuration for the library. */
@interface RMConfiguration : NSObject
/** @name Accessing the Configuration */
/** Access the shared instance of the configuration.
* @return The shared configuration instance. */
+ (RMConfiguration *)configuration;
- (RMConfiguration *)initWithPath:(NSString *)path;
/** Access the disk- and memory-based cache configuration.
* @return A dictionary containing the cache configuration. */
- (NSDictionary *)cacheConfiguration;
/** @name Changing and Accessing a Custom User Agent */
/** Access and change the global user agent for HTTP requests using the library.
*
* If unset, defaults to `MapBox iOS SDK` followed by generic hardware model and software version information.
*
* Example: `MyMapApp/1.2` */
@property (nonatomic, retain) NSString *userAgent;
@end
#pragma mark -
@interface NSURLConnection (RMUserAgent)
+ (NSData *)sendBrandedSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
@end
#pragma mark -
@interface NSData (RMUserAgent)
+ (NSData *)brandedDataWithContentsOfURL:(NSURL *)aURL;
@end
#pragma mark -
@interface NSString (RMUserAgent)
+ (id)brandedStringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error;
@end
... ...
... ... @@ -29,11 +29,54 @@
static RMConfiguration *RMConfigurationSharedInstance = nil;
@implementation NSURLConnection (RMUserAgent)
+ (NSData *)sendBrandedSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
{
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:request.URL cachePolicy:request.cachePolicy timeoutInterval:request.timeoutInterval];
[newRequest setValue:[[RMConfiguration configuration] userAgent] forHTTPHeaderField:@"User-Agent"];
return [NSURLConnection sendSynchronousRequest:newRequest returningResponse:response error:error];
}
@end
#pragma mark -
@implementation NSData (RMUserAgent)
+ (NSData *)brandedDataWithContentsOfURL:(NSURL *)aURL
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aURL];
[request setValue:[[RMConfiguration configuration] userAgent] forHTTPHeaderField:@"User-Agent"];
return [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
}
@end
#pragma mark -
@implementation NSString (RMUserAgent)
+ (id)brandedStringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error
{
return [[self class] stringWithContentsOfURL:url encoding:enc error:error];
}
@end
#pragma mark -
@implementation RMConfiguration
{
id _propertyList;
}
@synthesize userAgent=_userAgent;
+ (RMConfiguration *)configuration
{
static dispatch_once_t onceToken;
... ... @@ -49,6 +92,8 @@ static RMConfiguration *RMConfigurationSharedInstance = nil;
if (!(self = [super init]))
return nil;
_userAgent = [NSString stringWithFormat:@"MapBox iOS SDK (%@/%@)", [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion]];
if (path == nil)
{
_propertyList = nil;
... ...
... ... @@ -33,6 +33,8 @@
#import "RMInteractiveSource.h"
#import "RMConfiguration.h"
#import "FMDatabase.h"
#import "FMDatabaseQueue.h"
... ... @@ -542,7 +544,7 @@ RMTilePoint RMInteractiveSourceNormalizedTilePointForMapView(CGPoint point, RMMa
// get the data for this tile
//
NSData *gridData = [NSData dataWithContentsOfURL:[NSURL URLWithString:gridURLString]];
NSData *gridData = [NSData brandedDataWithContentsOfURL:[NSURL URLWithString:gridURLString]];
if (gridData)
{
... ...
... ... @@ -26,8 +26,8 @@
_contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width * 3, frame.size.height * 3)];
[self addSubview:_contentView];
[self setMapZooming:YES];
[self setMapZooming:NO];
self.userInteractionEnabled = NO;
self.showsHorizontalScrollIndicator = NO;
self.showsVerticalScrollIndicator = NO;
... ...
... ... @@ -39,6 +39,9 @@
#define kMapBoxDefaultLatLonBoundingBox ((RMSphericalTrapezium){ .northEast = { .latitude = 90, .longitude = 180 }, \
.southWest = { .latitude = -90, .longitude = -180 } })
#define kMapBoxPlaceholderNormalMapID @"examples.map-z2effxa8"
#define kMapBoxPlaceholderRetinaMapID @"examples.map-zswgei2n"
// constants for the image quality API (see http://mapbox.com/developers/api/#image_quality)
typedef enum : NSUInteger {
RMMapBoxSourceQualityFull = 0, // default
... ...
... ... @@ -35,9 +35,7 @@
#import "RMMapView.h"
#import "RMPointAnnotation.h"
#define kMapBoxNormalMapID @"examples.map-z2effxa8"
#define kMapBoxRetinaMapID @"examples.map-zswgei2n"
#import "RMConfiguration.h"
@interface RMMapBoxSource ()
... ... @@ -54,7 +52,7 @@
- (id)init
{
return [self initWithMapID:([[UIScreen mainScreen] scale] > 1.0 ? kMapBoxRetinaMapID : kMapBoxNormalMapID)];
return [self initWithMapID:([[UIScreen mainScreen] scale] > 1.0 ? kMapBoxPlaceholderRetinaMapID : kMapBoxPlaceholderNormalMapID)];
}
- (id)initWithMapID:(NSString *)mapID
... ... @@ -91,7 +89,7 @@
NSMutableString *jsonString = nil;
if (dataURL && (jsonString = [NSMutableString stringWithContentsOfURL:dataURL encoding:NSUTF8StringEncoding error:nil]) && jsonString)
if (dataURL && (jsonString = [NSMutableString brandedStringWithContentsOfURL:dataURL encoding:NSUTF8StringEncoding error:nil]) && jsonString)
{
if ([jsonString hasPrefix:@"grid("])
{
... ... @@ -151,7 +149,7 @@
options:NSAnchoredSearch & NSBackwardsSearch
range:NSMakeRange(0, [[referenceURL absoluteString] length])]];
if ([[referenceURL pathExtension] isEqualToString:@"json"] && (dataObject = [NSString stringWithContentsOfURL:referenceURL encoding:NSUTF8StringEncoding error:nil]) && dataObject)
if ([[referenceURL pathExtension] isEqualToString:@"json"] && (dataObject = [NSString brandedStringWithContentsOfURL:referenceURL encoding:NSUTF8StringEncoding error:nil]) && dataObject)
return [self initWithTileJSON:dataObject enablingDataOnMapView:mapView];
return nil;
... ...
... ... @@ -40,7 +40,7 @@
// expressed in projected meters. The anchorPoint of the image/path/etc. is plotted here.
RMProjectedPoint projectedLocation;
BOOL enableDragging;
BOOL draggingEnabled;
// provided for storage of arbitrary user data
id userInfo;
... ... @@ -55,7 +55,7 @@
@property (nonatomic, assign) RMProjectedPoint projectedLocation;
/** When set to YES, the layer can be dragged by the user. */
@property (nonatomic, assign) BOOL enableDragging;
@property (nonatomic, assign) BOOL draggingEnabled;
/** Storage for arbitrary data. */
@property (nonatomic, strong) id userInfo;
... ... @@ -64,7 +64,9 @@
*
* If the value of this property is `YES`, a standard callout bubble is shown when the user taps the layer. The callout uses the title text from the associated annotation object. If there is no title text, though, the annotation is treated as if its enabled property is set to `NO`. The callout also displays any custom callout views stored in the leftCalloutAccessoryView and rightCalloutAccessoryView properties.
*
* 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. */
* 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.
*
* Note that callouts are not supported on cluster annotation layers. These annotations can be interacted with, but do not remain consistent visually during map pan and zoom events; thus, callout behavior would be inconsistent. */
@property (nonatomic, assign) BOOL canShowCallout;
/** The offset (in pixels) at which to place the callout bubble.
... ...
... ... @@ -27,14 +27,15 @@
#import "RMMapLayer.h"
#import "RMPixel.h"
#import "RMAnnotation.h"
@implementation RMMapLayer
@synthesize annotation;
@synthesize projectedLocation;
@synthesize enableDragging;
@synthesize draggingEnabled;
@synthesize userInfo;
@synthesize canShowCallout;
@synthesize canShowCallout=_canShowCallout;
@synthesize calloutOffset;
@synthesize leftCalloutAccessoryView;
@synthesize rightCalloutAccessoryView;
... ... @@ -45,7 +46,7 @@
return nil;
self.annotation = nil;
self.enableDragging = NO;
self.draggingEnabled = NO;
self.calloutOffset = CGPointZero;
return self;
... ... @@ -63,6 +64,12 @@
return self;
}
- (void)setCanShowCallout:(BOOL)canShowCallout
{
if ( ! self.annotation.isClusterAnnotation)
_canShowCallout = canShowCallout;
}
- (void)setPosition:(CGPoint)position animated:(BOOL)animated
{
[self setPosition:position];
... ...
... ... @@ -49,13 +49,6 @@
@class RMQuadTree;
@class RMUserLocation;
// constants for boundingMask
enum : NSUInteger {
RMMapNoMinBound = 0, // Map can be zoomed out past view limits
RMMapMinHeightBound = 1, // Minimum map height when zooming out restricted to view height
RMMapMinWidthBound = 2 // Minimum map width when zooming out restricted to view width (default)
};
// constants for the scrollview deceleration mode
typedef enum : NSUInteger {
RMMapDecelerationNormal = 0,
... ... @@ -86,14 +79,14 @@ typedef enum : NSUInteger {
* This property controls only user interactions with the map. If you set the value of this property to `NO`, you may still change the map location programmatically.
*
* The default value of this property is `YES`. */
@property (nonatomic, assign) BOOL enableDragging;
@property (nonatomic, assign) BOOL draggingEnabled;
/** A Boolean value that determines whether the map view bounces past the edge of content and back again and whether it animates the content scaling when the scaling exceeds the maximum or minimum limits.
*
* If the value of this property is `YES`, the map view bounces when it encounters a boundary of the content or when zooming exceeds either the maximum or minimum limits for scaling. Bouncing visually indicates that scrolling or zooming has reached an edge of the content. If the value is `NO`, scrolling and zooming stop immediately at the content boundary without bouncing.
*
* The default value is `NO`. */
@property (nonatomic, assign) BOOL enableBouncing;
@property (nonatomic, assign) BOOL bouncingEnabled;
/** A Boolean value that determines whether double-tap zooms of the map always zoom on the center of the map, or whether they zoom on the center of the double-tap gesture. The default value is `NO`, which zooms on the gesture. */
@property (nonatomic, assign) BOOL zoomingInPivotsAroundCenter;
... ... @@ -129,8 +122,6 @@ typedef enum : NSUInteger {
/** Take missing tiles from lower-numbered zoom levels, up to a given number of zoom levels. This can be used in order to increase perceived tile load performance or to allow zooming in beyond levels supported natively by a given tile source. Defaults to 1. */
@property (nonatomic, assign) NSUInteger missingTilesDepth;
@property (nonatomic, assign) NSUInteger boundingMask;
/** A custom, static view to use behind the map tiles. The default behavior is to use grid imagery that moves with map panning like MapKit. */
@property (nonatomic, strong) UIView *backgroundView;
... ... @@ -352,9 +343,9 @@ typedef enum : NSUInteger {
/** @name Configuring Annotation Clustering */
/** Whether to enable clustering of map point annotations. Defaults to `NO`. */
@property (nonatomic, assign) BOOL enableClustering;
@property (nonatomic, assign) BOOL clusteringEnabled;
/** 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 `NO`. */
/** 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`. */
... ...
... ... @@ -77,14 +77,14 @@
- (void)createMapView;
- (void)registerMoveEventByUser:(BOOL)wasUserEvent;
- (void)completeMoveEventAfterDelay:(NSTimeInterval)delay;
- (void)registerZoomEventByUser:(BOOL)wasUserEvent;
- (void)completeZoomEventAfterDelay:(NSTimeInterval)delay;
- (void)correctPositionOfAllAnnotations;
- (void)correctPositionOfAllAnnotationsIncludingInvisibles:(BOOL)correctAllLayers animated:(BOOL)animated;
- (void)correctOrderingOfAllAnnotations;
- (void)correctMinZoomScaleForBoundingMask;
- (void)updateHeadingForDeviceOrientation;
@end
... ... @@ -163,7 +163,7 @@
CGSize _lastContentSize;
BOOL _mapScrollViewIsZooming;
BOOL _enableDragging, _enableBouncing;
BOOL _draggingEnabled, _bouncingEnabled;
CGPoint _lastDraggingTranslation;
RMAnnotation *_draggedAnnotation;
... ... @@ -190,17 +190,18 @@
RMAnnotation *_currentAnnotation;
SMCalloutView *_currentCallout;
BOOL _rotateAtMinZoom;
}
@synthesize decelerationMode = _decelerationMode;
@synthesize boundingMask = _boundingMask;
@synthesize zoomingInPivotsAroundCenter = _zoomingInPivotsAroundCenter;
@synthesize minZoom = _minZoom, maxZoom = _maxZoom;
@synthesize screenScale = _screenScale;
@synthesize tileCache = _tileCache;
@synthesize quadTree = _quadTree;
@synthesize enableClustering = _enableClustering;
@synthesize clusteringEnabled = _clusteringEnabled;
@synthesize positionClusterMarkersAtTheGravityCenter = _positionClusterMarkersAtTheGravityCenter;
@synthesize orderClusterMarkersAboveOthers = _orderClusterMarkersAboveOthers;
@synthesize clusterMarkerSize = _clusterMarkerSize, clusterAreaSize = _clusterAreaSize;
... ... @@ -224,8 +225,8 @@
minZoomLevel:(float)initialTileSourceMinZoomLevel
backgroundImage:(UIImage *)backgroundImage
{
_constrainMovement = _enableBouncing = _zoomingInPivotsAroundCenter = NO;
_enableDragging = YES;
_constrainMovement = _bouncingEnabled = _zoomingInPivotsAroundCenter = NO;
_draggingEnabled = YES;
_lastDraggingTranslation = CGPointZero;
_draggedAnnotation = nil;
... ... @@ -244,7 +245,6 @@
_screenScale = [UIScreen mainScreen].scale;
_boundingMask = RMMapMinWidthBound;
_adjustTilesForRetinaDisplay = NO;
_missingTilesDepth = 1;
_debugTiles = NO;
... ... @@ -252,7 +252,8 @@
_annotations = [NSMutableSet new];
_visibleAnnotations = [NSMutableSet new];
[self setQuadTree:[[RMQuadTree alloc] initWithMapView:self]];
_enableClustering = _positionClusterMarkersAtTheGravityCenter = NO;
_clusteringEnabled = NO;
_positionClusterMarkersAtTheGravityCenter = YES;
_clusterMarkerSize = CGSizeMake(100.0, 100.0);
_clusterAreaSize = CGSizeMake(150.0, 150.0);
... ... @@ -285,7 +286,6 @@
[self setCenterCoordinate:initialCenterCoordinate animated:NO];
[self setDecelerationMode:RMMapDecelerationFast];
[self setBoundingMask:RMMapMinHeightBound];
self.showLogoBug = YES;
... ... @@ -390,7 +390,11 @@
[self setCenterProjectedPoint:centerPoint animated:NO];
[self correctPositionOfAllAnnotations];
[self correctMinZoomScaleForBoundingMask];
self.minZoom = 0; // force new minZoom calculation
if (_loadingTileView)
_loadingTileView.mapZooming = NO;
}
}
... ... @@ -439,10 +443,17 @@
//
if (self.userTrackingMode == RMUserTrackingModeFollowWithHeading)
[self locationManager:_locationManager didUpdateHeading:_locationManager.heading];
// fix UIScrollView artifacts from rotation at minZoomScale
//
_rotateAtMinZoom = fabs(self.zoom - self.minZoom) < 0.1;
}
- (void)handleDidChangeOrientationNotification:(NSNotification *)notification
{
if (_rotateAtMinZoom)
[_mapScrollView setZoomScale:_mapScrollView.minimumZoomScale animated:YES];
[self updateHeadingForDeviceOrientation];
}
... ... @@ -567,6 +578,11 @@
}
}
- (void)completeMoveEventAfterDelay:(NSTimeInterval)delay
{
[_moveDelegateQueue performSelector:@selector(setSuspended:) withObject:[NSNumber numberWithBool:NO] afterDelay:delay];
}
- (void)registerZoomEventByUser:(BOOL)wasUserEvent
{
@synchronized (_zoomDelegateQueue)
... ... @@ -598,6 +614,11 @@
}
}
- (void)completeZoomEventAfterDelay:(NSTimeInterval)delay
{
[_zoomDelegateQueue performSelector:@selector(setSuspended:) withObject:[NSNumber numberWithBool:NO] afterDelay:delay];
}
#pragma mark -
#pragma mark Bounds
... ... @@ -774,7 +795,7 @@
// RMLog(@"setMapCenterProjectedPoint: {%f,%f} -> {%.0f,%.0f}", centerProjectedPoint.x, centerProjectedPoint.y, mapScrollView.contentOffset.x, mapScrollView.contentOffset.y);
if ( ! animated)
[_moveDelegateQueue setSuspended:NO];
[self completeMoveEventAfterDelay:0];
[self correctPositionOfAllAnnotations];
}
... ... @@ -790,37 +811,12 @@
contentOffset.y += delta.height;
_mapScrollView.contentOffset = contentOffset;
[_moveDelegateQueue setSuspended:NO];
[self completeMoveEventAfterDelay:0];
}
#pragma mark -
#pragma mark Zoom
- (void)setBoundingMask:(NSUInteger)mask
{
_boundingMask = mask;
[self correctMinZoomScaleForBoundingMask];
}
- (void)correctMinZoomScaleForBoundingMask
{
if (self.boundingMask != RMMapNoMinBound)
{
if ([_tiledLayersSuperview.subviews count] == 0)
return;
CGFloat newMinZoomScale = (self.boundingMask == RMMapMinWidthBound ? self.bounds.size.width : self.bounds.size.height) / ((CATiledLayer *)((RMMapTiledLayerView *)[_tiledLayersSuperview.subviews objectAtIndex:0]).layer).tileSize.width;
if (_mapScrollView.minimumZoomScale > 0 && newMinZoomScale > _mapScrollView.minimumZoomScale)
{
RMLog(@"clamping min zoom of %f to %f due to %@", log2f(_mapScrollView.minimumZoomScale), log2f(newMinZoomScale), (self.boundingMask == RMMapMinWidthBound ? @"RMMapMinWidthBound" : @"RMMapMinHeightBound"));
_mapScrollView.minimumZoomScale = newMinZoomScale;
}
}
}
- (RMProjectedRect)projectedBounds
{
CGPoint bottomLeft = CGPointMake(_mapScrollView.contentOffset.x, _mapScrollView.contentSize.height - (_mapScrollView.contentOffset.y + _mapScrollView.bounds.size.height));
... ... @@ -858,48 +854,6 @@
[_mapScrollView zoomToRect:zoomRect animated:animated];
}
- (float)adjustedZoomForCurrentBoundingMask:(float)zoomFactor
{
if (_boundingMask == RMMapNoMinBound)
return zoomFactor;
double newMetersPerPixel = _metersPerPixel / zoomFactor;
RMProjectedRect mercatorBounds = [_projection planetBounds];
// Check for MinWidthBound
if (_boundingMask & RMMapMinWidthBound)
{
double newMapContentsWidth = mercatorBounds.size.width / newMetersPerPixel;
double screenBoundsWidth = [self bounds].size.width;
double mapContentWidth;
if (newMapContentsWidth < screenBoundsWidth)
{
// Calculate new zoom facter so that it does not shrink the map any further.
mapContentWidth = mercatorBounds.size.width / _metersPerPixel;
zoomFactor = screenBoundsWidth / mapContentWidth;
}
}
// Check for MinHeightBound
if (_boundingMask & RMMapMinHeightBound)
{
double newMapContentsHeight = mercatorBounds.size.height / newMetersPerPixel;
double screenBoundsHeight = [self bounds].size.height;
double mapContentHeight;
if (newMapContentsHeight < screenBoundsHeight)
{
// Calculate new zoom facter so that it does not shrink the map any further.
mapContentHeight = mercatorBounds.size.height / _metersPerPixel;
zoomFactor = screenBoundsHeight / mapContentHeight;
}
}
return zoomFactor;
}
- (BOOL)shouldZoomToTargetZoom:(float)targetZoom withZoomFactor:(float)zoomFactor
{
// bools for syntactical sugar to understand the logic in the if statement below
... ... @@ -941,7 +895,6 @@
if (![self tileSourceBoundsContainScreenPoint:pivot])
return;
zoomFactor = [self adjustedZoomForCurrentBoundingMask:zoomFactor];
float zoomDelta = log2f(zoomFactor);
float targetZoom = zoomDelta + [self zoom];
... ... @@ -1154,9 +1107,9 @@
_mapScrollView.showsVerticalScrollIndicator = NO;
_mapScrollView.showsHorizontalScrollIndicator = NO;
_mapScrollView.scrollsToTop = NO;
_mapScrollView.scrollEnabled = _enableDragging;
_mapScrollView.bounces = _enableBouncing;
_mapScrollView.bouncesZoom = _enableBouncing;
_mapScrollView.scrollEnabled = _draggingEnabled;
_mapScrollView.bounces = _bouncingEnabled;
_mapScrollView.bouncesZoom = _bouncingEnabled;
_mapScrollView.contentSize = contentSize;
_mapScrollView.minimumZoomScale = exp2f([self minZoom]);
_mapScrollView.maximumZoomScale = exp2f([self maxZoom]);
... ... @@ -1258,7 +1211,7 @@
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if ( ! decelerate)
[_moveDelegateQueue setSuspended:NO];
[self completeMoveEventAfterDelay:0];
}
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
... ... @@ -1269,12 +1222,12 @@
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[_moveDelegateQueue setSuspended:NO];
[self completeMoveEventAfterDelay:0];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[_moveDelegateQueue setSuspended:NO];
[self completeMoveEventAfterDelay:0];
}
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
... ... @@ -1289,11 +1242,17 @@
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
[_moveDelegateQueue setSuspended:NO];
[_zoomDelegateQueue setSuspended:NO];
[self completeMoveEventAfterDelay:0];
[self completeZoomEventAfterDelay:0];
_mapScrollViewIsZooming = NO;
// slight jiggle fixes problems with UIScrollView
// briefly allowing zoom beyond min
//
[self moveBy:CGSizeMake(-1, -1)];
[self moveBy:CGSizeMake( 1, 1)];
[self correctPositionOfAllAnnotations];
if (_loadingTileView)
... ... @@ -1540,21 +1499,24 @@
- (void)doubleTapAtPoint:(CGPoint)aPoint
{
[self registerZoomEventByUser:YES];
if (self.zoomingInPivotsAroundCenter)
{
[self zoomInToNextNativeZoomAt:[self convertPoint:self.center fromView:self.superview] animated:YES];
}
else if (self.userTrackingMode != RMUserTrackingModeNone && fabsf(aPoint.x - [self coordinateToPixel:self.userLocation.location.coordinate].x) < 75 && fabsf(aPoint.y - [self coordinateToPixel:self.userLocation.location.coordinate].y) < 75)
if (self.zoom < self.maxZoom)
{
[self zoomInToNextNativeZoomAt:[self coordinateToPixel:self.userLocation.location.coordinate] animated:YES];
}
else
{
[self registerMoveEventByUser:YES];
[self registerZoomEventByUser:YES];
if (self.zoomingInPivotsAroundCenter)
{
[self zoomInToNextNativeZoomAt:[self convertPoint:self.center fromView:self.superview] animated:YES];
}
else if (self.userTrackingMode != RMUserTrackingModeNone && fabsf(aPoint.x - [self coordinateToPixel:self.userLocation.location.coordinate].x) < 75 && fabsf(aPoint.y - [self coordinateToPixel:self.userLocation.location.coordinate].y) < 75)
{
[self zoomInToNextNativeZoomAt:[self coordinateToPixel:self.userLocation.location.coordinate] animated:YES];
}
else
{
[self registerMoveEventByUser:YES];
[self zoomInToNextNativeZoomAt:aPoint animated:YES];
[self zoomInToNextNativeZoomAt:aPoint animated:YES];
}
}
if (_delegateHasDoubleTapOnMap)
... ... @@ -1594,14 +1556,17 @@
- (void)handleTwoFingerSingleTap:(UIGestureRecognizer *)recognizer
{
[self registerZoomEventByUser:YES];
if (self.zoom > self.minZoom)
{
[self registerZoomEventByUser:YES];
CGPoint centerPoint = [self convertPoint:self.center fromView:self.superview];
CGPoint centerPoint = [self convertPoint:self.center fromView:self.superview];
if (self.userTrackingMode != RMUserTrackingModeNone)
centerPoint = [self coordinateToPixel:self.userLocation.location.coordinate];
if (self.userTrackingMode != RMUserTrackingModeNone)
centerPoint = [self coordinateToPixel:self.userLocation.location.coordinate];
[self zoomOutToNextNativeZoomAt:centerPoint animated:YES];
[self zoomOutToNextNativeZoomAt:centerPoint animated:YES];
}
if (_delegateHasSingleTapTwoFingersOnMap)
[_delegate singleTapTwoFingersOnMap:self at:[recognizer locationInView:self]];
... ... @@ -1638,7 +1603,7 @@
if ([hit isEqual:_overlayView.layer])
return NO;
if (!hit || ([hit respondsToSelector:@selector(enableDragging)] && ![(RMMarker *)hit enableDragging]))
if (!hit || ([hit respondsToSelector:@selector(draggingEnabled)] && ![(RMMarker *)hit draggingEnabled]))
return NO;
if ( ! [self shouldDragAnnotation:[self findAnnotationInLayer:hit]])
... ... @@ -1665,7 +1630,7 @@
if ( ! hit)
return;
if ([hit respondsToSelector:@selector(enableDragging)] && ![(RMMarker *)hit enableDragging])
if ([hit respondsToSelector:@selector(draggingEnabled)] && ![(RMMarker *)hit draggingEnabled])
return;
_lastDraggingTranslation = CGPointZero;
... ... @@ -1818,6 +1783,8 @@
[_mapScrollView setContentOffset:contentOffset animated:YES];
[self completeMoveEventAfterDelay:kSMCalloutViewRepositionDelayForUIScrollView];
return kSMCalloutViewRepositionDelayForUIScrollView;
}
... ... @@ -2224,16 +2191,18 @@
- (void)setMinZoom:(float)newMinZoom
{
if (newMinZoom < 0.0)
newMinZoom = 0.0;
float boundingDimension = fmaxf(self.bounds.size.width, self.bounds.size.height);
float tileSideLength = _tileSourcesContainer.tileSideLength;
float clampedMinZoom = log2(boundingDimension / tileSideLength);
if (newMinZoom < clampedMinZoom)
newMinZoom = clampedMinZoom;
_minZoom = newMinZoom;
// RMLog(@"New minZoom:%f", newMinZoom);
_mapScrollView.minimumZoomScale = exp2f(newMinZoom);
[self correctMinZoomScaleForBoundingMask];
}
- (float)tileSourcesMinZoom
... ... @@ -2295,7 +2264,7 @@
_mapScrollView.zoomScale = exp2f(_zoom);
[_zoomDelegateQueue setSuspended:NO];
[self completeZoomEventAfterDelay:0];
}
- (float)tileSourcesZoom
... ... @@ -2318,9 +2287,9 @@
[self setZoom:tileSourcesZoom];
}
- (void)setEnableClustering:(BOOL)doEnableClustering
- (void)setClusteringEnabled:(BOOL)doEnableClustering
{
_enableClustering = doEnableClustering;
_clusteringEnabled = doEnableClustering;
[self correctPositionOfAllAnnotations];
}
... ... @@ -2339,25 +2308,25 @@
[_mapScrollView setDecelerationRate:decelerationRate];
}
- (BOOL)enableDragging
- (BOOL)draggingEnabled
{
return _enableDragging;
return _draggingEnabled;
}
- (void)setEnableDragging:(BOOL)enableDragging
- (void)setDraggingEnabled:(BOOL)enableDragging
{
_enableDragging = enableDragging;
_draggingEnabled = enableDragging;
_mapScrollView.scrollEnabled = enableDragging;
}
- (BOOL)enableBouncing
- (BOOL)bouncingEnabled
{
return _enableBouncing;
return _bouncingEnabled;
}
- (void)setEnableBouncing:(BOOL)enableBouncing
- (void)setBouncingEnabled:(BOOL)enableBouncing
{
_enableBouncing = enableBouncing;
_bouncingEnabled = enableBouncing;
_mapScrollView.bounces = enableBouncing;
_mapScrollView.bouncesZoom = enableBouncing;
}
... ... @@ -2666,7 +2635,7 @@
boundingBox.size.height += (2.0 * boundingBoxBuffer);
NSArray *annotationsToCorrect = [self.quadTree annotationsInProjectedRect:boundingBox
createClusterAnnotations:self.enableClustering
createClusterAnnotations:self.clusteringEnabled
withProjectedClusterSize:RMProjectedSizeMake(self.clusterAreaSize.width * _metersPerPixel, self.clusterAreaSize.height * _metersPerPixel)
andProjectedClusterMarkerSize:RMProjectedSizeMake(self.clusterMarkerSize.width * _metersPerPixel, self.clusterMarkerSize.height * _metersPerPixel)
findGravityCenter:self.positionClusterMarkersAtTheGravityCenter];
... ... @@ -2802,10 +2771,10 @@
// clusters above/below non-clusters (based on _orderClusterMarkersAboveOthers)
//
if ( [annotation1.annotationType isEqualToString:kRMClusterAnnotationTypeName] && ! [annotation2.annotationType isEqualToString:kRMClusterAnnotationTypeName])
if ( annotation1.isClusterAnnotation && ! annotation2.isClusterAnnotation)
return (_orderClusterMarkersAboveOthers ? NSOrderedDescending : NSOrderedAscending);
if ( ! [annotation1.annotationType isEqualToString:kRMClusterAnnotationTypeName] && [annotation2.annotationType isEqualToString:kRMClusterAnnotationTypeName])
if ( ! annotation1.isClusterAnnotation && annotation2.isClusterAnnotation)
return (_orderClusterMarkersAboveOthers ? NSOrderedAscending : NSOrderedDescending);
// markers above shapes
... ... @@ -2860,7 +2829,7 @@
[self.quadTree addAnnotation:annotation];
}
if (_enableClustering)
if (_clusteringEnabled)
{
[self correctPositionOfAllAnnotations];
}
... ... @@ -3121,7 +3090,7 @@
[self insertSubview:_userHaloTrackingView belowSubview:_overlayView];
_userHeadingTrackingView = [[UIImageView alloc] initWithImage:[RMMapView resourceImageNamed:@"HeadingAngleSmall.png"]];
_userHeadingTrackingView = [[UIImageView alloc] initWithImage:[RMMapView resourceImageNamed:@"HeadingAngleLarge.png"]];
_userHeadingTrackingView.frame = CGRectMake((self.bounds.size.width / 2) - (_userHeadingTrackingView.bounds.size.width / 2),
(self.bounds.size.height / 2) - _userHeadingTrackingView.bounds.size.height,
... ... @@ -3248,6 +3217,30 @@
[self addAnnotation:_accuracyCircleAnnotation];
}
if ( ! oldLocation)
{
// make accuracy circle bounce until we get our second update
//
[CATransaction begin];
[CATransaction setAnimationDuration:0.75];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
CABasicAnimation *bounceAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
bounceAnimation.repeatCount = MAXFLOAT;
bounceAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)];
bounceAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.8, 0.8, 1.0)];
bounceAnimation.removedOnCompletion = NO;
bounceAnimation.autoreverses = YES;
[_accuracyCircleAnnotation.layer addAnimation:bounceAnimation forKey:@"animateScale"];
[CATransaction commit];
}
else
{
[_accuracyCircleAnnotation.layer removeAnimationForKey:@"animateScale"];
}
if ([newLocation distanceFromLocation:oldLocation])
_accuracyCircleAnnotation.coordinate = newLocation.coordinate;
... ... @@ -3278,7 +3271,6 @@
boundsAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
boundsAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2.0, 2.0, 1.0)];
boundsAnimation.removedOnCompletion = NO;
boundsAnimation.fillMode = kCAFillModeForwards;
[_trackingHaloAnnotation.layer addAnimation:boundsAnimation forKey:@"animateScale"];
... ... @@ -3289,7 +3281,6 @@
opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnimation.toValue = [NSNumber numberWithFloat:-1.0];
opacityAnimation.removedOnCompletion = NO;
opacityAnimation.fillMode = kCAFillModeForwards;
[_trackingHaloAnnotation.layer addAnimation:opacityAnimation forKey:@"animateOpacity"];
... ... @@ -3338,6 +3329,13 @@
if ( ! _showsUserLocation || _mapScrollView.isDragging || newHeading.headingAccuracy < 0)
return;
if (newHeading.headingAccuracy > 40)
_userHeadingTrackingView.image = [RMMapView resourceImageNamed:@"HeadingAngleLarge.png"];
else if (newHeading.headingAccuracy >= 25 && newHeading.headingAccuracy <= 40)
_userHeadingTrackingView.image = [RMMapView resourceImageNamed:@"HeadingAngleMedium.png"];
else
_userHeadingTrackingView.image = [RMMapView resourceImageNamed:@"HeadingAngleSmall.png"];
self.userLocation.heading = newHeading;
if (_delegateHasDidUpdateUserLocation)
... ...
... ... @@ -26,7 +26,9 @@
// POSSIBILITY OF SUCH DAMAGE.
#import "RMMarker.h"
#import "RMPixel.h"
#import "RMConfiguration.h"
@implementation RMMarker
... ... @@ -147,7 +149,7 @@
if ((image = [UIImage imageWithData:[NSData dataWithContentsOfFile:cachePath] scale:(useRetina ? 2.0 : 1.0)]) && image)
return [self initWithUIImage:image];
[[NSFileManager defaultManager] createFileAtPath:cachePath contents:[NSData dataWithContentsOfURL:imageURL] attributes:nil];
[[NSFileManager defaultManager] createFileAtPath:cachePath contents:[NSData brandedDataWithContentsOfURL:imageURL] attributes:nil];
return [self initWithUIImage:[UIImage imageWithData:[NSData dataWithContentsOfFile:cachePath] scale:(useRetina ? 2.0 : 1.0)]];
}
... ...
... ... @@ -35,8 +35,6 @@ typedef enum : short {
nodeTypeNode
} RMQuadTreeNodeType;
#define kRMClusterAnnotationTypeName @"RMClusterAnnotation"
#pragma mark - RMQuadTree nodes
@interface RMQuadTreeNode : NSObject
... ...
... ... @@ -38,6 +38,12 @@
#define kMaxAnnotationsPerLeaf 4
#define kMinPixelDistanceForLeafClustering 100.0
@interface RMAnnotation (RMQuadTree)
@property (nonatomic, assign) BOOL isClusterAnnotation;
@end
@interface RMQuadTreeNode ()
- (id)initWithMapView:(RMMapView *)aMapView forParent:(RMQuadTreeNode *)aParentNode inBoundingBox:(RMProjectedRect)aBoundingBox;
... ... @@ -514,7 +520,7 @@
_cachedClusterAnnotation = [[RMAnnotation alloc] initWithMapView:_mapView
coordinate:clusterMarkerCoordinate
andTitle:[NSString stringWithFormat:@"%d", enclosedAnnotationsCount]];
_cachedClusterAnnotation.annotationType = kRMClusterAnnotationTypeName;
_cachedClusterAnnotation.isClusterAnnotation = YES;
_cachedClusterAnnotation.userInfo = self;
_cachedClusterEnclosedAnnotations = [[NSArray alloc] initWithArray:enclosedAnnotations];
... ...
... ... @@ -31,19 +31,35 @@
#import "RMMapBoxSource.h"
#import "RMMarker.h"
#define kMapBoxDefaultCenter CLLocationCoordinate2DMake(MAXFLOAT, MAXFLOAT)
#define kMapBoxDefaultZoom -1.0f
@interface RMStaticMapView ()
- (void)performInitializationWithMapID:(NSString *)mapID centerCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(CGFloat)zoomLevel completionHandler:(void (^)(UIImage *))handler;
@end
#pragma mark -
@implementation RMStaticMapView
{
__weak RMStaticMapView *_weakSelf;
}
- (id)initWithFrame:(CGRect)frame
{
return [self initWithFrame:frame mapID:nil];
}
- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID
{
return [self initWithFrame:frame mapID:mapID centerCoordinate:CLLocationCoordinate2DMake(MAXFLOAT, MAXFLOAT) zoomLevel:-1 completionHandler:nil];
return [self initWithFrame:frame mapID:mapID centerCoordinate:kMapBoxDefaultCenter zoomLevel:kMapBoxDefaultZoom completionHandler:nil];
}
- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID completionHandler:(void (^)(UIImage *))handler
{
return [self initWithFrame:frame mapID:mapID centerCoordinate:CLLocationCoordinate2DMake(MAXFLOAT, MAXFLOAT) zoomLevel:-1 completionHandler:handler];
return [self initWithFrame:frame mapID:mapID centerCoordinate:kMapBoxDefaultCenter zoomLevel:kMapBoxDefaultZoom completionHandler:handler];
}
- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID centerCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(CGFloat)zoomLevel
... ... @@ -56,6 +72,25 @@
if (!(self = [super initWithFrame:frame]))
return nil;
[self performInitializationWithMapID:mapID centerCoordinate:centerCoordinate zoomLevel:zoomLevel completionHandler:handler];
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (!(self = [super initWithCoder:aDecoder]))
return nil;
[self performInitializationWithMapID:nil centerCoordinate:kMapBoxDefaultCenter zoomLevel:kMapBoxDefaultZoom completionHandler:nil];
return self;
}
- (void)performInitializationWithMapID:(NSString *)mapID centerCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(CGFloat)zoomLevel completionHandler:(void (^)(UIImage *))handler
{
mapID = (mapID ? mapID : (([[UIScreen mainScreen] scale] > 1.0 ? kMapBoxPlaceholderRetinaMapID : kMapBoxPlaceholderNormalMapID)));
RMMapBoxSource *tileSource = [[RMMapBoxSource alloc] initWithMapID:mapID enablingDataOnMapView:self];
self.tileSource = tileSource;
... ... @@ -92,9 +127,6 @@
});
});
}
return self;
}
- (void)addAnnotation:(RMAnnotation *)annotation
... ...
... ... @@ -130,6 +130,10 @@
DD932BBE165C287000D69D49 /* TrackingHeading@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BB0165C287000D69D49 /* TrackingHeading@2x.png */; };
DD932BBF165C287000D69D49 /* TrackingLocation.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BB1165C287000D69D49 /* TrackingLocation.png */; };
DD932BC0165C287000D69D49 /* TrackingLocation@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BB2165C287000D69D49 /* TrackingLocation@2x.png */; };
DD94D46A16C2E064003D5739 /* HeadingAngleLarge.png in Resources */ = {isa = PBXBuildFile; fileRef = DD94D46616C2E064003D5739 /* HeadingAngleLarge.png */; };
DD94D46B16C2E064003D5739 /* HeadingAngleLarge@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD94D46716C2E064003D5739 /* HeadingAngleLarge@2x.png */; };
DD94D46C16C2E064003D5739 /* HeadingAngleMedium.png in Resources */ = {isa = PBXBuildFile; fileRef = DD94D46816C2E064003D5739 /* HeadingAngleMedium.png */; };
DD94D46D16C2E064003D5739 /* HeadingAngleMedium@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD94D46916C2E064003D5739 /* HeadingAngleMedium@2x.png */; };
DD97C11616489678007C4652 /* libProj4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DD97C11516489678007C4652 /* libProj4.a */; };
DD98B6FA14D76B930092882F /* RMMapBoxSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD98B6F814D76B930092882F /* RMMapBoxSource.h */; };
DD98B6FB14D76B930092882F /* RMMapBoxSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD98B6F914D76B930092882F /* RMMapBoxSource.m */; };
... ... @@ -287,6 +291,10 @@
DD932BB0165C287000D69D49 /* TrackingHeading@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingHeading@2x.png"; path = "Map/Resources/TrackingHeading@2x.png"; sourceTree = "<group>"; };
DD932BB1165C287000D69D49 /* TrackingLocation.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingLocation.png; path = Map/Resources/TrackingLocation.png; sourceTree = "<group>"; };
DD932BB2165C287000D69D49 /* TrackingLocation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocation@2x.png"; path = "Map/Resources/TrackingLocation@2x.png"; sourceTree = "<group>"; };
DD94D46616C2E064003D5739 /* HeadingAngleLarge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleLarge.png; path = Map/Resources/HeadingAngleLarge.png; sourceTree = "<group>"; };
DD94D46716C2E064003D5739 /* HeadingAngleLarge@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleLarge@2x.png"; path = "Map/Resources/HeadingAngleLarge@2x.png"; sourceTree = "<group>"; };
DD94D46816C2E064003D5739 /* HeadingAngleMedium.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleMedium.png; path = Map/Resources/HeadingAngleMedium.png; sourceTree = "<group>"; };
DD94D46916C2E064003D5739 /* HeadingAngleMedium@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleMedium@2x.png"; path = "Map/Resources/HeadingAngleMedium@2x.png"; sourceTree = "<group>"; };
DD97C11516489678007C4652 /* libProj4.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libProj4.a; path = ../Proj4/libProj4.a; sourceTree = "<group>"; };
DD98B6F814D76B930092882F /* RMMapBoxSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMapBoxSource.h; sourceTree = "<group>"; };
DD98B6F914D76B930092882F /* RMMapBoxSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMapBoxSource.m; sourceTree = "<group>"; };
... ... @@ -591,6 +599,10 @@
DD932BA6165C287000D69D49 /* mapbox@2x.png */,
DD932BA9165C287000D69D49 /* HeadingAngleSmall.png */,
DD932BAA165C287000D69D49 /* HeadingAngleSmall@2x.png */,
DD94D46816C2E064003D5739 /* HeadingAngleMedium.png */,
DD94D46916C2E064003D5739 /* HeadingAngleMedium@2x.png */,
DD94D46616C2E064003D5739 /* HeadingAngleLarge.png */,
DD94D46716C2E064003D5739 /* HeadingAngleLarge@2x.png */,
DD932BAB165C287000D69D49 /* LoadingTile.png */,
DD932BAC165C287000D69D49 /* LoadingTileZoom.png */,
DD932BA7165C287000D69D49 /* TrackingDot.png */,
... ... @@ -800,6 +812,10 @@
DD932BBE165C287000D69D49 /* TrackingHeading@2x.png in Resources */,
DD932BBF165C287000D69D49 /* TrackingLocation.png in Resources */,
DD932BC0165C287000D69D49 /* TrackingLocation@2x.png in Resources */,
DD94D46A16C2E064003D5739 /* HeadingAngleLarge.png in Resources */,
DD94D46B16C2E064003D5739 /* HeadingAngleLarge@2x.png in Resources */,
DD94D46C16C2E064003D5739 /* HeadingAngleMedium.png in Resources */,
DD94D46D16C2E064003D5739 /* HeadingAngleMedium@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
... ...
... ... @@ -70,7 +70,7 @@ More documentation is available:
There are two subdirectories - MapView and Proj4. Proj4 is a support library used to do map projections. The MapView project contains only the Route-Me map library.
See License.txt for license details. In any app that uses this SDK, include the following text on your "preferences" or "about" screen: "Uses MapBox iOS SDK, (c) 2008-2012 MapBox and Route-Me Contributors". Your data provider will have additional attribution requirements.
See License.txt for license details. In any app that uses this SDK, include the following text on your "preferences" or "about" screen: "Uses MapBox iOS SDK, (c) 2008-2013 MapBox and Route-Me Contributors". Your data provider will have additional attribution requirements.
News, Support and Contributing
------------------------------
... ...