diff --git a/.gitignore b/.gitignore index 125fbebac..e5c2cc43f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ Icon? .Trashes # Project-specific ignores +Docs +CocoaPods +_site diff --git a/.gitmodules b/.gitmodules index 85935112a..ec02bc2c8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "MapView/Map/FMDB"] path = MapView/Map/FMDB url = https://github.com/ccgus/fmdb.git +[submodule "MapView/Map/GRMustache"] + path = MapView/Map/GRMustache + url = https://github.com/groue/GRMustache.git +[submodule "MapView/Map/SMCalloutView"] + path = MapView/Map/SMCalloutView + url = https://github.com/nfarina/calloutview.git diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..f93a71f00 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,274 @@ +Changelog +--------- + +### 1.6.1 +#### April 25, 2015 + + - Allow requirement for iOS 8 location services to be satisified both "always" and "when in use" modes. + - Fixed a bug when checking the types of tile sources that can be taken offline. + - Better developer warnings around when a Mapbox access token is required. + - Fixed a visual glitch with the user location dot. + - Improvements and fixes to CocoaPods installation method. + +### 1.6.0 +#### February 4, 2015 + + - Removed support for Mapbox `v3` API and require [access tokens](https://www.mapbox.com/developers/api/#access-tokens). + - Fixed a small bug with database caching which was also causing an error in the console log. + - Reduced console log verbosity. + - Deprecated the `-[RMMapboxSource init]` convenience initializer since tokens are now required. + - Updated the included GRMustache from 6.8.3 to 7.3.0. + - Documentation improvements. + +### 1.5.1 +#### January 28, 2015 + + - Deprecated `+[RMConfiguration configuration]` in favor of the Swift-friendly and better-looking `+[RMConfiguration sharedInstance]`. + - Fixed a bug in the docs removal script. + - Documentation improvements. + +### 1.5.0 +#### January 16, 2015 + + - Re-added support for Mapbox `v4` API and [access tokens](https://www.mapbox.com/developers/api/#access-tokens) (removed temporarily in `1.4.0`), which are required for new accounts. + - Added support for iOS 8's QoS on background network requests. + - Improved error handling. + - Improved localization support. + - Improved deprecation notification on some previously-removed API. + - A map view's `-setCenterCoordinate:` is no longer animated by default. + - Fixed an Auto Layout bug. + - Fixed some memory leaks. + - Performance improvements, especially to background downloading for offline use and to general disk caching. + - Clarified that only web-based tile sources are eligible for background downloading. + - Documentation improvements. + +### 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 + + - Added support for Mapbox `v4` API and [access tokens](https://www.mapbox.com/developers/api/#access-tokens) in tile and metadata requests. + - Now ensures that all Mapbox API requests are over HTTPS. + - Updated FMDB SQLite library under the hood for caching and MBTiles support. + - Updated some support for the forthcoming iOS 8. + - Fixed a crash that could occur when the map view delegate changed `showsUserLocation`. + - Fixes a minor bug with map view subview constraints during use of tab bar controllers. + - Fixed a minor memory leak with Grand Central Dispatch queues. + - Fixed a small deployment problem for iOS 5. + - Quieted some debug logging. + +### 1.2.0 +#### June 23, 2014 + + - Added an `RMGreatCircleAnnotation` class for geodesic polylines. + - Allow for additional touch gesture padding around thin `RMShape` layers. + - Added an `RMTileCache` method for retrieving anticipated raster tile background download counts for a given coverage area. + - Added some documentation to the now-supported `RMCompositeSource` for client-side raster tile compositing. + - Upgraded SMCalloutView with updated iOS 7+ support. + - No longer allow callouts on non-marker annotation layers. + - Minor fix to center coordinate/zoom level animation method. + - Use magnetic heading if true heading isn't accurate. + - Added a debug log when using the default watermarked map style. + - Updated some syntax to the newer boxed literals. + - Removed some compiler flags that would over-optimize and make debugging difficult. + - Made some improvements to the map view long-press gesture. + - Fixed an issue with certain tile sources having wrong tile image request methods called. + - Fixed some issues with the SQLite-backed tile cache not reclaiming freed disk space. + - Fixed some retain cycle memory use bugs. + - Fixed a bug when toggling the logo bug and attribution button. + - Fixed a crash when trying to add invalid annotations. + - Fixed a bug with `RMStaticMapView` always using the default map style. + +### 1.1.0 +#### January 2, 2014 + + - Updated for iOS 7, including visual appearance, tint color behavior, modal presentation paradigms, deprecations, and addition of a compass button when in tracking mode. + - 64-bit compliance. + - Requires Xcode 5.0+. + - Revamped annotation drag & drop system to work more like MapKit's. + - Improved autolayout support, including iOS 7 `UIViewController` layout guides. + - Support for [auto-retina mode](/developers/api/#Image.quality.&.scale) for Mapbox OpenStreetMap-based maps. + - Added `-[RMMapView setAlpha:forTileSource:]` and `-[RMMapView setAlpha:forTileSourceAtIndex:]`. + - Added `RMCircleAnnotation`. + - Added `-[RMMBTilesSource initWithTileSetResource:]` convenience method. + - Added `-[RMPointAnnotation image]`. + - Changed default `RMMarker` image from a pin with a star to a blank pin. + - Updated `RMCircle` default alpha from `1.0` to `0.25` and line width from `10.0` to `2.0`. + - Enhanced customizability for point, polyline, and polygon annotations. + - Improvements to `RMUserTrackingBarButtonItem` state animations. + - More accurate tile background loading grid for iOS 6+. + - Renamed instances of *MapBox* to *Mapbox* to better reflect branding. + - Fixed several crashes related to XIB unarchiving, invalid `frame` passing, and offline use. + - More efficient `RMPointAnnotation` redraws. + - Raise an exception when bad parameters are passed to background caching instead of failing silently. + - Background cache delegate methods are now truly optional as specified in the `RMTileCacheBackgroundDelegate` protocol. + - Updated [GRMustache](https://github.com/groue/GRMustache) from `v5.4.3` to `v6.8.3`. + - Updated usage of `instancetype` and `typedef enum`. + - Clarified documentation. + - Improved and updated CocoaPods specification. + - Fixed some build warnings. + - Minor bug fixes. + +### 1.0.3 +#### June 28, 2013 + + - Added support for the new SSL tile API. + - Improved disk caching API. + - Updated some API URLs to the latest preferred versions. + - Made some documentation improvements. + - Fixed a bug with MapBox markers that used custom colors. + - Fixed several small potental crash bugs. + +### 1.0.2 +#### March 29, 2013 + + - Added locally-bundled metadata for basic `RMMapBoxSource` use so that apps can better work offline from first launch, including when using XIBs and storyboards. + - Added a `fillPatternImage` property to `RMShape` and `RMCircle`. + - Fixed a bug related to updating annotation clusters after removal of single annotations. + - Fixed a bug related to comparisons of projected points on the map. + +### 1.0.1 +#### March 5, 2013 + + - Fixed a bug with `RMMapViewDelegate` callbacks for post-move and zoom events. + +### 1.0.0 +#### March 4, 2013 + + - Support for Automatic Reference Counting (ARC) for easier memory management. + - Added delegate callbacks for annotation selection & deselection notification. + - Improved documentation, especially for offline tile caching. + - Added a new [code examples gallery](../examples). + - Added a long press gesture recognizer for annotation layers. + - Added an API for setting an SDK-wide custom user-agent string for network requests. + - Added a convenience method for MBTiles tile sources to more easily find them in your app's bundle. + - Allow selection of a `nil` annotation in order to deselect the current annotation. + - Added an API for clearing MapBox marker local caching. + - Map views now default to a watermarked MapBox Streets map instead of OpenStreetMap. + - User location accuracy circle now bounces when first homing in on coordinate. + - Compass heading path now adjusts width based on heading accuracy reading. + - Annotation clustering API is now much simpler and easier to use. + - Privatized some header files to reduce clutter during Xcode autocompletion. + - Latest upstream improvements, including constraints, annotation z-ordering, and bounding box fixes. + - Code cleanups, consistency tweaks, and bug fixes. + +### 0.5.2 +#### January 3, 2013 + + - Added support for programmatic selection of annotations and display of callouts. + - Added support for annotation `calloutOffset` like MapKit. + - Fixed some bugs with callouts on circles and other shapes. + - Better shape hit detection based on current `fillRule`. + - Fixed a bug with shape clipping when map views were inset from the top of their superview. + - Fixed a few memory reuse problems. + - Allow silent re-add of already-added annotations. + +### 0.5.1 +#### December 12, 2012 + + - Added support for annotation callout subtitles. + - Fixed a bug related to touch events in `UIControl` objects on the map view. + - Fixed a bug with Bézier shape drawing on iOS 5. + - Fixed a crash when passing a `nil` static map completion handler. + - Added a CocoaPods `Podspec` directly to the repository for development use. + - Corrected annotation layer delegate request behavior when using simplestyle. + +### 0.5.0 +#### November 29, 2012 + + - Added a background tile downloader for pre-caching maps. + - Added some annotation convenience classes for simple use cases. + - Added annotation callouts that behave like MapKit. + - Support for MapBox map ID alongside TileJSON for easier map tile source use. + - Support for the MapBox image quality API to save bandwidth. + - Improved Interface Builder support for `RMMapView` and `RMUserTrackingBarButtonItem`. + - New `RMStaticMapView` class for creating `UIImageView`-like one-shot map images. + - New `RMTileMillSource` tile source for developing directly off of a TileMill instance. + - Methods for animated map zooming without changing map center as well as zoom/center changes in one step. + - Support for individual annotation touch enabling/disabling with the enabled property. + - Support for Bézier curves in shape layers. + - Improved tile cache API to allow greater flexibility with selective cache clearing. + - Easier attribution of map tile source data in the map view. + - MapKit-like support for a custom user location annotation layer. + - New `RMCompositeSource` tile source to enabling caching of client-side composited map tile end products. + - Unified `MapBox.h` header with commonly-used classes for all install methods. + - Updated GRMustache library for more up-to-date Mustache template functionality in UTFGrid interactivity. + - SDK resources such as images now install in a single `MapBox.bundle` file instead of individually. + - Removed the dependent build of the Proj4 projection library to greatly speed up compilation time. + - Improvements to asynchronous map tile render speed and reliability. + - Improved z-index sorting of cluster, point, and shape annotation layers. + - Cleaned and reorganized Xcode project groups for simplicity. + +### 0.4.3 +#### September 17, 2012 + + - Fixed a bug related to hiding & showing of the user location halo. + +### 0.4.2 +#### September 5, 2012 + + - Fixed a bug related to over-aggressive tile rendering for local tile sources. + +### 0.4.1 +#### August 27, 2012 + + - Fixed a bug related to app location services permission changes. + +### 0.4.0 +#### August 23, 2012 + + - First release in CocoaPods. + - First release of Xcode documentation. + - Improved the performance of network tile fetching and drawing. + - Added retina support for MapBox markers. + - Added the ability to reload individual composited tile sources. + - The map view background now behaves more like MapKit when loading tiles. + - Added a single, unified header file for easier project inclusion. + - The map view is no longer recreated on tile source reordering or hiding. + - Improvements to map rotation when tracking user compass heading and when rotating the application orientation. + - Annotations are now ordered in the third dimension according to relative screen position, including during map rotation. + - Improved the map view delegate protocol to indicate direct user actions that change the map. + - Reduced the amount of code necessary at map view initialization in order to behave more like MapKit. + - Added an option to disable compass heading calibration display. + - Map view delegate can now be set graphically in a XIB. + - Added the ability to interact with the user location annotation. + - Stability improvements when applications lose and regain location services permissions. + - Improved ability to debug UTFGrid interactivity in Xcode. + +### 0.3.0 +#### July 5, 2012 + + - First release of the prepackaged binary. + - Added support for MapBox markers. + - Improved the performance of vector paths and shapes when panning and zooming. + - Enhanced the performance and redrawing of multiple stacked tile layers. + - Other refactorings and improvements. + +### 0.2.0 +#### June 8, 2012 + + - Added user location services. + - Added configurable cache expiration handling. + - Enhancements for interactivity & composite sources. + - Xcode 4.3 compatibility. + - Minor bug fixes. + - Various upstream enhancements. + +### 0.1.0 +#### April 16, 2012 + + - Initial public release. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..5cee14b32 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,6 @@ +CONTRIBUTING +------------ + +**Please note that this legacy tree of the Mapbox iOS SDK is deprecated. As such, this project is not under active development. The `2.0.0` and above tree, based on code located at https://github.com/mapbox/mapbox-gl-native/, is a complete rewrite based on OpenGL ES and vector map rendering.** + +If you have a usage question, please email help-at-mapbox.com. diff --git a/LicenseRouteMe.txt b/License.txt similarity index 59% rename from LicenseRouteMe.txt rename to License.txt index e7eacc1c7..4091dba87 100644 --- a/LicenseRouteMe.txt +++ b/License.txt @@ -1,14 +1,30 @@ +Mapbox iOS SDK copyright (c) 2012-2013, 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. - diff --git a/MapView/DesktopMapView-Info.plist b/MapView/DesktopMapView-Info.plist deleted file mode 100644 index e7411ea24..000000000 --- a/MapView/DesktopMapView-Info.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - FMWK - CFBundleSignature - ???? - CFBundleVersion - 1.0 - - diff --git a/MapView/Info.plist b/MapView/Info.plist deleted file mode 100644 index 3dfcc3c25..000000000 --- a/MapView/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.catchme.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/MapView/Map/FMDB b/MapView/Map/FMDB index 0cfca8499..e052477dc 160000 --- a/MapView/Map/FMDB +++ b/MapView/Map/FMDB @@ -1 +1 @@ -Subproject commit 0cfca849943c6d109934c9d708d0942a8708cb99 +Subproject commit e052477dc8953f51b56994b754b1c8a10bfe7262 diff --git a/MapView/Map/GRMustache b/MapView/Map/GRMustache new file mode 160000 index 000000000..a7e871f58 --- /dev/null +++ b/MapView/Map/GRMustache @@ -0,0 +1 @@ +Subproject commit a7e871f58d8e7b81b5fb88e082d49760662ba399 diff --git a/MapView/Map/RouteMe.h b/MapView/Map/Mapbox.h similarity index 67% rename from MapView/Map/RouteMe.h rename to MapView/Map/Mapbox.h index 265e2b367..53572b18a 100644 --- a/MapView/Map/RouteMe.h +++ b/MapView/Map/Mapbox.h @@ -1,7 +1,7 @@ // -// RouteMe.h +// Mapbox.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Mapbox & Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -28,46 +28,28 @@ // The list of header files for more convenient Route-Me import to projects. // (in alphabetic order) -#import "NSUserDefaults+RouteMe.h" -#import "RMAbstractMercatorTileSource.h" -#import "RMAbstractWebMapSource.h" #import "RMAnnotation.h" #import "RMCacheObject.h" #import "RMCircle.h" +#import "RMCircleAnnotation.h" +#import "RMCompositeSource.h" #import "RMConfiguration.h" #import "RMCoordinateGridSource.h" -#import "RMDBMapSource.h" #import "RMDatabaseCache.h" -#import "RMFoundation.h" -#import "RMFractalTileProjection.h" -#import "RMGenericMapSource.h" -#import "RMGlobalConstants.h" +#import "RMGreatCircleAnnotation.h" +#import "RMInteractiveSource.h" #import "RMMBTilesSource.h" -#import "RMMapBoxSource.h" -#import "RMMapLayer.h" -#import "RMMapOverlayView.h" -#import "RMMapQuestOSMSource.h" -#import "RMMapQuestOpenAerialSource.h" -#import "RMMapScrollView.h" -#import "RMMapTiledLayerView.h" +#import "RMMapboxSource.h" #import "RMMapView.h" #import "RMMapViewDelegate.h" #import "RMMarker.h" #import "RMMemoryCache.h" -#import "RMNotifications.h" -#import "RMOpenCycleMapSource.h" -#import "RMOpenSeaMapLayer.h" -#import "RMOpenSeaMapSource.h" -#import "RMOpenStreetMapSource.h" -#import "RMPath.h" -#import "RMPixel.h" -#import "RMProjection.h" -#import "RMQuadTree.h" +#import "RMPointAnnotation.h" +#import "RMPolygonAnnotation.h" +#import "RMPolylineAnnotation.h" #import "RMShape.h" -#import "RMTile.h" +#import "RMStaticMapView.h" #import "RMTileCache.h" -#import "RMTileImage.h" -#import "RMTileSource.h" -#import "RMTileSourcesContainer.h" +#import "RMTileMillSource.h" #import "RMUserLocation.h" #import "RMUserTrackingBarButtonItem.h" diff --git a/MapView/Map/NSUserDefaults+RouteMe.m b/MapView/Map/NSUserDefaults+RouteMe.m deleted file mode 100644 index c88009ec1..000000000 --- a/MapView/Map/NSUserDefaults+RouteMe.m +++ /dev/null @@ -1,74 +0,0 @@ -// -// NSUserDefaults+RouteMe.m -// -// Copyright (c) 2008-2011, 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. -// - -#import "NSUserDefaults+RouteMe.h" - -#define kEasting @"easting" -#define kNorthing @"northing" -#define kWidth @"width" -#define kHeight @"height" - -@implementation NSUserDefaults (RouteMe) - -- (RMProjectedPoint)projectedPointForKey:(NSString *)key -{ - NSDictionary *projectedPointDictionary = [self dictionaryForKey:key]; - RMProjectedPoint projectedPoint = RMMakeProjectedPoint([[projectedPointDictionary objectForKey:kEasting] doubleValue], - [[projectedPointDictionary objectForKey:kNorthing] doubleValue]); - return projectedPoint; -} - -- (void)setProjectedPoint:(RMProjectedPoint)projectedPoint forKey:(NSString *)key -{ - NSDictionary *projectedPointDictionary = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithDouble:projectedPoint.easting], kEasting, - [NSNumber numberWithDouble:projectedPoint.northing], kNorthing, nil]; - [self setObject:projectedPointDictionary forKey:key]; -} - -- (RMProjectedRect)projectedRectForKey:(NSString *)key -{ - NSDictionary *projectedRectDictionary = [self dictionaryForKey:key]; - RMProjectedRect projectedRect = RMMakeProjectedRect([[projectedRectDictionary objectForKey:kEasting] doubleValue], - [[projectedRectDictionary objectForKey:kNorthing] doubleValue], - [[projectedRectDictionary objectForKey:kWidth] doubleValue], - [[projectedRectDictionary objectForKey:kHeight] doubleValue]); - return projectedRect; -} - -- (void)setProjectedRect:(RMProjectedRect)projectedRect forKey:(NSString *)key -{ - NSDictionary *projectedRectDictionary = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithDouble:projectedRect.origin.easting], kEasting, - [NSNumber numberWithDouble:projectedRect.origin.northing], kNorthing, - [NSNumber numberWithDouble:projectedRect.size.width], kWidth, - [NSNumber numberWithDouble:projectedRect.size.height], kHeight, nil]; - [self setObject:projectedRectDictionary forKey:key]; -} - -@end diff --git a/MapView/Map/README.txt b/MapView/Map/README.txt deleted file mode 100644 index 3a2280e8b..000000000 --- a/MapView/Map/README.txt +++ /dev/null @@ -1,6 +0,0 @@ -The Route-Me project is receiving frequent updates from its developer community. For -this reason, you'll probably want to have your hands on the source of Route-Me while -you're developing your own project. If you want to link the Route-Me .xcodeproj to your -own program, please follow the Embedding Guide, found at -http://github.com/Alpstein/route-me/wiki/Embedding-Guide -Use the "MapView" target. diff --git a/MapView/Map/RMAbstractMercatorTileSource.h b/MapView/Map/RMAbstractMercatorTileSource.h index 0fa16fa27..9dd0bb389 100644 --- a/MapView/Map/RMAbstractMercatorTileSource.h +++ b/MapView/Map/RMAbstractMercatorTileSource.h @@ -1,7 +1,7 @@ // // RMAbstractMercatorTileSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -37,6 +37,7 @@ #pragma mark --- end constants --- +/** Abstract class representing a Mercator projection for the display of map tiles. Developers wanting to provide custom network-based tiles should subclass RMAbstractWebMapSource. */ @interface RMAbstractMercatorTileSource : NSObject @end diff --git a/MapView/Map/RMAbstractMercatorTileSource.m b/MapView/Map/RMAbstractMercatorTileSource.m index ceecf48a6..414273869 100644 --- a/MapView/Map/RMAbstractMercatorTileSource.m +++ b/MapView/Map/RMAbstractMercatorTileSource.m @@ -1,7 +1,7 @@ // // RMAbstractMercatorTileSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -35,7 +35,7 @@ @implementation RMAbstractMercatorTileSource RMFractalTileProjection *_tileProjection; } -@synthesize minZoom = _minZoom, maxZoom = _maxZoom; +@synthesize minZoom = _minZoom, maxZoom = _maxZoom, cacheable = _cacheable, opaque = _opaque; - (id)init { @@ -48,13 +48,10 @@ - (id)init self.minZoom = kDefaultMinTileZoom; self.maxZoom = kDefaultMaxTileZoom; - return self; -} + self.cacheable = YES; + self.opaque = YES; -- (void)dealloc -{ - [_tileProjection release]; _tileProjection = nil; - [super dealloc]; + return self; } - (RMSphericalTrapezium)latitudeLongitudeBoundingBox @@ -69,6 +66,11 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache userInfo:nil]; } +- (BOOL)tileSourceHasTile:(RMTile)tile +{ + return YES; +} + - (void)cancelAllDownloads { } @@ -88,7 +90,7 @@ - (RMFractalTileProjection *)mercatorToTileProjection minZoom:self.minZoom]; } - return [[_tileProjection retain] autorelease]; + return _tileProjection; } - (void)didReceiveMemoryWarning diff --git a/MapView/Map/RMAbstractWebMapSource.h b/MapView/Map/RMAbstractWebMapSource.h index bde0f69b8..5e86b40fc 100644 --- a/MapView/Map/RMAbstractWebMapSource.h +++ b/MapView/Map/RMAbstractWebMapSource.h @@ -1,7 +1,7 @@ // // RMAbstractWebMapSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -31,15 +31,27 @@ #define RMAbstractWebMapSourceDefaultRetryCount 3 #define RMAbstractWebMapSourceDefaultWaitSeconds 15.0 +/** Abstract class representing a network-based location for retrieving map tiles for display. Developers can create subclasses in order to provide custom web addresses for tile downloads. */ @interface RMAbstractWebMapSource : RMAbstractMercatorTileSource +/** @name Configuring Network Behavior */ + +/** The number of times to retry downloads of a given tile image. */ @property (nonatomic, assign) NSUInteger retryCount; + +/** The network timeout for each attempt to download a tile image. */ @property (nonatomic, assign) NSTimeInterval requestTimeoutSeconds; +/** @name Providing Tile Images */ + +/** Provide the URL for a given tile. + @param tile A specific map tile. + @return A URL to a tile image to download. */ - (NSURL *)URLForTile:(RMTile)tile; -// Tilesources with layers use this method. -// URLs are ordered from the bottom layer to the top layer. +/** Provide multiple URLs for a given tile. Each URL is fetched in turn and composited together before placement on the map. URLs are ordered from the bottom layer to the top layer. + @param tile A specific map tile. + @return An array of tile URLs to download, listed bottom to top. */ - (NSArray *)URLsForTile:(RMTile)tile; @end diff --git a/MapView/Map/RMAbstractWebMapSource.m b/MapView/Map/RMAbstractWebMapSource.m index 8087d8db1..20decb8ac 100644 --- a/MapView/Map/RMAbstractWebMapSource.m +++ b/MapView/Map/RMAbstractWebMapSource.m @@ -1,7 +1,7 @@ // // RMAbstractWebMapSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -26,7 +26,9 @@ // POSSIBILITY OF SUCH DAMAGE. #import "RMAbstractWebMapSource.h" + #import "RMTileCache.h" +#import "RMConfiguration.h" #define HTTP_404_NOT_FOUND 404 @@ -62,21 +64,32 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache __block UIImage *image = nil; tile = [[self mercatorToTileProjection] normaliseTile:tile]; - image = [tileCache cachedImage:tile withCacheKey:[self uniqueTilecacheKey]]; - if (image) - return image; + // Return NSNull here so that the RMMapTiledLayerView will try to + // fetch another tile if missingTilesDepth > 0 + if ( ! [self tileSourceHasTile:tile]) + return (UIImage *)[NSNull null]; + + if (self.isCacheable) + { + image = [tileCache cachedImage:tile withCacheKey:[self uniqueTilecacheKey]]; + + if (image) + return image; + } dispatch_async(dispatch_get_main_queue(), ^(void) { [[NSNotificationCenter defaultCenter] postNotificationName:RMTileRequested object:[NSNumber numberWithUnsignedLongLong:RMTileKey(tile)]]; }); - [tileCache retain]; - NSArray *URLs = [self URLsForTile:tile]; - if ([URLs count] > 1) + if ([URLs count] == 0) + { + return nil; + } + else if ([URLs count] > 1) { // fill up collection array with placeholders // @@ -98,13 +111,14 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache for (NSUInteger try = 0; tileData == nil && try < self.retryCount; ++try) { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:currentURL]; + [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; [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) { - @synchronized(self) + @synchronized (self) { // safely put into collection array in proper order // @@ -117,7 +131,9 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache // wait for whole group of fetches (with retries) to finish, then clean up // dispatch_group_wait(fetchGroup, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * self.requestTimeoutSeconds)); +#if ! OS_OBJECT_USE_OBJC dispatch_release(fetchGroup); +#endif // composite the collected images together // @@ -147,19 +163,18 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache { NSHTTPURLResponse *response = nil; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[URLs objectAtIndex:0]]; + [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; [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; } } - if (image) + if (image && self.isCacheable) [tileCache addImage:image forTile:tile withCacheKey:[self uniqueTilecacheKey]]; - [tileCache release]; - dispatch_async(dispatch_get_main_queue(), ^(void) { [[NSNotificationCenter defaultCenter] postNotificationName:RMTileRetrieved object:[NSNumber numberWithUnsignedLongLong:RMTileKey(tile)]]; diff --git a/MapView/Map/RMAnnotation.h b/MapView/Map/RMAnnotation.h index 699e4dcd2..52fe0db8b 100644 --- a/MapView/Map/RMAnnotation.h +++ b/MapView/Map/RMAnnotation.h @@ -2,7 +2,7 @@ // RMAnnotation.h // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -28,8 +28,14 @@ #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. +* +* Subclasses of RMAnnotation such as RMPointAnnotation, RMPolylineAnnotation, and RMPolygonAnnotation are useful for simple needs such as easily putting points and shapes onto a map view. They manage their own layer and don't require configuration in the map view delegate in order to be displayed. */ @interface RMAnnotation : NSObject { CLLocationCoordinate2D coordinate; @@ -42,7 +48,7 @@ BOOL enabled, clusteringEnabled; RMMapLayer *layer; - RMQuadTreeNode *quadTreeNode; + __weak RMQuadTreeNode *quadTreeNode; // provided for storage of arbitrary user data id userInfo; @@ -51,34 +57,86 @@ CGPoint anchorPoint; } +/** @name Configuration Basic Annotation Properties */ + +/** The annotation's location on the map. */ @property (nonatomic, assign) CLLocationCoordinate2D coordinate; -@property (nonatomic, retain) NSString *title; -@property (nonatomic, retain) id userInfo; -@property (nonatomic, retain) NSString *annotationType; -@property (nonatomic, retain) UIImage *annotationIcon; -@property (nonatomic, retain) UIImage *badgeIcon; + +/** The annotation's title. */ +@property (nonatomic, strong) NSString *title; + +/** The annotation's subtitle. */ +@property (nonatomic, strong) NSString *subtitle; + +/** Storage for arbitrary data. */ +@property (nonatomic, strong) id userInfo; + +/** An arbitrary string representing the type of annotation. Useful for determining which layer to draw for the annotation when requested in the delegate. Cluster annotations, which are automatically created by a map view, will automatically have an annotationType of `RMClusterAnnotation`. */ +@property (nonatomic, strong) NSString *annotationType; + +/** An arbitrary icon image for the annotation. Useful to pass an image at annotation creation time for use in the layer at a later time. */ +@property (nonatomic, strong) UIImage *annotationIcon; +@property (nonatomic, strong) UIImage *badgeIcon; @property (nonatomic, assign) CGPoint anchorPoint; -// the location on screen. don't set this directly, use the coordinate property. +/** 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; -@property (nonatomic, assign) BOOL enabled; + +/** Whether touch events for the annotation's layer are recognized. Defaults to `YES`. */ +@property (nonatomic, assign, getter=isEnabled) BOOL enabled; + +/** @name Representing an Annotation Visually */ + +/** An object representing the annotation's visual appearance. +* +* @see RMMarker +* @see RMShape +* @see RMCircle */ +@property (nonatomic, strong) RMMapLayer *layer; + +/** @name Annotation Clustering */ + +/** Whether the annotation should be clustered when map view clustering is enabled. Defaults to `YES`. */ @property (nonatomic, assign) BOOL clusteringEnabled; -// RMMarker, RMPath, whatever you return in your delegate method mapView:layerForAnnotation: -@property (nonatomic, retain) RMMapLayer *layer; +/** 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; -// This is for the QuadTree. Don't mess this up. -@property (nonatomic, assign) RMQuadTreeNode *quadTreeNode; +@property (nonatomic, weak) RMQuadTreeNode *quadTreeNode; -// This is for filtering framework-provided annotations. +/** @name Filtering Types of Annotations */ + +/** Whether the annotation is related to display of the user's location. Useful for filtering purposes when providing annotation layers in the delegate. +* +* There are three possible user location annotations, depending on current conditions: the user dot, the pulsing halo, and the accuracy circle. All may have custom layers provided, but if you only want to customize the user dot, you should check that the annotation is a member of the RMUserLocation class in order to ensure that you are altering only the correct annotation layer. */ @property (nonatomic, readonly) BOOL isUserLocationAnnotation; #pragma mark - -+ (id)annotationWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle; +/** @name Initializing Annotations */ + +/** 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. +* @return An annotation object, or `nil` if an annotation was unable to be created. */ ++ (instancetype)annotationWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle; + +/** 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. +* @return An initialized annotation object, or `nil` if an annotation was unable to be initialized. */ - (id)initWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle; - (void)setBoundingBoxCoordinatesSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast; @@ -86,12 +144,16 @@ #pragma mark - -// YES if the annotation is on the screen, regardles if clustered or not +/** @name Querying Annotation Visibility */ + +/** Whether the annotation is currently on the screen, regardless if clustered or not. */ @property (nonatomic, readonly) BOOL isAnnotationOnScreen; +/** Whether the annotation is within a certain screen bounds. +* @param bounds A given screen bounds. */ - (BOOL)isAnnotationWithinBounds:(CGRect)bounds; -// NO if the annotation is currently offscreen or clustered +/** Whether the annotation is currently visible on the screen. An annotation is not visible if it is either offscreen or currently in a cluster. */ @property (nonatomic, readonly) BOOL isAnnotationVisibleOnScreen; #pragma mark - @@ -101,6 +163,6 @@ #pragma mark - // Used internally -@property (nonatomic, retain) RMMapView *mapView; +@property (nonatomic, weak) RMMapView *mapView; @end diff --git a/MapView/Map/RMAnnotation.m b/MapView/Map/RMAnnotation.m index c119a429f..985ef349e 100644 --- a/MapView/Map/RMAnnotation.m +++ b/MapView/Map/RMAnnotation.m @@ -2,7 +2,7 @@ // RMAnnotation.m // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -34,10 +34,19 @@ #import "RMMapLayer.h" #import "RMQuadTree.h" +@interface RMQuadTreeNode (RMAnnotation) + +- (void)annotationDidChangeBoundingBox:(RMAnnotation *)annotation; + +@end + +#pragma mark - + @implementation RMAnnotation @synthesize coordinate; @synthesize title; +@synthesize subtitle; @synthesize userInfo; @synthesize annotationType; @synthesize annotationIcon, badgeIcon; @@ -50,11 +59,13 @@ @implementation RMAnnotation @synthesize enabled, clusteringEnabled; @synthesize position; @synthesize quadTreeNode; +@synthesize isClusterAnnotation=_isClusterAnnotation; +@synthesize clusteredAnnotations; @synthesize isUserLocationAnnotation; -+ (id)annotationWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle ++ (instancetype)annotationWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle { - return [[[self alloc] initWithMapView:aMapView coordinate:aCoordinate andTitle:aTitle] autorelease]; + return [[self alloc] initWithMapView:aMapView coordinate:aCoordinate andTitle:aTitle]; } - (id)initWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle @@ -65,6 +76,7 @@ - (id)initWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)a self.mapView = aMapView; self.coordinate = aCoordinate; self.title = aTitle; + self.subtitle = nil; self.userInfo = nil; self.quadTreeNode = nil; @@ -85,18 +97,7 @@ - (id)initWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)a - (void)dealloc { - self.title = nil; - self.userInfo = nil; - self.layer = nil; [[self.mapView quadTree] removeAnnotation:self]; - self.quadTreeNode = nil; - self.mapView = nil; - - self.annotationType = nil; - self.annotationIcon = nil; - self.badgeIcon = nil; - - [super dealloc]; } - (void)setCoordinate:(CLLocationCoordinate2D)aCoordinate @@ -113,8 +114,7 @@ - (void)setCoordinate:(CLLocationCoordinate2D)aCoordinate - (void)setMapView:(RMMapView *)aMapView { - [mapView autorelease]; - mapView = [aMapView retain]; + mapView = aMapView; if (!aMapView) self.layer = nil; @@ -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; @@ -140,19 +145,21 @@ - (RMMapLayer *)layer - (void)setLayer:(RMMapLayer *)aLayer { + CALayer *superLayer = [layer superlayer]; + if (layer != aLayer) { if (layer.superlayer) [layer removeFromSuperlayer]; - [layer release]; layer = nil; + layer = nil; } if (aLayer) { layer = aLayer; - [layer retain]; layer.annotation = self; + [superLayer addSublayer:layer]; [layer setPosition:self.position animated:NO]; } } @@ -172,13 +179,22 @@ - (BOOL)isAnnotationWithinBounds:(CGRect)bounds - (BOOL)isAnnotationOnScreen { - CGRect screenBounds = [mapView bounds]; - return [self isAnnotationWithinBounds:screenBounds]; + return [self isAnnotationWithinBounds:[mapView bounds]]; } - (BOOL)isAnnotationVisibleOnScreen { - return (layer != nil); + 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 diff --git a/MapView/Map/RMAttributionViewController.h b/MapView/Map/RMAttributionViewController.h new file mode 100644 index 000000000..dbd869d0e --- /dev/null +++ b/MapView/Map/RMAttributionViewController.h @@ -0,0 +1,17 @@ +// +// RMAttributionViewController.h +// MapView +// +// Created by Justin Miller on 6/19/12. +// Copyright (c) 2012-2013 Mapbox. All rights reserved. +// + +#import + +@class RMMapView; + +@interface RMAttributionViewController : UIViewController + +- (id)initWithMapView:(RMMapView *)mapView; + +@end diff --git a/MapView/Map/RMAttributionViewController.m b/MapView/Map/RMAttributionViewController.m new file mode 100644 index 000000000..eddff6d40 --- /dev/null +++ b/MapView/Map/RMAttributionViewController.m @@ -0,0 +1,220 @@ +// +// RMAttributionViewController.m +// MapView +// +// Created by Justin Miller on 6/19/12. +// Copyright (c) 2012-2013 Mapbox. All rights reserved. +// + +#import "RMAttributionViewController.h" + +#import "RMMapView.h" +#import "RMTileSource.h" + +@interface RMMapView (RMAttributionViewControllerPrivate) + +@property (nonatomic, assign) UIViewController *viewControllerPresentingAttribution; + +- (void)dismissAttribution:(id)sender; + +@end + +#pragma mark - + +@interface RMAttributionViewController () + +@property (nonatomic, weak) RMMapView *mapView; + +@end + +#pragma mark - + +@implementation RMAttributionViewController + +- (id)initWithMapView:(RMMapView *)mapView +{ + self = [super initWithNibName:nil bundle:nil]; + + if (self) + _mapView = mapView; + + return self; +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + self.title = @"Map Attribution"; + + self.view.backgroundColor = (RMPostVersion7 ? [UIColor colorWithWhite:1 alpha:0.9] : [UIColor darkGrayColor]); + + if (RMPreVersion7) + [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss:)]]; + + CGRect frame = (RMPostVersion7 ? self.view.bounds : CGRectMake(0, self.view.bounds.size.height - 70, self.view.bounds.size.width, 60)); + + UIWebView *webView = [[UIWebView alloc] initWithFrame:frame]; + webView.delegate = self; + webView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | (RMPostVersion7 ? UIViewAutoresizingFlexibleHeight : UIViewAutoresizingFlexibleTopMargin); + webView.scrollView.showsVerticalScrollIndicator = NO; + webView.backgroundColor = [UIColor clearColor]; + webView.opaque = NO; + + // don't bounce for page curled presentation + // + if (RMPreVersion7) + { + if ([webView respondsToSelector:@selector(scrollView)]) + { + webView.scrollView.bounces = NO; + } + else + { + for (id subview in webView.subviews) + if ([[subview class] isSubclassOfClass:[UIScrollView class]]) + ((UIScrollView *)subview).bounces = NO; + } + } + + // build up attribution from tile sources + // + NSMutableString *attribution = [NSMutableString string]; + + for (id tileSource in _mapView.tileSources) + { + if ([tileSource respondsToSelector:@selector(shortAttribution)]) + { + if ([attribution length]) + [attribution appendString:@" "]; + + if ([tileSource shortAttribution]) + [attribution appendString:[tileSource shortAttribution]]; + } + } + + // fallback to generic OSM attribution + // + if ( ! [attribution length]) + [attribution setString:@"Map data © OpenStreetMap contributors
More"]; + + // build up HTML styling + // + NSMutableString *contentString = [NSMutableString string]; + + [contentString appendString:@""]; + + if (RMPostVersion7) + { + // add SDK info + // + NSString *appName = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleDisplayName"]; + NSDateFormatter *dateFormatter = [NSDateFormatter new]; + [dateFormatter setDateFormat:@"yyyy"]; + NSString *currentYear = [dateFormatter stringFromDate:[NSDate date]]; + [attribution insertString:[NSString stringWithFormat:@"%@ uses the Mapbox iOS SDK © %@ Mapbox, Inc.
More

", appName, currentYear] atIndex:0]; + + // add tinted logo + // + UIImage *logoImage = [RMMapView resourceImageNamed:@"mapbox-logo.png"]; + UIGraphicsBeginImageContextWithOptions(logoImage.size, NO, [[UIScreen mainScreen] scale]); + [logoImage drawAtPoint:CGPointMake(0, 0)]; + CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeSourceIn); + CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [self.view.tintColor CGColor]); + CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, logoImage.size.width, logoImage.size.height)); + NSString *tempFile = [[NSTemporaryDirectory() stringByAppendingString:@"/"] stringByAppendingString:[NSString stringWithFormat:@"%f", [NSDate timeIntervalSinceReferenceDate]]]; + [UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext()) writeToFile:tempFile atomically:YES]; + UIGraphicsEndImageContext(); + [attribution insertString:[NSString stringWithFormat:@"

", tempFile] atIndex:0]; + } + + // add attribution + // + [contentString appendString:attribution]; + + [webView loadHTMLString:contentString baseURL:nil]; + [self.view addSubview:webView]; + + // add activity indicator + // + UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + [spinner startAnimating]; + spinner.center = webView.center; + spinner.tag = 1; + [self.view insertSubview:spinner atIndex:0]; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return [_mapView.viewControllerPresentingAttribution shouldAutorotateToInterfaceOrientation:interfaceOrientation]; +} + +- (NSUInteger)supportedInterfaceOrientations +{ + return [_mapView.viewControllerPresentingAttribution supportedInterfaceOrientations]; +} + +- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation +{ + UIWebView *webView = (UIWebView *)self.view.subviews[0]; + + if (UIInterfaceOrientationIsLandscape(fromInterfaceOrientation)) + webView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); + + [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; +} + +#pragma mark - + +- (void)dismiss:(id)sender +{ + [self.mapView dismissAttribution:self]; +} + +#pragma mark - + +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType +{ + if (navigationType == UIWebViewNavigationTypeLinkClicked) + { + [[UIApplication sharedApplication] openURL:request.URL]; + + [self performSelector:@selector(dismiss:) withObject:nil afterDelay:0]; + } + + return [[request.URL scheme] isEqualToString:@"about"]; +} + +- (void)webViewDidFinishLoad:(UIWebView *)webView +{ + [webView stringByEvaluatingJavaScriptFromString:@"document.body.style.webkitTouchCallout='none';"]; + + [[self.view viewWithTag:1] removeFromSuperview]; +} + +@end diff --git a/MapView/Map/RMBingSource.h b/MapView/Map/RMBingSource.h new file mode 100644 index 000000000..209598888 --- /dev/null +++ b/MapView/Map/RMBingSource.h @@ -0,0 +1,41 @@ +// +// RMBingSource.h +// +// Copyright (c) 2008-2013, 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. + +#import "RMAbstractWebMapSource.h" + +typedef enum : NSUInteger { + RMBingImagerySetRoad = 0, // default + RMBingImagerySetAerial = 1, + RMBingImagerySetAerialWithLabels = 2, +} RMBingImagerySet; + +@interface RMBingSource : RMAbstractWebMapSource + +- (id)initWithMapsKey:(NSString *)mapsKey; +- (id)initWithMapsKey:(NSString *)mapsKey forImagerySet:(RMBingImagerySet)imagerySet; + +@end diff --git a/MapView/Map/RMBingSource.m b/MapView/Map/RMBingSource.m new file mode 100644 index 000000000..bf2a1c9f3 --- /dev/null +++ b/MapView/Map/RMBingSource.m @@ -0,0 +1,152 @@ +// +// RMBingSource.m +// +// Copyright (c) 2008-2013, 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. + +#import "RMBingSource.h" + +#import "RMConfiguration.h" + +@implementation RMBingSource +{ + NSString *_mapsKey; + NSString *_imageURLString; + NSString *_uniqueTilecacheKey; + RMBingImagerySet _imagerySet; +} + +- (id)initWithMapsKey:(NSString *)mapsKey +{ + return [self initWithMapsKey:mapsKey forImagerySet:RMBingImagerySetRoad]; +} + +- (id)initWithMapsKey:(NSString *)mapsKey forImagerySet:(RMBingImagerySet)imagerySet; +{ + if (self = [super init]) + { + _mapsKey = mapsKey; + + _imagerySet = imagerySet; + + _uniqueTilecacheKey = [NSString stringWithFormat:@"Bing%lu", (unsigned long)_imagerySet]; + + self.minZoom = 1; + self.maxZoom = 21; + + return self; + } + + return nil; +} + +- (NSURL *)URLForTile:(RMTile)tile +{ + if ( ! _imageURLString) + { + NSString *imagerySetString = nil; + + if (_imagerySet == RMBingImagerySetAerial) + imagerySetString = @"Aerial"; + else if (_imagerySet == RMBingImagerySetAerialWithLabels) + imagerySetString = @"AerialWithLabels"; + else + imagerySetString = @"Road"; + + NSURL *metadataURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://dev.virtualearth.net/REST/v1/Imagery/Metadata/%@?key=%@", imagerySetString, _mapsKey]]; + + NSData *metadataData = [NSData brandedDataWithContentsOfURL:metadataURL]; + + if ( ! metadataData) + return nil; + + id metadata = [NSJSONSerialization JSONObjectWithData:metadataData options:0 error:NULL]; + + if (metadata && [metadata isKindOfClass:[NSDictionary class]] && [[metadata objectForKey:@"statusCode"] intValue] == 200) + { + NSDictionary *resources = [[[[(NSDictionary *)metadata objectForKey:@"resourceSets"] objectAtIndex:0] objectForKey:@"resources"] objectAtIndex:0]; + + _imageURLString = [[[resources objectForKey:@"imageUrl"] stringByReplacingOccurrencesOfString:@"{subdomain}" + withString:[[resources objectForKey:@"imageUrlSubdomains"] objectAtIndex:0]] copy]; + } + } + + if ( ! _imageURLString) + return nil; + + NSMutableString *tileURLString = [NSMutableString stringWithString:_imageURLString]; + + [tileURLString replaceOccurrencesOfString:@"{culture}" withString:@"en" options:0 range:NSMakeRange(0, [tileURLString length])]; + + NSMutableString *quadKey = [NSMutableString string]; + + for (int i = tile.zoom; i > 0; i--) + { + int digit = 0; + + int mask = 1 << (i - 1); + + if ((tile.x & mask) != 0) + digit++; + + if ((tile.y & mask) != 0) + { + digit++; + digit++; + } + + [quadKey appendString:[NSString stringWithFormat:@"%i", digit]]; + } + + [tileURLString replaceOccurrencesOfString:@"{quadkey}" withString:quadKey options:0 range:NSMakeRange(0, [tileURLString length])]; + + return [NSURL URLWithString:tileURLString]; +} + +- (NSString *)uniqueTilecacheKey +{ + return _uniqueTilecacheKey; +} + +- (NSString *)shortName +{ + return @"Bing"; +} + +- (NSString *)longDescription +{ + return @"Microsoft Bing Maps"; +} + +- (NSString *)shortAttribution +{ + return @"Copyright © 2013 Microsoft"; +} + +- (NSString *)longAttribution +{ + return @"Copyright © 2013 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation."; +} + +@end diff --git a/MapView/Map/RMCacheObject.h b/MapView/Map/RMCacheObject.h index 2e4e23443..9203498c5 100644 --- a/MapView/Map/RMCacheObject.h +++ b/MapView/Map/RMCacheObject.h @@ -27,17 +27,38 @@ #import "RMTile.h" +/** An RMCacheObject is a representation of a tile cache for use with the RMMemoryCache in-memory cache storage. While RMDatabaseCache uses a disk-based database backing store, RMMemoryCache maintains first-class objects in memory for use later. */ @interface RMCacheObject : NSObject +/** @name Managing Cache Objects */ + +/** The object to be cached, typically a UIImage. */ @property (nonatomic, readonly) id cachedObject; + +/** The unique identifier for the cache. */ @property (nonatomic, readonly) NSString *cacheKey; + +/** The tile key for the cache object. */ @property (nonatomic, readonly) RMTile tile; + +/** The freshness timestamp for the cache object. */ @property (nonatomic, readonly) NSDate *timestamp; -+ (id)cacheObject:(id)anObject forTile:(RMTile)aTile withCacheKey:(NSString *)aCacheKey; +/** Creates and returns a cache object for a given key and object to store in a given cache. +* @param anObject The object to cache, typically a UIImage. +* @param aTile The tile key for the object. +* @param aCacheKey The unique identifier for the cache. +* @return A newly created cache object. */ ++ (instancetype)cacheObject:(id)anObject forTile:(RMTile)aTile withCacheKey:(NSString *)aCacheKey; +/** Initializes and returns a newly allocated cache object for a given key and object to store in a given cache. +* @param anObject The object to cache, typically a UIImage. +* @param tile The tile key for the object. +* @param aCacheKey The unique identifier for the cache. +* @return An initialized cache object. */ - (id)initWithObject:(id)anObject forTile:(RMTile)tile withCacheKey:(NSString *)aCacheKey; +/** Updates the timestamp on a cache object to indicate freshness. Objects with older timestamps get deleted first when space is needed. */ - (void)touch; @end diff --git a/MapView/Map/RMCacheObject.m b/MapView/Map/RMCacheObject.m index b3c2bb721..f6bed2049 100644 --- a/MapView/Map/RMCacheObject.m +++ b/MapView/Map/RMCacheObject.m @@ -42,9 +42,9 @@ @implementation RMCacheObject @synthesize tile = _tile; @synthesize timestamp = _timestamp; -+ (id)cacheObject:(id)anObject forTile:(RMTile)aTile withCacheKey:(NSString *)aCacheKey ++ (instancetype)cacheObject:(id)anObject forTile:(RMTile)aTile withCacheKey:(NSString *)aCacheKey { - return [[[self alloc] initWithObject:anObject forTile:aTile withCacheKey:aCacheKey] autorelease]; + return [[self alloc] initWithObject:anObject forTile:aTile withCacheKey:aCacheKey]; } - (id)initWithObject:(id)anObject forTile:(RMTile)aTile withCacheKey:(NSString *)aCacheKey @@ -52,26 +52,20 @@ - (id)initWithObject:(id)anObject forTile:(RMTile)aTile withCacheKey:(NSString * if (!(self = [super init])) return nil; - _cachedObject = [anObject retain]; - _cacheKey = [aCacheKey retain]; + _cachedObject = anObject; + _cacheKey = aCacheKey; _tile = aTile; _timestamp = [NSDate new]; return self; } -- (void)dealloc -{ - [_cachedObject release]; _cachedObject = nil; - [_cacheKey release]; _cacheKey = nil; - [_timestamp release]; _timestamp = nil; - [super dealloc]; -} - - (void)touch { - [_timestamp autorelease]; - _timestamp = [NSDate new]; + @synchronized (self) + { + _timestamp = [NSDate new]; + } } - (NSString *)description diff --git a/MapView/Map/RMCircle.h b/MapView/Map/RMCircle.h index 37f97d8ef..9eae9a82e 100644 --- a/MapView/Map/RMCircle.h +++ b/MapView/Map/RMCircle.h @@ -1,7 +1,7 @@ // // RMCircle.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ @class RMMapView; +/** An RMCircle is used to represent a perfect circle shape on a map view. An RMCircle changes visible size in response to map zooms in order to consistently represent coverage of the same geographic area. */ @interface RMCircle : RMMapLayer { RMMapView *mapView; @@ -45,12 +46,31 @@ CGMutablePathRef circlePath; } -@property (nonatomic, retain) CAShapeLayer *shapeLayer; -@property (nonatomic, retain) UIColor *lineColor; -@property (nonatomic, retain) UIColor *fillColor; +/** @name Accessing Drawing Properties */ + +/** The circle's underlying shape layer. */ +@property (nonatomic, strong) CAShapeLayer *shapeLayer; + +/** The circle's line color. Defaults to black. */ +@property (nonatomic, strong) UIColor *lineColor; + +/** The circle's fill color. Defaults to blue with a 25% alpha value. */ +@property (nonatomic, strong) UIColor *fillColor; + +/** The fill pattern image of the circle. If set, the fillColor is set to `nil`. */ +@property (nonatomic, strong) UIImage *fillPatternImage; + +/** The radius of the circle in projected meters. Regardless of map zoom, the circle will change visible size to continously represent this radius on the map. */ @property (nonatomic, assign) CGFloat radiusInMeters; + +/** The circle's line width. Defaults to 2.0. */ @property (nonatomic, assign) CGFloat lineWidthInPixels; +/** @name Creating Circle Objects */ + +/** Initializes and returns a newly allocated RMCircle for the specified map view. +* @param aMapView The map view the shape should be drawn on. +* @param newRadiusInMeters The radius of the circle object in projected meters. Regardless of map zoom, the circle will change visible size to continously represent this radius on the map. */ - (id)initWithView:(RMMapView *)aMapView radiusInMeters:(CGFloat)newRadiusInMeters; @end diff --git a/MapView/Map/RMCircle.m b/MapView/Map/RMCircle.m index 929267dea..d5d8361fb 100644 --- a/MapView/Map/RMCircle.m +++ b/MapView/Map/RMCircle.m @@ -1,7 +1,7 @@ /// // RMCircle.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -29,9 +29,9 @@ #import "RMProjection.h" #import "RMMapView.h" -#define kDefaultLineWidth 10.0 +#define kDefaultLineWidth 2.0 #define kDefaultLineColor [UIColor blackColor] -#define kDefaultFillColor [UIColor blueColor] +#define kDefaultFillColor [UIColor colorWithRed:0 green:0 blue:1.0 alpha:0.25] @interface RMCircle () @@ -54,7 +54,7 @@ - (id)initWithView:(RMMapView *)aMapView radiusInMeters:(CGFloat)newRadiusInMete if (!(self = [super init])) return nil; - shapeLayer = [[CAShapeLayer alloc] init]; + shapeLayer = [CAShapeLayer new]; [self addSublayer:shapeLayer]; mapView = aMapView; @@ -65,22 +65,18 @@ - (id)initWithView:(RMMapView *)aMapView radiusInMeters:(CGFloat)newRadiusInMete fillColor = kDefaultFillColor; scaleLineWidth = NO; - enableDragging = YES; circlePath = NULL; [self updateCirclePathAnimated:NO]; + self.masksToBounds = NO; + return self; } - (void)dealloc { - mapView = nil; - [shapeLayer release]; shapeLayer = nil; CGPathRelease(circlePath); circlePath = NULL; - [lineColor release]; lineColor = nil; - [fillColor release]; fillColor = nil; - [super dealloc]; } #pragma mark - @@ -128,16 +124,41 @@ - (void)updateCirclePathAnimated:(BOOL)animated [self.shapeLayer setFillColor:[fillColor CGColor]]; [self.shapeLayer setStrokeColor:[lineColor CGColor]]; [self.shapeLayer setLineWidth:lineWidthInPixels]; + + if (self.fillPatternImage) + self.shapeLayer.fillColor = [[UIColor colorWithPatternImage:self.fillPatternImage] CGColor]; } #pragma mark - Accessors +- (BOOL)containsPoint:(CGPoint)thePoint +{ + BOOL containsPoint = NO; + + if ([self.fillColor isEqual:[UIColor clearColor]]) + { + // if shape is not filled with a color, do a simple "point on path" test + // + UIGraphicsBeginImageContext(self.bounds.size); + CGContextAddPath(UIGraphicsGetCurrentContext(), shapeLayer.path); + containsPoint = CGContextPathContainsPoint(UIGraphicsGetCurrentContext(), thePoint, kCGPathStroke); + UIGraphicsEndImageContext(); + } + else + { + // else do a "path contains point" test + // + containsPoint = CGPathContainsPoint(shapeLayer.path, nil, thePoint, [shapeLayer.fillRule isEqualToString:kCAFillRuleEvenOdd]); + } + + return containsPoint; +} + - (void)setLineColor:(UIColor *)newLineColor { if (lineColor != newLineColor) { - [lineColor release]; - lineColor = [newLineColor retain]; + lineColor = newLineColor; [self updateCirclePathAnimated:NO]; } } @@ -146,8 +167,19 @@ - (void)setFillColor:(UIColor *)newFillColor { if (fillColor != newFillColor) { - [fillColor release]; - fillColor = [newFillColor retain]; + fillColor = newFillColor; + [self updateCirclePathAnimated:NO]; + } +} + +- (void)setFillPatternImage:(UIImage *)fillPatternImage +{ + if (fillPatternImage) + self.fillColor = nil; + + if (_fillPatternImage != fillPatternImage) + { + _fillPatternImage = fillPatternImage; [self updateCirclePathAnimated:NO]; } } diff --git a/MapView/Map/RMCircleAnnotation.h b/MapView/Map/RMCircleAnnotation.h new file mode 100644 index 000000000..a389470e6 --- /dev/null +++ b/MapView/Map/RMCircleAnnotation.h @@ -0,0 +1,52 @@ +// +// RMCircleAnnotation.h +// MapView +// +// Copyright (c) 2008-2013, 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. + +#import "RMShapeAnnotation.h" + +/** An RMCircleAnnotation is a concrete subclass of RMShapeAnnotation that is used to represent a circle shape on the map. The annotation will automatically have a layer created when needed that displays an RMCircle. +* +* If you wish to customize the layer appearance in more detail, you should instead create an RMAnnotation and configure its layer directly. Providing a layer manually for instances of RMCircleAnnotation will not have any effect. */ +@interface RMCircleAnnotation : RMShapeAnnotation + +/** Initialize a circle annotation. +* @param aMapView The map view on which to place the annotation. +* @param centerCoordinate The center of the annotation. +* @param radiusInMeters The radius of the circle in projected meters. +* @return An initialized circle annotation object, or `nil` if an annotation was unable to be initialized. */ +- (id)initWithMapView:(RMMapView *)aMapView centerCoordinate:(CLLocationCoordinate2D)centerCoordinate radiusInMeters:(CGFloat)radiusInMeters; + +/** The circle annotation's center coordinate. */ +@property (nonatomic, assign) CLLocationCoordinate2D centerCoordinate; + +/** The circle annotation's line width. */ +@property (nonatomic, assign) CGFloat lineWidthInPixels; + +/** The radius of the circle annotation in projected meters. Regardless of map zoom, the circle will change visible size to continously represent this radius on the map. */ +@property (nonatomic, assign) CGFloat radiusInMeters; + +@end diff --git a/MapView/Map/RMCircleAnnotation.m b/MapView/Map/RMCircleAnnotation.m new file mode 100644 index 000000000..634afc627 --- /dev/null +++ b/MapView/Map/RMCircleAnnotation.m @@ -0,0 +1,98 @@ +// +// RMCircleAnnotation.m +// MapView +// +// Copyright (c) 2008-2013, 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. + +#import "RMCircleAnnotation.h" + +#import "RMCircle.h" + +@implementation RMCircleAnnotation + +@synthesize radiusInMeters=_radiusInMeters; + +- (id)initWithMapView:(RMMapView *)aMapView centerCoordinate:(CLLocationCoordinate2D)centerCoordinate radiusInMeters:(CGFloat)radiusInMeters +{ + if (!(self = [super initWithMapView:aMapView points:[NSArray arrayWithObject:[[CLLocation alloc] initWithLatitude:centerCoordinate.latitude longitude:centerCoordinate.longitude]]])) + return nil; + + _radiusInMeters = radiusInMeters; + + return self; +} + +- (void)setLayer:(RMMapLayer *)newLayer +{ + if ( ! newLayer) + [super setLayer:nil]; + else + RMLog(@"Setting a custom layer on an %@ is a no-op", [self class]); +} + +- (RMMapLayer *)layer +{ + if ( ! [super layer]) + super.layer = [[RMCircle alloc] initWithView:self.mapView radiusInMeters:_radiusInMeters]; + + return [super layer]; +} + +- (CLLocationCoordinate2D)centerCoordinate +{ + return self.coordinate; +} + +- (void)setLineWidthInPixels:(CGFloat)lineWidthInPixels +{ + [(RMCircle *)[self layer] setLineWidthInPixels:lineWidthInPixels]; +} + +- (CGFloat)lineWidthInPixels +{ + return ((RMCircle *)[self layer]).lineWidthInPixels; +} + +- (void)setLineWidth:(CGFloat)lineWidth +{ + [self setLineWidthInPixels:lineWidth]; +} + +- (CGFloat)lineWidth +{ + return [self lineWidthInPixels]; +} + +- (void)setRadiusInMeters:(CGFloat)radiusInMeters +{ + [(RMCircle *)[self layer] setRadiusInMeters:radiusInMeters]; +} + +- (CGFloat)radiusInMeters +{ + return [((RMCircle *)[self layer]) radiusInMeters]; +} + +@end diff --git a/MapView/Map/RMCompositeSource.h b/MapView/Map/RMCompositeSource.h new file mode 100644 index 000000000..1664916e8 --- /dev/null +++ b/MapView/Map/RMCompositeSource.h @@ -0,0 +1,50 @@ +// +// RMCompositeSource.h +// MapView +// +// Copyright (c) 2008-2013, 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. + +#import "RMAbstractMercatorTileSource.h" + +/** RMCompositeSource combines two or more other tile sources, compositing them into a single image per tile and caching that composited result to the tile cache. +* +* RMCompositeSource can have better performance for instances of fully opaque tiles that are layered above other tiles in the tile source stacking order. It will determine if a tile is opaque and stop iteration of tile sources below it early as a result, since they would be obscured anyway. */ +@interface RMCompositeSource : RMAbstractMercatorTileSource + +/** @name Creating Tile Sources */ + +/** Initialize a compositing tile source. +* +* @param tileSources An array of tile sources to be composited. +* @param tileCacheKey A tile cache key for storage of composited result tiles. +* @return An initialized compositing tile source. */ +- (id)initWithTileSources:(NSArray *)tileSources tileCacheKey:(NSString *)tileCacheKey; + +/** @name Querying Tile Source Information */ + +/** An array of tile sources being composited. */ +@property (nonatomic, weak, readonly) NSArray *tileSources; + +@end diff --git a/MapView/Map/RMCompositeSource.m b/MapView/Map/RMCompositeSource.m new file mode 100644 index 000000000..f996b31bd --- /dev/null +++ b/MapView/Map/RMCompositeSource.m @@ -0,0 +1,181 @@ +// +// RMCompositeSource.m +// MapView +// +// Copyright (c) 2008-2013, 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. + +#import "RMCompositeSource.h" +#import "RMTileCache.h" + +@implementation RMCompositeSource +{ + NSArray *_tileSources; + NSString *_uniqueTilecacheKey; +} + +- (id)initWithTileSources:(NSArray *)tileSources tileCacheKey:(NSString *)tileCacheKey +{ + if (!(self = [super init])) + return nil; + + NSAssert(tileSources != nil && [tileSources count], @"Empty host parameter not allowed"); + + _tileSources = [tileSources copy]; + + if (tileCacheKey) + { + _uniqueTilecacheKey = tileCacheKey; + } + else + { + self.cacheable = NO; + _uniqueTilecacheKey = nil; + } + + float tileSourcesMinZoom = FLT_MAX, tileSourcesMaxZoom = FLT_MIN; + BOOL tileSourcesAreOpaque = YES; + + for (id currentTileSource in _tileSources) + { + tileSourcesMinZoom = MIN(tileSourcesMinZoom, currentTileSource.minZoom); + tileSourcesMaxZoom = MAX(tileSourcesMaxZoom, currentTileSource.maxZoom); + + if ( ! currentTileSource.isOpaque) + tileSourcesAreOpaque = NO; + } + + self.minZoom = tileSourcesMinZoom; + self.maxZoom = tileSourcesMaxZoom; + self.opaque = tileSourcesAreOpaque; + + return self; +} + +- (NSArray *)tileSources +{ + return [_tileSources copy]; +} + +- (NSString *)uniqueTilecacheKey +{ + return _uniqueTilecacheKey; +} + +- (NSString *)shortName +{ + return @"Generic Map Source"; +} + +- (NSString *)longDescription +{ + return @"Generic Map Source"; +} + +- (NSString *)shortAttribution +{ + return @"n/a"; +} + +- (NSString *)longAttribution +{ + return @"n/a"; +} + +- (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache +{ + UIImage *image = nil; + + tile = [[self mercatorToTileProjection] normaliseTile:tile]; + + if (self.isCacheable) + { + image = [tileCache cachedImage:tile withCacheKey:[self uniqueTilecacheKey]]; + + if (image) + return image; + } + + dispatch_async(dispatch_get_main_queue(), ^(void) + { + [[NSNotificationCenter defaultCenter] postNotificationName:RMTileRequested object:[NSNumber numberWithUnsignedLongLong:RMTileKey(tile)]]; + }); + + NSMutableArray *tileImages = [NSMutableArray arrayWithCapacity:[_tileSources count]]; + + for (NSUInteger p = 0; p < [_tileSources count]; ++p) + [tileImages addObject:[NSNull null]]; + + for (NSInteger u = [_tileSources count]-1; u >=0 ; --u) + { + id tileSource = [_tileSources objectAtIndex:u]; + + if (tile.zoom < tileSource.minZoom || tile.zoom > tileSource.maxZoom || ![tileSource tileSourceHasTile:tile]) + continue; + + UIImage *tileImage = [tileSource imageForTile:tile inCache:tileCache]; + + if (tileImage) + { + [tileImages replaceObjectAtIndex:u withObject:tileImage]; + + if (tileSource.isOpaque) + break; + } + } + + // composite the collected images together + // + for (UIImage *tileImage in tileImages) + { + if ( ! [tileImage isKindOfClass:[UIImage class]]) + continue; + + if (image != nil) + { + UIGraphicsBeginImageContext(image.size); + [image drawAtPoint:CGPointMake(0,0)]; + [tileImage drawAtPoint:CGPointMake(0,0)]; + + image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + } + else + { + image = tileImage; + } + } + + if (image && self.isCacheable) + [tileCache addImage:image forTile:tile withCacheKey:[self uniqueTilecacheKey]]; + + dispatch_async(dispatch_get_main_queue(), ^(void) + { + [[NSNotificationCenter defaultCenter] postNotificationName:RMTileRetrieved object:[NSNumber numberWithUnsignedLongLong:RMTileKey(tile)]]; + }); + + return image; +} + +@end diff --git a/MapView/Map/RMConfiguration.h b/MapView/Map/RMConfiguration.h index ed76f1cc4..3b7cdaf91 100644 --- a/MapView/Map/RMConfiguration.h +++ b/MapView/Map/RMConfiguration.h @@ -1,7 +1,7 @@ // // RMConfiguration.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -27,12 +27,63 @@ #import +/** The RMConfiguration object is a shared instance of the configuration for the library. */ @interface RMConfiguration : NSObject -+ (RMConfiguration *)configuration; +/** @name Accessing the Configuration */ + +/** Access the shared instance of the configuration. +* @return The shared configuration instance. */ ++ (instancetype)sharedInstance; + +/** Access the shared instance of the configuration. +* @return The shared configuration instance. */ ++ (instancetype)configuration DEPRECATED_MSG_ATTRIBUTE("use +[RMConfiguration sharedInstance]"); - (RMConfiguration *)initWithPath:(NSString *)path; +/** @name Authorizing Access */ + +/** A Mapbox API access token. Obtain an access token on your [Mapbox account page](https://www.mapbox.com/account/apps/). */ +@property (nonatomic, retain) NSString *accessToken; + +/** @name Cache Configuration */ + +/** Access the disk- and memory-based cache configuration. +* @return A dictionary containing the cache configuration. */ - (NSDictionary *)cacheConfiguration; +/** @name Using 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) + ++ (instancetype)brandedDataWithContentsOfURL:(NSURL *)aURL; + +@end + +#pragma mark - + +@interface NSString (RMUserAgent) + ++ (instancetype)brandedStringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error; + @end diff --git a/MapView/Map/RMConfiguration.m b/MapView/Map/RMConfiguration.m index 92c9f78fd..f8fb10240 100644 --- a/MapView/Map/RMConfiguration.m +++ b/MapView/Map/RMConfiguration.m @@ -1,7 +1,7 @@ // // RMConfiguration.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -29,12 +29,67 @@ 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 sharedInstance] userAgent] forHTTPHeaderField:@"User-Agent"]; + + return [NSURLConnection sendSynchronousRequest:newRequest returningResponse:response error:error]; +} + +@end + +#pragma mark - + +@implementation NSData (RMUserAgent) + ++ (instancetype)brandedDataWithContentsOfURL:(NSURL *)aURL +{ + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aURL]; + + [request setValue:[[RMConfiguration sharedInstance] userAgent] forHTTPHeaderField:@"User-Agent"]; + + return [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; +} + +@end + +#pragma mark - + +@implementation NSString (RMUserAgent) + ++ (instancetype)brandedStringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error +{ + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + [request setValue:[[RMConfiguration sharedInstance] userAgent] forHTTPHeaderField:@"User-Agent"]; + + NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:error]; + + if ( ! returnData) + return nil; + + return [[[self class] alloc] initWithData:returnData encoding:enc]; +} + +@end + +#pragma mark - + @implementation RMConfiguration { id _propertyList; } -+ (RMConfiguration *)configuration +@synthesize userAgent=_userAgent; +@synthesize accessToken=_accessToken; + ++ (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -44,11 +99,18 @@ + (RMConfiguration *)configuration return RMConfigurationSharedInstance; } ++ (instancetype)configuration +{ + return [[self class] sharedInstance]; +} + - (RMConfiguration *)initWithPath:(NSString *)path { if (!(self = [super init])) return nil; + _userAgent = [NSString stringWithFormat:@"Mapbox iOS SDK (%@/%@)", [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion]]; + if (path == nil) { _propertyList = nil; @@ -57,27 +119,27 @@ - (RMConfiguration *)initWithPath:(NSString *)path RMLog(@"reading route-me configuration from %@", path); - NSString *error = nil; + NSError *error = nil; NSData *plistData = [NSData dataWithContentsOfFile:path]; - _propertyList = [[NSPropertyListSerialization propertyListFromData:plistData - mutabilityOption:NSPropertyListImmutable - format:NULL - errorDescription:&error] retain]; + _propertyList = [NSPropertyListSerialization propertyListWithData:plistData + options:NSPropertyListImmutable + format:NULL + error:&error]; if ( ! _propertyList) { RMLog(@"problem reading route-me configuration from %@: %@", path, error); - [error release]; } return self; } -- (void)dealloc +- (NSString *)accessToken { - [_propertyList release]; _propertyList = nil; - [super dealloc]; + NSAssert(_accessToken, @"An access token is required in order to use the Mapbox API. Obtain a token on your Mapbox account page at https://www.mapbox.com/account/apps/."); + + return _accessToken; } - (NSDictionary *)cacheConfiguration diff --git a/MapView/Map/RMCoordinateGridSource.h b/MapView/Map/RMCoordinateGridSource.h index f1a68df3a..1c8bc9944 100644 --- a/MapView/Map/RMCoordinateGridSource.h +++ b/MapView/Map/RMCoordinateGridSource.h @@ -2,7 +2,7 @@ // RMCoordinateGridSource.h // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -41,13 +41,13 @@ typedef enum : short { @property (nonatomic, assign) CoordinateGridMode gridMode; -@property (nonatomic, retain) UIColor *gridColor; +@property (nonatomic, strong) UIColor *gridColor; @property (nonatomic, assign) CGFloat gridLineWidth; @property (nonatomic, assign) NSUInteger gridLabelInterval; -@property (nonatomic, retain) UIColor *minorLabelColor; -@property (nonatomic, retain) UIFont *minorLabelFont; -@property (nonatomic, retain) UIColor *majorLabelColor; -@property (nonatomic, retain) UIFont *majorLabelFont; +@property (nonatomic, strong) UIColor *minorLabelColor; +@property (nonatomic, strong) UIFont *minorLabelFont; +@property (nonatomic, strong) UIColor *majorLabelColor; +@property (nonatomic, strong) UIFont *majorLabelFont; @end diff --git a/MapView/Map/RMCoordinateGridSource.m b/MapView/Map/RMCoordinateGridSource.m index 03638276a..f80e7833e 100644 --- a/MapView/Map/RMCoordinateGridSource.m +++ b/MapView/Map/RMCoordinateGridSource.m @@ -2,7 +2,7 @@ // RMCoordinateGridSource.m // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -81,7 +81,7 @@ @implementation RMCoordinateGridSource @synthesize gridColor = _gridColor; @synthesize gridLineWidth = _gridLineWidth; @synthesize gridLabelInterval = _gridLabelInterval; -@synthesize gridMode = _labelingMode; +@synthesize gridMode = _gridMode; @synthesize minorLabelColor = _minorLabelColor; @synthesize minorLabelFont = _minorLabelFont; @synthesize majorLabelColor = _majorLabelColor; @@ -93,14 +93,16 @@ - (id)init return nil; self.minZoom = 5; - self.maxZoom = 18; + self.maxZoom = 17; + + self.opaque = NO; self.gridColor = [UIColor colorWithWhite:0.1 alpha:0.6]; self.gridLineWidth = 2.0; self.gridLabelInterval = 1; self.gridMode = GridModeGeographicDecimal; - self.minorLabelColor = self.majorLabelColor = [UIColor colorWithWhite:0.1 alpha:0.6]; + self.minorLabelColor = self.majorLabelColor = [UIColor colorWithWhite:0.1 alpha:0.7]; self.minorLabelFont = [UIFont boldSystemFontOfSize:14.0]; self.majorLabelFont = [UIFont boldSystemFontOfSize:11.0]; @@ -314,7 +316,29 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache - (NSString *)uniqueTilecacheKey { - return @"RMCoordinateGrid"; + NSString *tileCacheKey = nil; + + switch (self.gridMode) + { + case GridModeGeographic: { + tileCacheKey = @"RMCoordinateGridGeographic"; + break; + } + case GridModeGeographicDecimal: + { + tileCacheKey = @"RMCoordinateGridDecimal"; + break; + } + case GridModeUTM: { + tileCacheKey = @"RMCoordinateGridUTM"; + break; + } + } + + if ( ! tileCacheKey) + tileCacheKey = @"RMCoordinateGrid"; + + return tileCacheKey; } - (NSString *)shortName diff --git a/MapView/Map/RMDBMapSource.h b/MapView/Map/RMDBMapSource.h index 15b43140e..d75b5d9b3 100644 --- a/MapView/Map/RMDBMapSource.h +++ b/MapView/Map/RMDBMapSource.h @@ -1,7 +1,7 @@ // // RMDBMapSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMDBMapSource.m b/MapView/Map/RMDBMapSource.m index 7b426e54b..2ba869bd0 100644 --- a/MapView/Map/RMDBMapSource.m +++ b/MapView/Map/RMDBMapSource.m @@ -1,7 +1,7 @@ // // RMDBMapSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -72,8 +72,7 @@ #import "RMTileImage.h" #import "RMTileCache.h" #import "RMFractalTileProjection.h" -#import "FMDatabase.h" -#import "FMDatabaseQueue.h" +#import "FMDB.h" #pragma mark --- begin constants ---- @@ -126,9 +125,9 @@ - (id)initWithPath:(NSString *)path if (!(self = [super init])) return nil; - _uniqueTilecacheKey = [[[path lastPathComponent] stringByDeletingPathExtension] retain]; + _uniqueTilecacheKey = [[path lastPathComponent] stringByDeletingPathExtension]; - _queue = [[FMDatabaseQueue databaseQueueWithPath:path] retain]; + _queue = [FMDatabaseQueue databaseQueueWithPath:path]; if ( ! _queue) { @@ -160,7 +159,7 @@ - (id)initWithPath:(NSString *)path _center.latitude = [self getPreferenceAsFloat:kCoverageCenterLatitudeKey]; _center.longitude = [self getPreferenceAsFloat:kCoverageCenterLongitudeKey]; - RMLog(@"Tile size: %d pixel", self.tileSideLength); + RMLog(@"Tile size: %lu pixel", (unsigned long)self.tileSideLength); RMLog(@"Supported zoom range: %.0f - %.0f", self.minZoom, self.maxZoom); RMLog(@"Coverage area: (%2.6f,%2.6f) x (%2.6f,%2.6f)", _topLeft.latitude, @@ -174,13 +173,6 @@ - (id)initWithPath:(NSString *)path return self; } -- (void)dealloc -{ - [_uniqueTilecacheKey release]; _uniqueTilecacheKey = nil; - [_queue release]; _queue = nil; - [super dealloc]; -} - - (CLLocationCoordinate2D)topLeftOfCoverage { return _topLeft; @@ -203,10 +195,14 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache __block UIImage *image = nil; tile = [[self mercatorToTileProjection] normaliseTile:tile]; - image = [tileCache cachedImage:tile withCacheKey:[self uniqueTilecacheKey]]; - if (image) - return image; + if (self.isCacheable) + { + image = [tileCache cachedImage:tile withCacheKey:[self uniqueTilecacheKey]]; + + if (image) + return image; + } // get the unique key for the tile NSNumber *key = [NSNumber numberWithLongLong:RMTileKey(tile)]; @@ -220,14 +216,14 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache NSLog(@"DB error %d on line %d: %@", [db lastErrorCode], __LINE__, [db lastErrorMessage]); if ([result next]) - image = [[[UIImage alloc] initWithData:[result dataForColumnIndex:0]] autorelease]; + image = [[UIImage alloc] initWithData:[result dataForColumnIndex:0]]; else image = [RMTileImage missingTile]; [result close]; }]; - if (image) + if (image && self.isCacheable) [tileCache addImage:image forTile:tile withCacheKey:[self uniqueTilecacheKey]]; return image; diff --git a/MapView/Map/RMDatabaseCache.h b/MapView/Map/RMDatabaseCache.h index 4468b3043..60e67f237 100644 --- a/MapView/Map/RMDatabaseCache.h +++ b/MapView/Map/RMDatabaseCache.h @@ -28,18 +28,52 @@ #import #import "RMTileCache.h" +/** An RMDatabaseCache object represents disk-based caching of map tile images. This cache is meant for longer-term storage than RMMemoryCache, potentially for long periods of time, allowing completely offline use of map view. +* +* @warning The database cache is currently based on [SQLite](http://www.sqlite.org), a lightweight, cross-platform, file-based relational database system. The schema is independent of and unrelated to the [MBTiles](http://mbtiles.org) file format or the RMMBTilesSource tile source. */ @interface RMDatabaseCache : NSObject -@property (nonatomic, retain) NSString *databasePath; +/** @name Getting the Database Path */ + +/** The path to the SQLite database on disk that backs the cache. */ +@property (nonatomic, strong) NSString *databasePath; + (NSString *)dbPathUsingCacheDir:(BOOL)useCacheDir; +/** @name Initializing Database Caches */ + +/** Initializes and returns a newly allocated database cache object at the given disk path. +* @param path The path to use for the database backing. +* @return An initialized cache object or `nil` if the object couldn't be created. */ - (id)initWithDatabase:(NSString *)path; + +/** Initializes and returns a newly allocated database cache object. +* @param useCacheDir If YES, use the temporary cache space for the application, meaning that the cache files can be removed when the system deems it necessary to free up space. If NO, use the application's document storage space, meaning that the cache will not be automatically removed and will be backed up during device backups. The default value is NO. +* @return An initialized cache object or `nil` if the object couldn't be created. */ - (id)initUsingCacheDir:(BOOL)useCacheDir; +/** @name Configuring Cache Behavior */ + +/** Set the cache purge strategy to use for the database. +* @param theStrategy The cache strategy to use. */ - (void)setPurgeStrategy:(RMCachePurgeStrategy)theStrategy; + +/** Set the maximum tile count allowed in the database. +* @param theCapacity The number of tiles to allow to accumulate in the database before purging begins. */ - (void)setCapacity:(NSUInteger)theCapacity; + +/** The capacity, in number of tiles, that the database cache can hold. */ +@property (nonatomic, readonly, assign) NSUInteger capacity; + +/** Set the minimum number of tiles to purge when clearing space in the cache. +* @param thePurgeMinimum The number of tiles to delete at the time the cache is purged. */ - (void)setMinimalPurge:(NSUInteger)thePurgeMinimum; -- (void)setExpiryPeriod:(NSTimeInterval)theExpiryPeriod; // in seconds + +/** Set the expiry period for cache purging. +* @param theExpiryPeriod The amount of time to elapse before a tile should be removed from the cache. If set to zero, tile count-based purging will be used instead of time-based. */ +- (void)setExpiryPeriod:(NSTimeInterval)theExpiryPeriod; + +/** The current file size of the database cache on disk. */ +- (unsigned long long)fileSize; @end diff --git a/MapView/Map/RMDatabaseCache.m b/MapView/Map/RMDatabaseCache.m index d96b83594..c0c35e4a5 100644 --- a/MapView/Map/RMDatabaseCache.m +++ b/MapView/Map/RMDatabaseCache.m @@ -26,8 +26,7 @@ // POSSIBILITY OF SUCH DAMAGE. #import "RMDatabaseCache.h" -#import "FMDatabase.h" -#import "FMDatabaseQueue.h" +#import "FMDB.h" #import "RMTileImage.h" #import "RMTile.h" @@ -93,7 +92,7 @@ - (void)configureDBForFirstUse [_queue inDatabase:^(FMDatabase *db) { [[db executeQuery:@"PRAGMA synchronous=OFF"] close]; [[db executeQuery:@"PRAGMA journal_mode=OFF"] close]; - [[db executeQuery:@"PRAGMA cache-size=100"] close]; + [[db executeQuery:@"PRAGMA cache_size=100"] close]; [[db executeQuery:@"PRAGMA count_changes=OFF"] close]; [db executeUpdate:@"CREATE TABLE IF NOT EXISTS ZCACHE (tile_hash INTEGER NOT NULL, cache_key VARCHAR(25) NOT NULL, last_used DOUBLE NOT NULL, data BLOB NOT NULL)"]; [db executeUpdate:@"CREATE UNIQUE INDEX IF NOT EXISTS main_index ON ZCACHE(tile_hash, cache_key)"]; @@ -112,9 +111,7 @@ - (id)initWithDatabase:(NSString *)path [_writeQueue setMaxConcurrentOperationCount:1]; _writeQueueLock = [NSRecursiveLock new]; - RMLog(@"Opening database at %@", path); - - _queue = [[FMDatabaseQueue databaseQueueWithPath:path] retain]; + _queue = [FMDatabaseQueue databaseQueueWithPath:path]; if (!_queue) { @@ -122,7 +119,6 @@ - (id)initWithDatabase:(NSString *)path [[NSFileManager defaultManager] removeItemAtPath:path error:NULL]; - [self release]; return nil; } @@ -145,13 +141,11 @@ - (id)initUsingCacheDir:(BOOL)useCacheDir - (void)dealloc { - self.databasePath = nil; [_writeQueueLock lock]; - [_writeQueue release]; _writeQueue = nil; + _writeQueue = nil; [_writeQueueLock unlock]; - [_writeQueueLock release]; _writeQueueLock = nil; - [_queue release]; _queue = nil; - [super dealloc]; + _writeQueueLock = nil; + _queue = nil; } - (void)setPurgeStrategy:(RMCachePurgeStrategy)theStrategy @@ -164,6 +158,11 @@ - (void)setCapacity:(NSUInteger)theCapacity _capacity = theCapacity; } +- (NSUInteger)capacity +{ + return _capacity; +} + - (void)setMinimalPurge:(NSUInteger)theMinimalPurge { _minimalPurge = theMinimalPurge; @@ -173,7 +172,12 @@ - (void)setExpiryPeriod:(NSTimeInterval)theExpiryPeriod { _expiryPeriod = theExpiryPeriod; - srand(time(NULL)); + srand((unsigned int)time(NULL)); +} + +- (unsigned long long)fileSize +{ + return [[[NSFileManager defaultManager] attributesOfItemAtPath:self.databasePath error:nil] fileSize]; } - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey @@ -220,10 +224,11 @@ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey { BOOL result = [db executeUpdate:@"DELETE FROM ZCACHE WHERE last_used < ?", [NSDate dateWithTimeIntervalSinceNow:-_expiryPeriod]]; - if (result == NO) - RMLog(@"Error expiring cache"); + if (result) + result = [db executeUpdate:@"VACUUM"]; - [[db executeQuery:@"VACUUM"] close]; + if ( ! result) + RMLog(@"Error expiring cache"); }]; [_writeQueueLock unlock]; @@ -239,9 +244,11 @@ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey - (void)addImage:(UIImage *)image forTile:(RMTile)tile withCacheKey:(NSString *)aCacheKey { - // TODO: Converting the image here (again) is not so good... - NSData *data = UIImagePNGRepresentation(image); + [self addDiskCachedImageData:UIImagePNGRepresentation(image) forTile:tile withCacheKey:aCacheKey]; +} +- (void)addDiskCachedImageData:(NSData *)data forTile:(RMTile)tile withCacheKey:(NSString *)aCacheKey +{ if (_capacity != 0) { NSUInteger tilesInDb = [self count]; @@ -301,7 +308,7 @@ - (NSUInteger)countTiles [_queue inDatabase:^(FMDatabase *db) { - FMResultSet *results = [db executeQuery:@"SELECT COUNT(tile_hash) FROM ZCACHE"]; + FMResultSet *results = [db executeQuery:@"SELECT COUNT(*) FROM ZCACHE"]; if ([results next]) count = [results intForColumnIndex:0]; @@ -318,18 +325,19 @@ - (NSUInteger)countTiles - (void)purgeTiles:(NSUInteger)count { - RMLog(@"purging %u old tiles from the db cache", count); + RMLog(@"purging %lu old tiles from the db cache", (unsigned long)count); [_writeQueueLock lock]; [_queue inDatabase:^(FMDatabase *db) { - BOOL result = [db executeUpdate:@"DELETE FROM ZCACHE WHERE tile_hash IN (SELECT tile_hash FROM ZCACHE ORDER BY last_used LIMIT ?)", [NSNumber numberWithUnsignedInt:count]]; + BOOL result = [db executeUpdate:@"DELETE FROM ZCACHE WHERE tile_hash IN (SELECT tile_hash FROM ZCACHE ORDER BY last_used LIMIT ?)", [NSNumber numberWithUnsignedLongLong:count]]; - if (result == NO) - RMLog(@"Error purging cache"); + if (result) + result = [db executeUpdate:@"VACUUM"]; - [[db executeQuery:@"VACUUM"] close]; + if ( ! result) + RMLog(@"Error purging cache"); }]; [_writeQueueLock unlock]; @@ -348,10 +356,35 @@ - (void)removeAllCachedImages { BOOL result = [db executeUpdate:@"DELETE FROM ZCACHE"]; - if (result == NO) + if (result) + result = [db executeUpdate:@"VACUUM"]; + + if ( ! result) RMLog(@"Error purging cache"); + }]; - [[db executeQuery:@"VACUUM"] close]; + [_writeQueueLock unlock]; + + _tileCount = [self countTiles]; + }]; +} + +- (void)removeAllCachedImagesForCacheKey:(NSString *)cacheKey +{ + RMLog(@"removing tiles for key '%@' from the db cache", cacheKey); + + [_writeQueue addOperationWithBlock:^{ + [_writeQueueLock lock]; + + [_queue inDatabase:^(FMDatabase *db) + { + BOOL result = [db executeUpdate:@"DELETE FROM ZCACHE WHERE cache_key = ?", cacheKey]; + + if (result) + result = [db executeUpdate:@"VACUUM"]; + + if ( ! result) + RMLog(@"Error purging cache"); }]; [_writeQueueLock unlock]; diff --git a/MapView/Map/RMFoundation.c b/MapView/Map/RMFoundation.c index 7600d7b2e..781bd7c05 100644 --- a/MapView/Map/RMFoundation.c +++ b/MapView/Map/RMFoundation.c @@ -1,7 +1,7 @@ // // RMFoundation.c // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ bool RMProjectedPointEqualToProjectedPoint(RMProjectedPoint point1, RMProjectedPoint point2) { - return point1.x == point2.x && point2.y == point2.y; + return point1.x == point2.x && point1.y == point2.y; } bool RMProjectedRectIntersectsProjectedRect(RMProjectedRect rect1, RMProjectedRect rect2) @@ -178,6 +178,31 @@ RMProjectedRect RMProjectedRectUnion(RMProjectedRect rect1, RMProjectedRect rect return RMProjectedRectMake(minX, minY, maxX - minX, maxY - minY); } +// Rect intersection +RMProjectedRect RMProjectedRectIntersection(RMProjectedRect rect1, RMProjectedRect rect2) +{ + bool rect1IsZero = RMProjectedRectIsZero(rect1); + bool rect2IsZero = RMProjectedRectIsZero(rect2); + + if (rect1IsZero) + return (rect2IsZero ? RMProjectedRectZero() : rect2); + + if (rect2IsZero) + return rect1; + + if ( ! RMProjectedRectIntersectsProjectedRect(rect1, rect2)) + return RMProjectedRectZero(); + + double minX, maxX, minY, maxY; + + minX = RMMAX(rect1.origin.x, rect2.origin.x); + minY = RMMAX(rect1.origin.y, rect2.origin.y); + maxX = RMMIN(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width); + maxY = RMMIN(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height); + + return RMProjectedRectMake(minX, minY, maxX - minX, maxY - minY); +} + // apparently, this doesn't work well with coordinates on a sphere, but it might be appropriate for a quick estimation double RMEuclideanDistanceBetweenProjectedPoints(RMProjectedPoint point1, RMProjectedPoint point2) { diff --git a/MapView/Map/RMFoundation.h b/MapView/Map/RMFoundation.h index d683efb67..ee548d939 100644 --- a/MapView/Map/RMFoundation.h +++ b/MapView/Map/RMFoundation.h @@ -1,7 +1,7 @@ // // RMFoundation.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -84,6 +84,9 @@ bool RMProjectedSizeContainsProjectedSize(RMProjectedSize size1, RMProjectedSize // Union of two rectangles RMProjectedRect RMProjectedRectUnion(RMProjectedRect rect1, RMProjectedRect rect2); +// Rect intersection +RMProjectedRect RMProjectedRectIntersection(RMProjectedRect rect1, RMProjectedRect rect2); + RMProjectedPoint RMProjectedPointMake(double x, double y); RMProjectedRect RMProjectedRectMake(double x, double y, double width, double height); RMProjectedSize RMProjectedSizeMake(double width, double heigth); diff --git a/MapView/Map/RMFractalTileProjection.h b/MapView/Map/RMFractalTileProjection.h index 3da9e04dd..2863f859d 100644 --- a/MapView/Map/RMFractalTileProjection.h +++ b/MapView/Map/RMFractalTileProjection.h @@ -1,7 +1,7 @@ // // RMFractalTileProjection.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMFractalTileProjection.m b/MapView/Map/RMFractalTileProjection.m index 0163def1a..494cb2bfd 100644 --- a/MapView/Map/RMFractalTileProjection.m +++ b/MapView/Map/RMFractalTileProjection.m @@ -1,7 +1,7 @@ // // RMFractalTileProjection.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMGenericMapSource.h b/MapView/Map/RMGenericMapSource.h index a21c2be7f..f6eb379e1 100644 --- a/MapView/Map/RMGenericMapSource.h +++ b/MapView/Map/RMGenericMapSource.h @@ -1,7 +1,7 @@ // // RMGenericMapSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMGenericMapSource.m b/MapView/Map/RMGenericMapSource.m index 378293485..d2ea02ac7 100644 --- a/MapView/Map/RMGenericMapSource.m +++ b/MapView/Map/RMGenericMapSource.m @@ -1,7 +1,7 @@ // // RMGenericMapSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -40,8 +40,8 @@ - (id)initWithHost:(NSString *)host tileCacheKey:(NSString *)tileCacheKey minZoo NSAssert(host != nil, @"Empty host parameter not allowed"); NSAssert(tileCacheKey != nil, @"Empty tileCacheKey paramter not allowed"); - _host = [host retain]; - _uniqueTilecacheKey = [tileCacheKey retain]; + _host = host; + _uniqueTilecacheKey = tileCacheKey; self.minZoom = minZoom; self.maxZoom = maxZoom; @@ -49,13 +49,6 @@ - (id)initWithHost:(NSString *)host tileCacheKey:(NSString *)tileCacheKey minZoo return self; } -- (void)dealloc -{ - [_uniqueTilecacheKey release]; _uniqueTilecacheKey = nil; - [_host release]; _host = nil; - [super dealloc]; -} - - (NSURL *)URLForTile:(RMTile)tile { NSAssert4(((tile.zoom >= self.minZoom) && (tile.zoom <= self.maxZoom)), diff --git a/MapView/Map/RMGlobalConstants.h b/MapView/Map/RMGlobalConstants.h index 9bf5e089f..7fbf3f232 100644 --- a/MapView/Map/RMGlobalConstants.h +++ b/MapView/Map/RMGlobalConstants.h @@ -1,7 +1,7 @@ // // RMGlobalConstants.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMGreatCircleAnnotation.h b/MapView/Map/RMGreatCircleAnnotation.h new file mode 100644 index 000000000..0a1f7abd8 --- /dev/null +++ b/MapView/Map/RMGreatCircleAnnotation.h @@ -0,0 +1,47 @@ +// +// RMGreatCircleAnnotation.h +// MapView +// +// Copyright (c) 2008-2013, 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. + +#import "RMShapeAnnotation.h" + +/** An RMGreatCircleAnnotation class represents a line shape that traces the shortest path along the surface of the Earth. You specify a great circle (also known as a geodesic polyline) using a pair of points. When displayed on a two-dimensional map view, the line segment between the two points may appear curved. */ +@interface RMGreatCircleAnnotation : RMShapeAnnotation + +/** Initialize a great circle annotation using the specified coordinates. +* @param aMapView The map view on which to place the annotation. +* @param coordinate1 The starting coordinate. +* @param coordinate2 The ending coordinate. +* @return An initialized great circle annotation object, or `nil` if an annotation was unable to be initialized. */ +- (id)initWithMapView:(RMMapView *)aMapView coordinate1:(CLLocationCoordinate2D)coordinate1 coordinate2:(CLLocationCoordinate2D)coordinate2; + +/** The starting coordinate of the annotation. */ +@property (nonatomic, readonly, assign) CLLocationCoordinate2D coordinate1; + +/** The ending coordinate of the annotation. */ +@property (nonatomic, readonly, assign) CLLocationCoordinate2D coordinate2; + +@end diff --git a/MapView/Map/RMGreatCircleAnnotation.m b/MapView/Map/RMGreatCircleAnnotation.m new file mode 100644 index 000000000..fa6e1a046 --- /dev/null +++ b/MapView/Map/RMGreatCircleAnnotation.m @@ -0,0 +1,119 @@ +// +// RMGreatCircleAnnotation.m +// MapView +// +// Copyright (c) 2008-2013, 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. + +#import "RMGreatCircleAnnotation.h" + +#import "RMShape.h" + +@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; + + _coordinate1 = coordinate1; + _coordinate2 = coordinate2; + + return self; +} + +- (RMMapLayer *)layer +{ + if ( ! [super layer]) + { + RMShape *shape = [[RMShape alloc] initWithView:self.mapView]; + + [shape performBatchOperations:^(RMShape *aShape) + { + // based on implementation at http://stackoverflow.com/questions/6104517/drawing-great-circle-overlay-lines-on-an-mkmapview + // + double lat1 = self.coordinate1.latitude; + double lon1 = self.coordinate1.longitude; + double lat2 = self.coordinate2.latitude; + double lon2 = self.coordinate2.longitude; + lat1 = lat1 * (M_PI/180); + lon1 = lon1 * (M_PI/180); + lat2 = lat2 * (M_PI/180); + lon2 = lon2 * (M_PI/180); + double d = 2 * asin( sqrt(pow(( sin( (lat1-lat2)/2) ), 2) + cos(lat1) * cos(lat2) * pow(( sin( (lon1-lon2)/2) ), 2))); + int numsegs = 100; + NSMutableArray *coords = [NSMutableArray arrayWithCapacity:numsegs]; + double f = 0.0; + for(int i=1; i<=numsegs; i++) + { + f += 1.0 / (float)numsegs; + double A=sin((1-f)*d)/sin(d); + double B=sin(f*d)/sin(d); + double x = A*cos(lat1) * cos(lon1) + B * cos(lat2) * cos(lon2); + double y = A*cos(lat1) * sin(lon1) + B * cos(lat2) * sin(lon2); + double z = A*sin(lat1) + B*sin(lat2); + double latr=atan2(z, sqrt(pow(x, 2) + pow(y, 2) )); + double lonr=atan2(y, x); + double lat = latr * (180/M_PI); + double lon = lonr * (180/M_PI); + [coords addObject:[[CLLocation alloc] initWithLatitude:lat longitude:lon]]; + } + CLLocationCoordinate2D prevCoord; + NSMutableArray *coords2 = [NSMutableArray array]; + for(int i=0; i -180 && prevCoord.longitude < 0 + && coord.longitude > 170 && coord.longitude < 180 && coord.longitude > 0) + { + [coords2 addObjectsFromArray:[coords subarrayWithRange:NSMakeRange(i, [coords count] - i)]]; + [coords removeObjectsInRange:NSMakeRange(i, [coords count] - i)]; + break; + } + prevCoord = coord; + } + + [aShape moveToCoordinate:((CLLocation *)coords[0]).coordinate]; + + for (int i = 1; i < [coords count]; i++) + [aShape addLineToCoordinate:((CLLocation *)coords[i]).coordinate]; + + if ([coords2 count]) + { + [aShape moveToCoordinate:((CLLocation *)coords2[0]).coordinate]; + + for (int j = 1; j < [coords2 count]; j++) + [aShape addLineToCoordinate:((CLLocation *)coords2[j]).coordinate]; + } + }]; + + super.layer = shape; + } + + return [super layer]; +} + +@end diff --git a/MapView/Map/RMInteractiveSource.h b/MapView/Map/RMInteractiveSource.h new file mode 100644 index 000000000..6eb57fe93 --- /dev/null +++ b/MapView/Map/RMInteractiveSource.h @@ -0,0 +1,117 @@ +// +// RMInteractiveSource.h +// +// Created by Justin R. Miller on 6/22/11. +// Copyright 2012-2013 Mapbox. +// 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. +// +// * Neither the name of Mapbox, nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// 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. +// +// Based on the UTFGrid specification: https://github.com/mapbox/utfgrid-spec +// + +#import "RMMapView.h" +#import "RMMBTilesSource.h" +#import "RMMapboxSource.h" + +typedef enum : NSUInteger { + RMInteractiveSourceOutputTypeTeaser = 0, + RMInteractiveSourceOutputTypeFull = 1, +} RMInteractiveSourceOutputType; + +/** Developers can import RMInteractiveSource in order to enable embedded interactivity in their RMMapView, RMMBTilesSource, and RMMapboxSource objects. Interactivity is based on the UTFGrid specification, which is a space-efficient way to encode many arbitrary values for pixel coordinates at every zoom level, allowing later retrieval based on user events on those coordinates. For example, the user touching a pixel in Spain could trigger retrieval of Spain's flag image for display. +* +* Interactive map views adopt the RMInteractiveMapView protocol. +* +* Interactivity currently supports two types of output, teaser and full. These two types are ideal for master/detail interfaces or for showing a MapKit-style detail-toggling point callout. */ +@protocol RMInteractiveMapView + +@required + +/** @name Querying Interactivity */ + +/** Returns YES if a map view supports interactivity features given its current tile sources. */ +- (BOOL)supportsInteractivity; + +/** Returns the HTML-formatted output for a given point on a given map view. +* @param outputType The type of feature info desired. +* @param point A point in the map view. +* @return The formatted feature output. */ +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point; + +@end + +#pragma mark - + +@interface RMMapView (RMInteractiveSource) + +- (BOOL)supportsInteractivity; +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point; + +@end + +#pragma mark - + +/** Developers can import RMInteractiveSource in order to enable embedded interactivity in their RMMapView, RMMBTilesSource, and RMMapboxSource objects. Interactivity is based on the [UTFGrid specification](https://github.com/mapbox/utfgrid-spec) and is best described by [this web demo](https://mapbox.com/demo/visiblemap/). +* +* Interactive tile sources adopt the RMInteractiveSource protocol. +* +* Interactivity currently supports two types of output, teaser and full. These two types are ideal for master/detail interfaces or for showing a MapKit-style detail-toggling point callout. */ +@protocol RMInteractiveSource + +@required + +/** @name Querying Interactivity */ + +/** Returns YES if a tile source supports interactivity features. */ +- (BOOL)supportsInteractivity; + +/** Returns the HTML-formatted output for a given point on a given map view, considering the currently active interactive tile source. +* @param outputType The type of feature info desired. +* @param point A point in the map view. +* @param mapView The map view being interacted with. +* @return The formatted feature output. */ +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point inMapView:(RMMapView *)mapView; + +@end + +#pragma mark - + +@interface RMMBTilesSource (RMInteractiveSource) + +- (BOOL)supportsInteractivity; +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point inMapView:(RMMapView *)mapView; + +@end + +#pragma mark - + +@interface RMMapboxSource (RMInteractiveSource) + +- (BOOL)supportsInteractivity; +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point inMapView:(RMMapView *)mapView; + +@end diff --git a/MapView/Map/RMInteractiveSource.m b/MapView/Map/RMInteractiveSource.m new file mode 100644 index 000000000..1efd9cf6b --- /dev/null +++ b/MapView/Map/RMInteractiveSource.m @@ -0,0 +1,614 @@ +// +// RMInteractiveSource.m +// +// Created by Justin R. Miller on 6/22/11. +// Copyright 2012-2013 Mapbox. +// 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. +// +// * Neither the name of Mapbox, nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// 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. +// + +#import "RMInteractiveSource.h" + +#import "RMConfiguration.h" + +#import "FMDB.h" + +#import "GRMustache.h" + +#import +#import + +#include "zlib.h" + +@protocol RMInteractiveSourcePrivate + +// This is the stuff that interactive tile sources need to do, but +// that you don't interact with in a public way. + +@required + +- (NSDictionary *)interactivityDictionaryForPoint:(CGPoint)point inMapView:(RMMapView *)mapView; +- (NSString *)interactivityFormatterTemplate; + +@end + +#pragma mark RMMapView + +@interface RMMapView (RMInteractiveSourcePrivate) + +- (id )interactiveTileSource; +- (NSDictionary *)interactivityDictionaryForPoint:(CGPoint)point; +- (NSString *)interactivityFormatterTemplate; + +@end + +@implementation RMMapView (RMInteractiveSource) + +- (id )interactiveTileSource +{ + id interactiveTileSource = nil; + + // currently, we iterate top-down and return the first interactive source + // + for (id source in [[self.tileSources reverseObjectEnumerator] allObjects]) + { + if (([source isKindOfClass:[RMMBTilesSource class]] || [source isKindOfClass:[RMMapboxSource class]]) && + [source conformsToProtocol:@protocol(RMInteractiveSource)] && + [(id )source supportsInteractivity]) + { + interactiveTileSource = (id )source; + + break; + } + } + + return interactiveTileSource; +} + +- (BOOL)supportsInteractivity +{ + return ([self interactiveTileSource] != nil); +} + +- (NSDictionary *)interactivityDictionaryForPoint:(CGPoint)point +{ + return [(id )[self interactiveTileSource] interactivityDictionaryForPoint:point inMapView:self]; +} + +- (NSString *)interactivityFormatterTemplate +{ + return [(id )[self interactiveTileSource] interactivityFormatterTemplate]; +} + +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point +{ + return [(id )[self interactiveTileSource] formattedOutputOfType:outputType forPoint:point inMapView:self]; +} + +@end + +#pragma mark - Utilities + +RMTilePoint RMInteractiveSourceNormalizedTilePointForMapView(CGPoint point, RMMapView *mapView); + +RMTilePoint RMInteractiveSourceNormalizedTilePointForMapView(CGPoint point, RMMapView *mapView) +{ + // This function figures out which RMTile a given point falls on and where + // in that tile the point is for a given map view. This is required because + // tiles get stitched together on render and touches are no longer + // correlated to tiles, unlike on websites where the tile is still an + // actual tile image. + + // get map scroll view + // + UIScrollView *scrollView = [mapView valueForKey:@"mapScrollView"]; + + // get closest whole zoom + // + int tileZoom = (int)(roundf(mapView.zoom)); + + // get displayed fractional zoom factor + // + float factor = scrollView.contentSize.width / (powf(2, tileZoom) * 256); + + // get point in even-zoom space + // + float evenX = (scrollView.contentOffset.x + point.x) / factor; + float evenY = (scrollView.contentOffset.y + point.y) / factor; + + // normalize for the tile touched + // + int normalizedX = (int)evenX % 256; + int normalizedY = (int)evenY % 256; + + // determine lat & lon of touch + // + CLLocationCoordinate2D touchLocation = [mapView pixelToCoordinate:point]; + + // use lat & lon to determine tile (per http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames) + // + int tileX = (int)(floor((touchLocation.longitude + 180.0) / 360.0 * pow(2.0, tileZoom))); + int tileY = (int)(floor((1.0 - log(tan(touchLocation.latitude * M_PI / 180.0) + 1.0 / \ + cos(touchLocation.latitude * M_PI / 180.0)) / M_PI) / 2.0 * pow(2.0, tileZoom))); + + // flip y for TMS and all MBTiles + // + id interactiveSource = [mapView interactiveTileSource]; + + if (([interactiveSource isKindOfClass:[RMMapboxSource class]] && [((RMMapboxSource *)interactiveSource).infoDictionary objectForKey:@"scheme"] && [[((RMMapboxSource *)interactiveSource).infoDictionary objectForKey:@"scheme"] isEqual:@"tms"]) || [interactiveSource isKindOfClass:[RMMBTilesSource class]]) + { + tileY = pow(2.0, tileZoom) - tileY - 1.0; + } + + RMTile tile = { + .zoom = tileZoom, + .x = tileX, + .y = tileY, + }; + + RMTilePoint tilePoint; + + tilePoint.tile = tile; + tilePoint.offset = CGPointMake(normalizedX, normalizedY); + + return tilePoint; +} + +@interface RMInteractiveSource : NSObject + +// These are routines common to all interactive tile source types, +// made handy as class methods for convenience. + ++ (NSString *)keyNameForPoint:(CGPoint)point inGrid:(NSDictionary *)grid; ++ (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)type forPoint:(CGPoint)point inMapView:(RMMapView *)mapView; + +@end + +@implementation RMInteractiveSource + ++ (NSString *)keyNameForPoint:(CGPoint)point inGrid:(NSDictionary *)grid +{ + NSString *keyName = nil; + + if ([grid objectForKey:@"grid"] && [grid objectForKey:@"keys"]) + { + NSArray *rows = [grid objectForKey:@"grid"]; + NSArray *keys = [grid objectForKey:@"keys"]; + + if (rows && [rows isKindOfClass:[NSArray class]] && keys && [keys isKindOfClass:[NSArray class]]) + { + if ([rows count] > 0) + { + // get grid coordinates per https://github.com/mapbox/mbtiles-spec/blob/master/1.1/utfgrid.md + // + int factor = 256 / [rows count]; + int row = point.y / factor; + int col = point.x / factor; + + if (row < [rows count]) + { + NSString *line = [rows objectAtIndex:row]; + + if (col < [line length]) + { + unichar theChar = [line characterAtIndex:col]; + unsigned short decoded = theChar; + + if (decoded >= 93) + decoded--; + + if (decoded >=35) + decoded--; + + decoded = decoded - 32; + + if (decoded < [keys count]) + keyName = [keys objectAtIndex:decoded]; + } + } + } + } + } + + return keyName; +} + ++ (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point inMapView:(RMMapView *)mapView +{ + NSString *formattedOutput = nil; + + id source = [mapView interactiveTileSource]; + + NSDictionary *interactivityDictionary = [(id )source interactivityDictionaryForPoint:point inMapView:mapView]; + + if (interactivityDictionary) + { + // As of UTFGrid 1.2, JavaScript formatters are no longer supported. We + // prefer Mustache-based templating instead for security reasons. + // + // More on Mustache: http://mustache.github.com + // + NSString *formatterTemplate = [(id )source interactivityFormatterTemplate]; + + if (formatterTemplate) + { + NSMutableDictionary *infoObject = [NSJSONSerialization JSONObjectWithData:[[interactivityDictionary objectForKey:@"keyJSON"] dataUsingEncoding:NSUTF8StringEncoding] + options:NSJSONReadingMutableContainers + error:nil]; + +#ifdef DEBUG + [GRMustache preventNSUndefinedKeyExceptionAttack]; +#endif + + switch (outputType) + { + case RMInteractiveSourceOutputTypeTeaser: + { + [infoObject setValue:[NSNumber numberWithBool:YES] forKey:@"__teaser__"]; + + formattedOutput = [GRMustacheTemplate renderObject:infoObject fromString:formatterTemplate error:NULL]; + + break; + } + case RMInteractiveSourceOutputTypeFull: + default: + { + [infoObject setValue:[NSNumber numberWithBool:YES] forKey:@"__full__"]; + + formattedOutput = [GRMustacheTemplate renderObject:infoObject fromString:formatterTemplate error:NULL]; + + break; + } + } + } + } + + return formattedOutput; +} + +@end + +// This is a category for dealing with gzip-deflated data +// over the wire or in MBTiles sources. + +@interface NSData (RMInteractiveSource) + +- (NSData *)gzipInflate; + +@end + +@implementation NSData (RMInteractiveSource) + +- (NSData *)gzipInflate +{ + // from http://cocoadev.com/index.pl?NSDataCategory + // + if ([self length] == 0) return self; + + NSUInteger full_length = [self length]; + NSUInteger half_length = [self length] / 2; + + NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; + BOOL done = NO; + int status; + + z_stream strm; + strm.next_in = (Bytef *)[self bytes]; + strm.avail_in = (unsigned int)[self length]; + strm.total_out = 0; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + + if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; + while (!done) + { + // Make sure we have enough room and reset the lengths. + if (strm.total_out >= [decompressed length]) + [decompressed increaseLengthBy: half_length]; + strm.next_out = [decompressed mutableBytes] + strm.total_out; + strm.avail_out = (uInt)([decompressed length] - strm.total_out); + + // Inflate another chunk. + status = inflate (&strm, Z_SYNC_FLUSH); + if (status == Z_STREAM_END) done = YES; + else if (status != Z_OK) break; + } + if (inflateEnd (&strm) != Z_OK) return nil; + + // Set real length. + if (done) + { + [decompressed setLength: strm.total_out]; + return [NSData dataWithData: decompressed]; + } + else return nil; +} + +@end + +#pragma mark - MBTiles + +@interface RMMBTilesSource (RMInteractiveSourcePrivate) + +- (NSDictionary *)interactivityDictionaryForPoint:(CGPoint)point inMapView:(RMMapView *)mapView; +- (NSString *)interactivityFormatterTemplate; + +@end + +@implementation RMMBTilesSource (RMInteractiveSource) + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@: %@, zooms %i-%i, %@", + [self class], + [self shortName], + (int)[self minZoom], + (int)[self maxZoom], + ([self supportsInteractivity] ? @"supports interactivity" : @"no interactivity")]; +} + +- (BOOL)supportsInteractivity +{ + if ([self interactivityFormatterTemplate]) + return YES; + + return NO; +} + +- (NSDictionary *)interactivityDictionaryForPoint:(CGPoint)point inMapView:(RMMapView *)mapView; +{ + RMTilePoint tilePoint = RMInteractiveSourceNormalizedTilePointForMapView(point, mapView); + + __block NSData *gridData = nil; + + [queue inDatabase:^(FMDatabase *db) + { + FMResultSet *results = [db executeQuery:@"select grid from grids where zoom_level = ? and tile_column = ? and tile_row = ?", + [NSNumber numberWithShort:tilePoint.tile.zoom], + [NSNumber numberWithUnsignedInt:tilePoint.tile.x], + [NSNumber numberWithUnsignedInt:tilePoint.tile.y]]; + + if ( ! [db hadError]) + { + [results next]; + + if ([results hasAnotherRow]) + gridData = [results dataForColumnIndex:0]; + } + + [results close]; + }]; + + if (gridData) + { + NSData *inflatedData = [gridData gzipInflate]; + NSString *gridString = [[NSString alloc] initWithData:inflatedData encoding:NSUTF8StringEncoding]; + + id grid = [NSJSONSerialization JSONObjectWithData:[gridString dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:nil]; + + if (grid && [grid isKindOfClass:[NSDictionary class]]) + { + NSString *keyName = [RMInteractiveSource keyNameForPoint:tilePoint.offset inGrid:grid]; + + if (keyName) + { + // get JSON for this grid point + // + __block NSString *jsonString = nil; + + [queue inDatabase:^(FMDatabase *db) + { + FMResultSet *results = [db executeQuery:@"select key_json from grid_data where zoom_level = ? and tile_column = ? and tile_row = ? and key_name = ?", + [NSNumber numberWithShort:tilePoint.tile.zoom], + [NSNumber numberWithShort:tilePoint.tile.x], + [NSNumber numberWithShort:tilePoint.tile.y], + keyName]; + + if ( ! [db hadError]) + { + [results next]; + + if ([results hasAnotherRow]) + jsonString = [results stringForColumn:@"key_json"]; + } + + [results close]; + }]; + + if (jsonString) + { + return [NSDictionary dictionaryWithObjectsAndKeys:keyName, @"keyName", + jsonString, @"keyJSON", + nil]; + } + } + } + } + + return nil; +} + +- (NSString *)interactivityFormatterTemplate +{ + __block NSString *template = nil; + + [queue inDatabase:^(FMDatabase *db) + { + FMResultSet *results = [db executeQuery:@"select value from metadata where name = 'template'"]; + + if ( ! [db hadError]) + { + [results next]; + + if ([results hasAnotherRow]) + template = [results stringForColumn:@"value"]; + } + + [results close]; + }]; + + return ([template length] ? template : nil); +} + +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point inMapView:(RMMapView *)mapView +{ + if ([self supportsInteractivity]) + return [RMInteractiveSource formattedOutputOfType:outputType forPoint:point inMapView:mapView]; + + return nil; +} + +@end + +#pragma mark - Mapbox + +@interface RMMapboxSource (RMInteractiveSourcePrivate) + +- (NSDictionary *)interactivityDictionaryForPoint:(CGPoint)point inMapView:(RMMapView *)mapView; +- (NSString *)interactivityFormatterTemplate; + +@end + +@implementation RMMapboxSource (RMInteractiveSource) + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@: %@, zooms %i-%i, %@", + [self class], + [self shortName], + (int)[self minZoom], + (int)[self maxZoom], + ([self supportsInteractivity] ? @"supports interactivity" : @"no interactivity")]; +} + +- (BOOL)supportsInteractivity +{ + if ([self interactivityFormatterTemplate]) + return YES; + + return NO; +} + +- (NSDictionary *)interactivityDictionaryForPoint:(CGPoint)point inMapView:(RMMapView *)mapView; +{ + NSString *gridURLString = nil; + + if ([self.infoDictionary objectForKey:@"grids"] && [[self.infoDictionary objectForKey:@"grids"] isKindOfClass:[NSArray class]]) + gridURLString = [[self.infoDictionary objectForKey:@"grids"] objectAtIndex:0]; + else + gridURLString = [self.infoDictionary objectForKey:@"gridURL"]; + + if ([gridURLString length]) + { + RMTilePoint tilePoint = RMInteractiveSourceNormalizedTilePointForMapView(point, mapView); + + NSInteger zoom = tilePoint.tile.zoom; + NSInteger x = tilePoint.tile.x; + NSInteger y = tilePoint.tile.y; + + gridURLString = [gridURLString stringByReplacingOccurrencesOfString:@"{z}" withString:[[NSNumber numberWithInteger:zoom] stringValue]]; + gridURLString = [gridURLString stringByReplacingOccurrencesOfString:@"{x}" withString:[[NSNumber numberWithInteger:x] stringValue]]; + gridURLString = [gridURLString stringByReplacingOccurrencesOfString:@"{y}" withString:[[NSNumber numberWithInteger:y] stringValue]]; + + // ensure JSONP format + // + if (NSEqualRanges([gridURLString rangeOfString:@"callback=grid"], NSMakeRange(NSNotFound, 0))) + { + if ([[NSURL URLWithString:gridURLString] query]) + { + gridURLString = [gridURLString stringByAppendingString:@"&callback=grid"]; + } + else + { + gridURLString = [gridURLString stringByAppendingString:@"?callback=grid"]; + } + } + + // get the data for this tile + // + NSData *gridData = [NSData brandedDataWithContentsOfURL:[NSURL URLWithString:gridURLString]]; + + if (gridData) + { + NSMutableString *gridString = [[NSMutableString alloc] initWithData:gridData encoding:NSUTF8StringEncoding]; + + // remove JSONP 'grid(' and ');' bits + // + if ([gridString hasPrefix:@"grid("]) + { + [gridString replaceCharactersInRange:NSMakeRange(0, 5) withString:@""]; + [gridString replaceCharactersInRange:NSMakeRange([gridString length] - 2, 2) withString:@""]; + } + + id grid = [NSJSONSerialization JSONObjectWithData:[gridString dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:nil]; + + if (grid && [grid isKindOfClass:[NSDictionary class]]) + { + NSString *keyName = [RMInteractiveSource keyNameForPoint:tilePoint.offset inGrid:grid]; + + if (keyName) + { + NSDictionary *data = [grid objectForKey:@"data"]; + + if (data && [data objectForKey:keyName]) + { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[data objectForKey:keyName] options:0 error:nil]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + + return [NSDictionary dictionaryWithObjectsAndKeys:keyName, @"keyName", + jsonString, @"keyJSON", + nil]; + } + } + } + } + } + + return nil; +} + +- (NSString *)interactivityFormatterTemplate +{ + if ([self.infoDictionary objectForKey:@"template"] && [[self.infoDictionary objectForKey:@"template"] length]) + return [self.infoDictionary objectForKey:@"template"]; + + return nil; +} + +- (NSString *)formattedOutputOfType:(RMInteractiveSourceOutputType)outputType forPoint:(CGPoint)point inMapView:(RMMapView *)mapView +{ + if ([self supportsInteractivity]) + return [RMInteractiveSource formattedOutputOfType:outputType forPoint:point inMapView:mapView]; + + return nil; +} + +@end diff --git a/MapView/UnitTesting/RMFoundationTests.h b/MapView/Map/RMLoadingTileView.h similarity index 88% rename from MapView/UnitTesting/RMFoundationTests.h rename to MapView/Map/RMLoadingTileView.h index bc2a538dc..9e94b3b6a 100644 --- a/MapView/UnitTesting/RMFoundationTests.h +++ b/MapView/Map/RMLoadingTileView.h @@ -1,7 +1,8 @@ // -// RMFoundationTests.h -// -// Copyright (c) 2008-2011, Route-Me Contributors +// RMTileLoadingView.h +// MapView +// +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -25,13 +26,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. - -#import #import +@interface RMLoadingTileView : UIScrollView -@interface RMFoundationTests : SenTestCase { - -} +@property (nonatomic, assign) BOOL mapZooming; @end diff --git a/MapView/Map/RMLoadingTileView.m b/MapView/Map/RMLoadingTileView.m new file mode 100644 index 000000000..380b1761e --- /dev/null +++ b/MapView/Map/RMLoadingTileView.m @@ -0,0 +1,102 @@ +// +// RMTileLoadingView.m +// MapView +// +// Copyright (c) 2008-2013, 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. + +#import "RMLoadingTileView.h" + +#import "RMMapView.h" + +@implementation RMLoadingTileView +{ + UIView *_contentView; +} + +@synthesize mapZooming=_mapZooming; + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + + if (self) + { + _contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width * 3, frame.size.height * 3)]; + [self addSubview:_contentView]; + + [self setMapZooming:NO]; + + self.userInteractionEnabled = NO; + self.showsHorizontalScrollIndicator = NO; + self.showsVerticalScrollIndicator = NO; + } + + return self; +} + +- (void)setMapZooming:(BOOL)zooming +{ + if (zooming) + { + _contentView.backgroundColor = [UIColor clearColor]; + } + else + { + _contentView.backgroundColor = [UIColor colorWithPatternImage:[RMMapView resourceImageNamed:(RMPostVersion6 ? @"LoadingTile6.png" : @"LoadingTile.png")]]; + + _contentView.frame = CGRectMake(0, 0, self.frame.size.width * 3, self.frame.size.height * 3); + self.contentSize = _contentView.bounds.size; + self.contentOffset = CGPointMake(self.frame.size.width, self.frame.size.height); + } + + _mapZooming = zooming; +} + +- (void)setContentOffset:(CGPoint)contentOffset +{ + CGPoint newContentOffset = contentOffset; + + if (newContentOffset.x > 2 * self.contentSize.width / 3) + { + newContentOffset.x = self.bounds.size.width; + } + else if (newContentOffset.x < self.contentSize.width / 3) + { + newContentOffset.x = self.bounds.size.width * 2; + } + + if (newContentOffset.y > 2 * self.contentSize.height / 3) + { + newContentOffset.y = self.bounds.size.height; + } + else if (newContentOffset.y < self.contentSize.height / 3) + { + newContentOffset.y = self.bounds.size.height * 2; + } + + [super setContentOffset:newContentOffset]; +} + +@end diff --git a/MapView/Map/RMMBTilesSource.h b/MapView/Map/RMMBTilesSource.h index 21a2feb87..29ca39ed1 100644 --- a/MapView/Map/RMMBTilesSource.h +++ b/MapView/Map/RMMBTilesSource.h @@ -2,7 +2,7 @@ // RMMBTilesSource.h // // Created by Justin R. Miller on 6/18/10. -// Copyright 2010, Code Sorcery Workshop, LLC and Development Seed, Inc. +// Copyright 2012-2013 Mapbox. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -15,10 +15,9 @@ // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // -// * Neither the names of Code Sorcery Workshop, LLC or Development Seed, -// Inc., nor the names of its contributors may be used to endorse or -// promote products derived from this software without specific prior -// written permission. +// * Neither the name of Mapbox, nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. // // 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 @@ -31,25 +30,55 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// http://mbtiles.org -// -// See samples/MBTilesDemo for example usage -// #import #import "RMTileSource.h" +@class FMDatabaseQueue; + #define kMBTilesDefaultTileSize 256 #define kMBTilesDefaultMinTileZoom 0 #define kMBTilesDefaultMaxTileZoom 22 #define kMBTilesDefaultLatLonBoundingBox ((RMSphericalTrapezium){.northEast = {.latitude = 90, .longitude = 180}, .southWest = {.latitude = -90, .longitude = -180}}) +/** An RMMBTilesSource provides for a fast, offline-capable set of map tile images served from a local database. [MBTiles](https://www.mapbox.com/foundations/an-open-platform/#mbtiles) is an open standard for map tile image transport. */ @interface RMMBTilesSource : NSObject +{ + FMDatabaseQueue *queue; +} + +/** @name Creating Tile Sources */ + +/** Initialize and return a newly allocated MBTiles tile source based on a given bundle resource with the extension `.mbtiles`. +* +* @param name The name of the resource file. If name is an empty string or `nil`, uses the first file encountered with the extension `.mbtiles`. +* @return An initialized MBTiles tile source. */ +- (id)initWithTileSetResource:(NSString *)name; + +/** Initialize and return a newly allocated MBTiles tile source based on a given bundle resource. +* @param name The name of the resource file. If name is an empty string or `nil`, uses the first file encountered of the supplied type. +* @param extension If extension is an empty string or `nil`, the extension is assumed not to exist and the file is the first file encountered that exactly matches name. +* @return An initialized MBTiles tile source. */ +- (id)initWithTileSetResource:(NSString *)name ofType:(NSString *)extension; +/** Initialize and return a newly allocated MBTiles tile source based on a given local database URL. +* @param tileSetURL Local file path URL to an MBTiles file. +* @return An initialized MBTiles tile source. */ - (id)initWithTileSetURL:(NSURL *)tileSetURL; -- (BOOL)coversFullWorld; +/** @name Querying Tile Source Information */ + +/** Any available HTML-formatted map legend data for the tile source, suitable for display in a `UIWebView`. */ - (NSString *)legend; +/** A suggested starting center coordinate for the map layer. */ +- (CLLocationCoordinate2D)centerCoordinate; + +/** A suggested starting center zoom level for the map layer. */ +- (float)centerZoom; + +/** Returns YES if the tile source provides full-world coverage; otherwise, returns NO. */ +- (BOOL)coversFullWorld; + @end diff --git a/MapView/Map/RMMBTilesSource.m b/MapView/Map/RMMBTilesSource.m index 349239d8e..cb5a299e3 100644 --- a/MapView/Map/RMMBTilesSource.m +++ b/MapView/Map/RMMBTilesSource.m @@ -2,7 +2,7 @@ // RMMBTilesSource.m // // Created by Justin R. Miller on 6/18/10. -// Copyright 2010, Code Sorcery Workshop, LLC and Development Seed, Inc. +// Copyright 2012-2013 Mapbox. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -15,10 +15,9 @@ // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // -// * Neither the names of Code Sorcery Workshop, LLC or Development Seed, -// Inc., nor the names of its contributors may be used to endorse or -// promote products derived from this software without specific prior -// written permission. +// * Neither the name of Mapbox, nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. // // 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 @@ -37,13 +36,24 @@ #import "RMProjection.h" #import "RMFractalTileProjection.h" -#import "FMDatabase.h" -#import "FMDatabaseQueue.h" +#import "FMDB.h" @implementation RMMBTilesSource { RMFractalTileProjection *tileProjection; - FMDatabaseQueue *queue; + NSString *_uniqueTilecacheKey; +} + +@synthesize cacheable = _cacheable, opaque = _opaque; + +- (id)initWithTileSetResource:(NSString *)name +{ + return [self initWithTileSetResource:name ofType:([[[name pathExtension] lowercaseString] isEqualToString:@"mbtiles"] ? @"" : @"mbtiles")]; +} + +- (id)initWithTileSetResource:(NSString *)name ofType:(NSString *)extension +{ + return [self initWithTileSetURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:name ofType:extension]]]; } - (id)initWithTileSetURL:(NSURL *)tileSetURL @@ -56,15 +66,20 @@ - (id)initWithTileSetURL:(NSURL *)tileSetURL maxZoom:kMBTilesDefaultMaxTileZoom minZoom:kMBTilesDefaultMinTileZoom]; - queue = [[FMDatabaseQueue databaseQueueWithPath:[tileSetURL path]] retain]; + queue = [FMDatabaseQueue databaseQueueWithPath:[tileSetURL path]]; if ( ! queue) return nil; + _uniqueTilecacheKey = [NSString stringWithFormat:@"MBTiles%@", [queue.path lastPathComponent]]; + [queue inDatabase:^(FMDatabase *db) { [db setShouldCacheStatements:YES]; }]; + self.cacheable = NO; + self.opaque = YES; + return self; } @@ -73,13 +88,6 @@ - (void)cancelAllDownloads // no-op } -- (void)dealloc -{ - [tileProjection release]; tileProjection = nil; - [queue release]; queue = nil; - [super dealloc]; -} - - (NSUInteger)tileSideLength { return tileProjection.tileSideLength; @@ -91,30 +99,30 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache @"%@ tried to retrieve tile with zoomLevel %d, outside source's defined range %f to %f", self, tile.zoom, self.minZoom, self.maxZoom); - NSInteger zoom = tile.zoom; - NSInteger x = tile.x; - NSInteger y = pow(2, zoom) - tile.y - 1; + NSUInteger zoom = tile.zoom; + NSUInteger x = tile.x; + NSUInteger y = pow(2, zoom) - tile.y - 1; dispatch_async(dispatch_get_main_queue(), ^(void) { [[NSNotificationCenter defaultCenter] postNotificationName:RMTileRequested object:[NSNumber numberWithUnsignedLongLong:RMTileKey(tile)]]; }); - __block UIImage *image; + __block UIImage *image = nil; [queue inDatabase:^(FMDatabase *db) { FMResultSet *results = [db executeQuery:@"select tile_data from tiles where zoom_level = ? and tile_column = ? and tile_row = ?", - [NSNumber numberWithShort:zoom], - [NSNumber numberWithUnsignedInt:x], - [NSNumber numberWithUnsignedInt:y]]; + [NSNumber numberWithUnsignedLongLong:zoom], + [NSNumber numberWithUnsignedLongLong:x], + [NSNumber numberWithUnsignedLongLong:y]]; if ([db hadError]) image = [RMTileImage errorTile]; [results next]; - NSData *data = [results dataForColumn:@"tile_data"]; + NSData *data = ([[results columnNameToIndexMap] count] ? [results dataForColumn:@"tile_data"] : nil); if ( ! data) image = [RMTileImage errorTile]; @@ -132,6 +140,11 @@ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache return image; } +- (BOOL)tileSourceHasTile:(RMTile)tile +{ + return YES; +} + - (NSString *)tileURL:(RMTile)tile { return nil; @@ -149,7 +162,7 @@ - (NSString *)tilePath - (RMFractalTileProjection *)mercatorToTileProjection { - return [[tileProjection retain] autorelease]; + return tileProjection; } - (RMProjection *)projection @@ -240,21 +253,9 @@ - (RMSphericalTrapezium)latitudeLongitudeBoundingBox return bounds; } -- (BOOL)coversFullWorld -{ - RMSphericalTrapezium ownBounds = [self latitudeLongitudeBoundingBox]; - RMSphericalTrapezium defaultBounds = kMBTilesDefaultLatLonBoundingBox; - - if (ownBounds.southWest.longitude <= defaultBounds.southWest.longitude + 10 && - ownBounds.northEast.longitude >= defaultBounds.northEast.longitude - 10) - return YES; - - return NO; -} - - (NSString *)legend { - __block NSString *legend; + __block NSString *legend = nil; [queue inDatabase:^(FMDatabase *db) { @@ -273,6 +274,57 @@ - (NSString *)legend return legend; } +- (CLLocationCoordinate2D)centerCoordinate +{ + __block CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(0, 0); + + [queue inDatabase:^(FMDatabase *db) + { + FMResultSet *results = [db executeQuery:@"select value from metadata where name = 'center'"]; + + [results next]; + + if ([results stringForColumn:@"value"] && [[[results stringForColumn:@"value"] componentsSeparatedByString:@","] count] >= 2) + centerCoordinate = CLLocationCoordinate2DMake([[[[results stringForColumn:@"value"] componentsSeparatedByString:@","] objectAtIndex:1] doubleValue], + [[[[results stringForColumn:@"value"] componentsSeparatedByString:@","] objectAtIndex:0] doubleValue]); + + [results close]; + }]; + + return centerCoordinate; +} + +- (float)centerZoom +{ + __block CGFloat centerZoom = [self minZoom]; + + [queue inDatabase:^(FMDatabase *db) + { + FMResultSet *results = [db executeQuery:@"select value from metadata where name = 'center'"]; + + [results next]; + + if ([results stringForColumn:@"value"] && [[[results stringForColumn:@"value"] componentsSeparatedByString:@","] count] >= 3) + centerZoom = [[[[results stringForColumn:@"value"] componentsSeparatedByString:@","] objectAtIndex:2] floatValue]; + + [results close]; + }]; + + return centerZoom; +} + +- (BOOL)coversFullWorld +{ + RMSphericalTrapezium ownBounds = [self latitudeLongitudeBoundingBox]; + RMSphericalTrapezium defaultBounds = kMBTilesDefaultLatLonBoundingBox; + + if (ownBounds.southWest.longitude <= defaultBounds.southWest.longitude + 10 && + ownBounds.northEast.longitude >= defaultBounds.northEast.longitude - 10) + return YES; + + return NO; +} + - (void)didReceiveMemoryWarning { NSLog(@"*** didReceiveMemoryWarning in %@", [self class]); @@ -280,12 +332,12 @@ - (void)didReceiveMemoryWarning - (NSString *)uniqueTilecacheKey { - return [NSString stringWithFormat:@"MBTiles%@", [queue.path lastPathComponent]]; + return _uniqueTilecacheKey; } - (NSString *)shortName { - __block NSString *shortName; + __block NSString *shortName = nil; [queue inDatabase:^(FMDatabase *db) { @@ -306,7 +358,7 @@ - (NSString *)shortName - (NSString *)longDescription { - __block NSString *description; + __block NSString *description = nil; [queue inDatabase:^(FMDatabase *db) { @@ -327,7 +379,7 @@ - (NSString *)longDescription - (NSString *)shortAttribution { - __block NSString *attribution; + __block NSString *attribution = nil; [queue inDatabase:^(FMDatabase *db) { @@ -351,9 +403,4 @@ - (NSString *)longAttribution return [NSString stringWithFormat:@"%@ - %@", [self shortName], [self shortAttribution]]; } -- (void)removeAllCachedImages -{ - NSLog(@"*** removeAllCachedImages in %@", [self class]); -} - @end diff --git a/MapView/Map/RMMapBoxSource.h b/MapView/Map/RMMapBoxSource.h deleted file mode 100644 index 7cd33f617..000000000 --- a/MapView/Map/RMMapBoxSource.h +++ /dev/null @@ -1,73 +0,0 @@ -// -// RMMapBoxSource.h -// -// Created by Justin R. Miller on 5/17/11. -// Copyright 2012 MapBox. -// 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. -// -// * Neither the name of MapBox, nor the names of its contributors may be -// used to endorse or promote products derived from this software -// without specific prior written permission. -// -// 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. -// -// This source supports both tiles from MapBox Hosting as well as the open source, -// self-hosted TileStream software. -// -// When initializing an instance, pass in valid TileJSON 2.0.0[1] as returned by -// the MapBox Hosting API[2] or TileStream software[3]. -// -// Example app at https://github.com/mapbox/mapbox-ios-example -// -// [1] https://github.com/mapbox/TileJSON/tree/master/2.0.0 -// [2] http://mapbox.com/hosting/api/ -// [3] https://github.com/mapbox/tilestream -// -// This class also supports initialization via the deprecated info dictionary -// for backwards compatibility and for iOS < 5.0 where JSON serialization isn't -// built into the SDK. Its use is discouraged. - -#import "RMAbstractWebMapSource.h" - -#define kMapBoxDefaultTileSize 256 -#define kMapBoxDefaultMinTileZoom 0 -#define kMapBoxDefaultMaxTileZoom 18 -#define kMapBoxDefaultLatLonBoundingBox ((RMSphericalTrapezium){ .northEast = { .latitude = 90, .longitude = 180 }, \ - .southWest = { .latitude = -90, .longitude = -180 } }) - -@interface RMMapBoxSource : RMAbstractWebMapSource - -- (id)initWithReferenceURL:(NSURL *)referenceURL; // Designated initializer. Point to either a remote TileJSON spec or a local TileJSON or property list. - -// -// You may also use just `init` to get MapBox Streets by default. -// - -- (id)initWithTileJSON:(NSString *)tileJSON; // Initialize source with TileJSON. -- (id)initWithInfo:(NSDictionary *)info; // Initialize source with properly list (deprecated). - -- (NSString *)legend; // HTML-formatted legend for this source, if any -- (BOOL)coversFullWorld; // Regional or global coverage? - -@property (nonatomic, readonly, retain) NSDictionary *infoDictionary; - -@end diff --git a/MapView/Map/RMMapBoxSource.m b/MapView/Map/RMMapBoxSource.m deleted file mode 100644 index d0997207c..000000000 --- a/MapView/Map/RMMapBoxSource.m +++ /dev/null @@ -1,209 +0,0 @@ -// -// RMMapBoxSource.m -// -// Created by Justin R. Miller on 5/17/11. -// Copyright 2012 MapBox. -// 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. -// -// * Neither the name of MapBox, nor the names of its contributors may be -// used to endorse or promote products derived from this software -// without specific prior written permission. -// -// 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. -// - -#import "RMMapBoxSource.h" - -@interface RMMapBoxSource () - -@property (nonatomic, retain) NSDictionary *infoDictionary; - -@end - -#pragma mark - - -@implementation RMMapBoxSource - -@synthesize infoDictionary; - -- (id)init -{ - return [self initWithReferenceURL:[NSURL URLWithString:@"http://api.tiles.mapbox.com/v2/mapbox.mapbox-streets.json"]]; -} - -- (id)initWithTileJSON:(NSString *)tileJSON -{ - if (self = [super init]) - { - NSAssert([NSJSONSerialization class], @"JSON serialization not supported by SDK"); - - infoDictionary = (NSDictionary *)[[NSJSONSerialization JSONObjectWithData:[tileJSON dataUsingEncoding:NSUTF8StringEncoding] - options:0 - error:nil] retain]; - } - - return self; -} - -- (id)initWithInfo:(NSDictionary *)info -{ - WarnDeprecated(); - - if ( ! (self = [super init])) - return nil; - - infoDictionary = [[NSDictionary dictionaryWithDictionary:info] retain]; - - return self; -} - -- (id)initWithReferenceURL:(NSURL *)referenceURL -{ - id dataObject; - - if ((dataObject = [NSString stringWithContentsOfURL:referenceURL encoding:NSUTF8StringEncoding error:nil]) && dataObject) - return [self initWithTileJSON:dataObject]; - - else if ((dataObject = [[[NSDictionary alloc] initWithContentsOfURL:referenceURL] autorelease]) && dataObject) - return [self initWithInfo:dataObject]; - - return nil; -} - -- (void)dealloc -{ - [infoDictionary release]; - [super dealloc]; -} - -#pragma mark - -- (NSURL *)URLForTile:(RMTile)tile -{ - // flip y value per OSM-style - // - NSInteger zoom = tile.zoom; - NSInteger x = tile.x; - NSInteger y = tile.y; - - if ([self.infoDictionary objectForKey:@"scheme"] && [[self.infoDictionary objectForKey:@"scheme"] isEqual:@"tms"]) - y = pow(2, zoom) - tile.y - 1; - - NSString *tileURLString; - - if ([self.infoDictionary objectForKey:@"tiles"]) - tileURLString = [[self.infoDictionary objectForKey:@"tiles"] objectAtIndex:0]; - - else - tileURLString = [self.infoDictionary objectForKey:@"tileURL"]; - - tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@"{z}" withString:[[NSNumber numberWithInteger:zoom] stringValue]]; - tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@"{x}" withString:[[NSNumber numberWithInteger:x] stringValue]]; - tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@"{y}" withString:[[NSNumber numberWithInteger:y] stringValue]]; - - return [NSURL URLWithString:tileURLString]; -} - -- (float)minZoom -{ - return [[self.infoDictionary objectForKey:@"minzoom"] floatValue]; -} - -- (float)maxZoom -{ - return [[self.infoDictionary objectForKey:@"maxzoom"] floatValue]; -} - -- (RMSphericalTrapezium)latitudeLongitudeBoundingBox -{ - id bounds = [self.infoDictionary objectForKey:@"bounds"]; - - NSArray *parts; - - if ([bounds isKindOfClass:[NSArray class]]) - parts = bounds; - - else - parts = [bounds componentsSeparatedByString:@","]; - - if ([parts count] == 4) - { - RMSphericalTrapezium bounds = { - .southWest = { - .longitude = [[parts objectAtIndex:0] doubleValue], - .latitude = [[parts objectAtIndex:1] doubleValue], - }, - .northEast = { - .longitude = [[parts objectAtIndex:2] doubleValue], - .latitude = [[parts objectAtIndex:3] doubleValue], - }, - }; - - return bounds; - } - - return kMapBoxDefaultLatLonBoundingBox; -} - -- (BOOL)coversFullWorld -{ - RMSphericalTrapezium ownBounds = [self latitudeLongitudeBoundingBox]; - RMSphericalTrapezium defaultBounds = kMapBoxDefaultLatLonBoundingBox; - - if (ownBounds.southWest.longitude <= defaultBounds.southWest.longitude + 10 && - ownBounds.northEast.longitude >= defaultBounds.northEast.longitude - 10) - return YES; - - return NO; -} - -- (NSString *)legend -{ - return [self.infoDictionary objectForKey:@"legend"]; -} - -- (NSString *)uniqueTilecacheKey -{ - return [NSString stringWithFormat:@"MapBox-%@-%@", [self.infoDictionary objectForKey:@"id"], [self.infoDictionary objectForKey:@"version"]]; -} - -- (NSString *)shortName -{ - return [self.infoDictionary objectForKey:@"name"]; -} - -- (NSString *)longDescription -{ - return [self.infoDictionary objectForKey:@"description"]; -} - -- (NSString *)shortAttribution -{ - return [self.infoDictionary objectForKey:@"attribution"]; -} - -- (NSString *)longAttribution -{ - return [self shortAttribution]; -} - -@end diff --git a/MapView/Map/RMMapLayer.h b/MapView/Map/RMMapLayer.h index a86f8279e..dcd3e8c44 100644 --- a/MapView/Map/RMMapLayer.h +++ b/MapView/Map/RMMapLayer.h @@ -1,7 +1,7 @@ // // RMMapLayer.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -29,27 +29,81 @@ #import #import "RMFoundation.h" +#import "RMMapViewDelegate.h" @class RMAnnotation; +/** RMMapLayer is a generic class for displaying scrollable vector layers on a map view. Generally, a more specialized subclass such as RMMarker will be used for a specific purpose, but RMMapLayer can also be used directly for special purposes. */ @interface RMMapLayer : CAScrollLayer { - RMAnnotation *annotation; + __weak RMAnnotation *annotation; // 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; } -@property (nonatomic, assign) RMAnnotation *annotation; +/** @name Configuring Map Layer Properties */ + +/** The annotation associated with the layer. This can be useful to inspect the annotation's userInfo in order to customize the visual representation. */ +@property (nonatomic, weak) RMAnnotation *annotation; + +/** The current projected location of the layer on the map. */ @property (nonatomic, assign) RMProjectedPoint projectedLocation; -@property (nonatomic, assign) BOOL enableDragging; -@property (nonatomic, retain) id userInfo; +/** The current drag state of the annotation layer. +* +* To support drag operations, you must override the implementation of this property and update the drag state at the following times: +* +* When the drag state changes to `RMMapLayerDragStateStarting`, you should set the state to `RMMapLayerDragStateDragging`. If you perform an animation to indicate the beginning of a drag, you should perform that animation before changing the state. Changing the state to the new value lets the map know that your animations are done. +* +* When the state changes to either `RMMapLayerDragStateCanceling` or `RMMapLayerDragStateEnding`, set the state to `RMMapLayerDragStateNone`. If you perform an animation at the end of a drag, you should perform that animation before changing the state. +* +* Changing the state to the `RMMapLayerDragStateDragging` or `RMMapLayerDragStateNone` value is the way to signal to the map view that you are done with any animations you wanted to perform. For example, when a drag operation begins for a marker, the RMMarker class executes an animation to lift the marker off the map. Similarly, when the marker is dropped, the class performs a drop animation. Even if you do not perform any animations, you should still change the value of this property to reflect the correct state. +* +* You must not try to abort a new drag operation by changing the state from `RMMapLayerDragStateStarting` to `RMMapLayerDragStateNone`. If you do not want your annotation layer to be draggable, return `NO` from the map view delegate's implementation of mapView:shouldDragAnnotation:. */ +@property (nonatomic, assign) RMMapLayerDragState dragState; + +/** Storage for arbitrary data. */ +@property (nonatomic, strong) id userInfo; + +/** A Boolean value indicating whether the annotation layer is able to display extra information in a callout bubble. +* +* 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. +* +* Note that callouts are not supported on non-marker or 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. +* +* 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. +* +* If the view you specify is also a descendant of the UIControl class, you can use the map view’s delegate to receive notifications when your control is tapped. If it does not descend from UIControl, your view is responsible for handling any touch events within its bounds. */ +@property (nonatomic, strong) UIView *leftCalloutAccessoryView; + +/** The view to display on the right side of the standard callout bubble. +* +* This property is set to `nil` by default. The right callout view is typically used to link to more detailed information about the annotation. The height of your view should be 32 pixels or less. A common view to specify for this property is UIButton object whose type is set to UIButtonTypeDetailDisclosure. +* +* If the view you specify is also a descendant of the UIControl class, you can use the map view’s delegate to receive notifications when your control is tapped. If it does not descend from UIControl, your view is responsible for handling any touch events within its bounds. */ +@property (nonatomic, strong) UIView *rightCalloutAccessoryView; + +/** Set the screen position of the layer. +* @param position The desired screen position. +* @param animated If set to `YES`, any position change is animated. */ - (void)setPosition:(CGPoint)position animated:(BOOL)animated; +- (void)setDragState:(RMMapLayerDragState)dragState animated:(BOOL)animated; + @end diff --git a/MapView/Map/RMMapLayer.m b/MapView/Map/RMMapLayer.m index 2717bd21c..cad6e76b3 100644 --- a/MapView/Map/RMMapLayer.m +++ b/MapView/Map/RMMapLayer.m @@ -1,7 +1,7 @@ // // RMMapLayer.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -27,13 +27,28 @@ #import "RMMapLayer.h" #import "RMPixel.h" +#import "RMAnnotation.h" +#import "RMMapView.h" +#import "RMMarker.h" + +@interface RMMapView (PrivateMethods) + +- (void)annotation:(RMAnnotation *)annotation didChangeDragState:(RMMapLayerDragState)newState fromOldState:(RMMapLayerDragState)oldState; + +@end + +#pragma mark - @implementation RMMapLayer @synthesize annotation; @synthesize projectedLocation; -@synthesize enableDragging; +@synthesize dragState=_dragState; @synthesize userInfo; +@synthesize canShowCallout=_canShowCallout; +@synthesize calloutOffset; +@synthesize leftCalloutAccessoryView; +@synthesize rightCalloutAccessoryView; - (id)init { @@ -41,7 +56,7 @@ - (id)init return nil; self.annotation = nil; - self.enableDragging = NO; + self.calloutOffset = CGPointZero; return self; } @@ -53,15 +68,20 @@ - (id)initWithLayer:(id)layer self.annotation = nil; self.userInfo = nil; + self.calloutOffset = CGPointZero; return self; } -- (void)dealloc +- (void)setCanShowCallout:(BOOL)canShowCallout { - self.annotation = nil; - self.userInfo = nil; - [super dealloc]; + if (canShowCallout) + { + NSAssert([self isKindOfClass:[RMMarker class]], @"Callouts are not supported on non-marker annotation layers"); + NSAssert( ! self.annotation.isClusterAnnotation, @"Callouts are not supported on cluster annotation layers"); + } + + _canShowCallout = canShowCallout; } - (void)setPosition:(CGPoint)position animated:(BOOL)animated @@ -69,6 +89,36 @@ - (void)setPosition:(CGPoint)position animated:(BOOL)animated [self setPosition:position]; } +- (void)setDragState:(RMMapLayerDragState)dragState +{ + [self setDragState:dragState animated:NO]; +} + +- (void)setDragState:(RMMapLayerDragState)dragState animated:(BOOL)animated +{ + RMMapLayerDragState oldDragState = _dragState; + + if (dragState == RMMapLayerDragStateStarting) + { + _dragState = RMMapLayerDragStateDragging; + } + else if (dragState == RMMapLayerDragStateDragging) + { + _dragState = RMMapLayerDragStateDragging; + } + else if (dragState == RMMapLayerDragStateCanceling || dragState == RMMapLayerDragStateEnding) + { + _dragState = RMMapLayerDragStateNone; + } + else if (dragState == RMMapLayerDragStateNone) + { + _dragState = RMMapLayerDragStateNone; + } + + if (_dragState != oldDragState) + [self.annotation.mapView annotation:self.annotation didChangeDragState:_dragState fromOldState:oldDragState]; +} + /// return nil for certain animation keys to block core animation //- (id )actionForKey:(NSString *)key //{ diff --git a/MapView/Map/RMMapOverlayView.h b/MapView/Map/RMMapOverlayView.h index 63f922e65..6f69af930 100644 --- a/MapView/Map/RMMapOverlayView.h +++ b/MapView/Map/RMMapOverlayView.h @@ -2,9 +2,29 @@ // RMMapOverlayView.h // MapView // -// Created by Thomas Rasch on 25.08.11. -// Copyright (c) 2011 Alpstein. All rights reserved. +// Copyright (c) 2008-2013, 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. #import @@ -12,7 +32,7 @@ @interface RMMapOverlayView : UIView -- (unsigned)sublayersCount; +- (NSUInteger)sublayersCount; - (void)addSublayer:(CALayer *)aLayer; - (void)insertSublayer:(CALayer *)aLayer atIndex:(unsigned)index; @@ -22,4 +42,6 @@ - (void)moveLayersBy:(CGPoint)delta; +- (CALayer *)overlayHitTest:(CGPoint)point; + @end diff --git a/MapView/Map/RMMapOverlayView.m b/MapView/Map/RMMapOverlayView.m index 3c74bba68..dce1edd67 100644 --- a/MapView/Map/RMMapOverlayView.m +++ b/MapView/Map/RMMapOverlayView.m @@ -2,14 +2,36 @@ // RMMapOverlayView.m // MapView // -// Created by Thomas Rasch on 25.08.11. -// Copyright (c) 2011 Alpstein. All rights reserved. +// Copyright (c) 2008-2013, 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. #import "RMMapOverlayView.h" #import "RMMarker.h" #import "RMAnnotation.h" #import "RMPixel.h" +#import "RMMapView.h" +#import "RMUserLocation.h" @implementation RMMapOverlayView @@ -28,7 +50,7 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (unsigned)sublayersCount +- (NSUInteger)sublayersCount { return [self.layer.sublayers count]; } @@ -58,4 +80,34 @@ - (void)moveLayersBy:(CGPoint)delta [self.layer scrollPoint:CGPointMake(-delta.x, -delta.y)]; } +- (CALayer *)overlayHitTest:(CGPoint)point +{ + RMMapView *mapView = ((RMMapView *)self.superview); + + // Here we be sure to hide disabled but visible annotations' layers to + // avoid touch events, then re-enable them after scoring the hit. We + // also show the user location if enabled and we're in tracking mode, + // since its layer is hidden and we want a possible hit. + // + NSPredicate *annotationPredicate = [NSPredicate predicateWithFormat:@"SELF.enabled = NO AND SELF.layer != %@ AND SELF.layer.isHidden = NO", [NSNull null]]; + + NSArray *disabledVisibleAnnotations = [mapView.annotations filteredArrayUsingPredicate:annotationPredicate]; + + for (RMAnnotation *annotation in disabledVisibleAnnotations) + annotation.layer.hidden = YES; + + if (mapView.userLocation.enabled && mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading) + mapView.userLocation.layer.hidden = NO; + + CALayer *hit = [self.layer hitTest:point]; + + if (mapView.userLocation.enabled && mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading) + mapView.userLocation.layer.hidden = YES; + + for (RMAnnotation *annotation in disabledVisibleAnnotations) + annotation.layer.hidden = NO; + + return hit; +} + @end diff --git a/MapView/Map/RMMapQuestOSMSource.h b/MapView/Map/RMMapQuestOSMSource.h index 42042ae01..e1069d720 100644 --- a/MapView/Map/RMMapQuestOSMSource.h +++ b/MapView/Map/RMMapQuestOSMSource.h @@ -1,7 +1,7 @@ // // RMMapQuestOSMSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMMapQuestOSMSource.m b/MapView/Map/RMMapQuestOSMSource.m index 23eab4471..a112436af 100644 --- a/MapView/Map/RMMapQuestOSMSource.m +++ b/MapView/Map/RMMapQuestOSMSource.m @@ -1,7 +1,7 @@ // // RMMapQuestOSMSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMMapQuestOpenAerialSource.h b/MapView/Map/RMMapQuestOpenAerialSource.h index 3b97c15ed..5474d12be 100644 --- a/MapView/Map/RMMapQuestOpenAerialSource.h +++ b/MapView/Map/RMMapQuestOpenAerialSource.h @@ -1,7 +1,7 @@ // // RMMapQuestOpenAerialSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMMapQuestOpenAerialSource.m b/MapView/Map/RMMapQuestOpenAerialSource.m index cb452d9c6..a5a4dd5e5 100644 --- a/MapView/Map/RMMapQuestOpenAerialSource.m +++ b/MapView/Map/RMMapQuestOpenAerialSource.m @@ -1,7 +1,7 @@ // // RMMapQuestOpenAerialSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMMapScrollView.h b/MapView/Map/RMMapScrollView.h index f3622f496..295dbcdf6 100644 --- a/MapView/Map/RMMapScrollView.h +++ b/MapView/Map/RMMapScrollView.h @@ -2,9 +2,29 @@ // RMMapScrollView.h // MapView // -// Created by Thomas Rasch on 11.06.12. -// Copyright (c) 2012 Alpstein. All rights reserved. +// Copyright (c) 2008-2013, 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. #import @@ -19,6 +39,6 @@ @interface RMMapScrollView : UIScrollView -@property (nonatomic, assign) id mapScrollViewDelegate; +@property (nonatomic, weak) id mapScrollViewDelegate; @end diff --git a/MapView/Map/RMMapScrollView.m b/MapView/Map/RMMapScrollView.m index 548d0705e..7c4ca22a7 100644 --- a/MapView/Map/RMMapScrollView.m +++ b/MapView/Map/RMMapScrollView.m @@ -2,9 +2,29 @@ // RMMapScrollView.m // MapView // -// Created by Thomas Rasch on 11.06.12. -// Copyright (c) 2012 Alpstein. All rights reserved. +// Copyright (c) 2008-2013, 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. #import "RMMapScrollView.h" @@ -17,7 +37,11 @@ - (void)setContentOffset:(CGPoint)contentOffset if (self.mapScrollViewDelegate) [self.mapScrollViewDelegate scrollView:self correctedContentOffset:&contentOffset]; - [super setContentOffset:contentOffset]; + if ( ! [[NSDecimalNumber notANumber] isEqualToNumber:@(contentOffset.x)] && + ! [[NSDecimalNumber notANumber] isEqualToNumber:@(contentOffset.y)]) + { + [super setContentOffset:contentOffset]; + } } - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated @@ -25,7 +49,11 @@ - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated if (self.mapScrollViewDelegate) [self.mapScrollViewDelegate scrollView:self correctedContentOffset:&contentOffset]; - [super setContentOffset:contentOffset animated:animated]; + if ( ! [[NSDecimalNumber notANumber] isEqualToNumber:@(contentOffset.x)] && + ! [[NSDecimalNumber notANumber] isEqualToNumber:@(contentOffset.y)]) + { + [super setContentOffset:contentOffset animated:animated]; + } } - (void)setContentSize:(CGSize)contentSize diff --git a/MapView/Map/RMMapTiledLayerView.h b/MapView/Map/RMMapTiledLayerView.h index 420741083..00cf0816c 100644 --- a/MapView/Map/RMMapTiledLayerView.h +++ b/MapView/Map/RMMapTiledLayerView.h @@ -2,9 +2,29 @@ // RMMapTiledLayerView.h // MapView // -// Created by Thomas Rasch on 17.08.11. -// Copyright (c) 2011 Alpstein. All rights reserved. +// Copyright (c) 2008-2013, 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. #import "RMTileSource.h" diff --git a/MapView/Map/RMMapTiledLayerView.m b/MapView/Map/RMMapTiledLayerView.m index c8cbe7cce..b45aa89f2 100644 --- a/MapView/Map/RMMapTiledLayerView.m +++ b/MapView/Map/RMMapTiledLayerView.m @@ -2,19 +2,46 @@ // RMMapTiledLayerView.m // MapView // -// Created by Thomas Rasch on 17.08.11. -// Copyright (c) 2011 Alpstein. All rights reserved. +// Copyright (c) 2008-2013, 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. #import "RMMapTiledLayerView.h" #import "RMMapView.h" #import "RMTileSource.h" #import "RMTileImage.h" +#import "RMTileCache.h" +#import "RMMBTilesSource.h" +#import "RMDBMapSource.h" +#import "RMAbstractWebMapSource.h" +#import "RMDatabaseCache.h" + +#define IS_VALID_TILE_IMAGE(image) (image != nil && [image isKindOfClass:[UIImage class]]) @implementation RMMapTiledLayerView { - RMMapView *_mapView; + __weak RMMapView *_mapView; id _tileSource; } @@ -38,14 +65,14 @@ - (id)initWithFrame:(CGRect)frame mapView:(RMMapView *)aMapView forTileSource:(i self.opaque = NO; - _mapView = [aMapView retain]; - _tileSource = [aTileSource retain]; + _mapView = aMapView; + _tileSource = aTileSource; self.useSnapshotRenderer = NO; CATiledLayer *tiledLayer = [self tiledLayer]; - size_t levelsOf2xMagnification = _mapView.tileSourcesContainer.maxZoom; - if (_mapView.adjustTilesForRetinaDisplay) levelsOf2xMagnification += 1; + size_t levelsOf2xMagnification = _mapView.tileSourcesMaxZoom; + if (_mapView.adjustTilesForRetinaDisplay && _mapView.screenScale > 1.0) levelsOf2xMagnification += 1; tiledLayer.levelsOfDetail = levelsOf2xMagnification; tiledLayer.levelsOfDetailBias = levelsOf2xMagnification; @@ -56,9 +83,7 @@ - (void)dealloc { [_tileSource cancelAllDownloads]; self.layer.contents = nil; - [_tileSource release]; _tileSource = nil; - [_mapView release]; _mapView = nil; - [super dealloc]; + _mapView = nil; } - (void)didMoveToWindow @@ -74,8 +99,6 @@ - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context // NSLog(@"drawLayer: {{%f,%f},{%f,%f}}", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - if (self.useSnapshotRenderer) { zoom = (short)ceilf(_mapView.adjustedZoomForRetinaDisplay); @@ -97,7 +120,9 @@ - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context for (int y=y1; y<=y2; ++y) { UIImage *tileImage = [_tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[_mapView tileCache]]; - [tileImage drawInRect:CGRectMake(x * rectSize, y * rectSize, rectSize, rectSize)]; + + if (IS_VALID_TILE_IMAGE(tileImage)) + [tileImage drawInRect:CGRectMake(x * rectSize, y * rectSize, rectSize, rectSize)]; } } @@ -109,6 +134,13 @@ - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context int x = floor(rect.origin.x / rect.size.width), y = floor(fabs(rect.origin.y / rect.size.height)); + if (_mapView.adjustTilesForRetinaDisplay && _mapView.screenScale > 1.0) + { + zoom--; + x >>= 1; + y >>= 1; + } + // NSLog(@"Tile @ x:%d, y:%d, zoom:%d", x, y, zoom); UIGraphicsPushContext(context); @@ -116,7 +148,52 @@ - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context UIImage *tileImage = nil; if (zoom >= _tileSource.minZoom && zoom <= _tileSource.maxZoom) - tileImage = [_tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[_mapView tileCache]]; + { + RMDatabaseCache *databaseCache = nil; + + for (RMTileCache *componentCache in _mapView.tileCache.tileCaches) + if ([componentCache isKindOfClass:[RMDatabaseCache class]]) + databaseCache = (RMDatabaseCache *)componentCache; + + if ( ! [_tileSource isKindOfClass:[RMAbstractWebMapSource class]] || ! databaseCache || ! databaseCache.capacity) + { + // for non-web tiles, query the source directly since trivial blocking + // + tileImage = [_tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[_mapView tileCache]]; + } + else + { + // for non-local tiles, consult cache directly first (if possible) + // + if (_tileSource.isCacheable) + tileImage = [[_mapView tileCache] cachedImage:RMTileMake(x, y, zoom) withCacheKey:[_tileSource uniqueTilecacheKey]]; + + if ( ! tileImage) + { + // fire off an asynchronous retrieval + // + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) + { + // ensure only one request for a URL at a time + // + @synchronized ([(RMAbstractWebMapSource *)_tileSource URLsForTile:RMTileMake(x, y, zoom)]) + { + // this will return quicker if cached since above attempt, else block on fetch + // + if (_tileSource.isCacheable && [_tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[_mapView tileCache]]) + { + dispatch_async(dispatch_get_main_queue(), ^(void) + { + // do it all again for this tile, next time synchronously from cache + // + [self.layer setNeedsDisplayInRect:rect]; + }); + } + } + }); + } + } + } if ( ! tileImage) { @@ -138,7 +215,7 @@ - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context tileImage = [_tileSource imageForTile:RMTileMake((int)nextTileX, (int)nextTileY, currentZoom) inCache:[_mapView tileCache]]; - if (tileImage) + if (IS_VALID_TILE_IMAGE(tileImage)) { // crop float cropSize = 1.0 / powf(2.0, (float)currentTileDepth); @@ -154,6 +231,10 @@ - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context break; } + else + { + tileImage = nil; + } currentTileDepth++; currentZoom = zoom - currentTileDepth; @@ -161,45 +242,66 @@ - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context } } - if (_mapView.debugTiles) + if (IS_VALID_TILE_IMAGE(tileImage)) { - UIGraphicsBeginImageContext(tileImage.size); + if (_mapView.adjustTilesForRetinaDisplay && _mapView.screenScale > 1.0) + { + // Crop the image + float xCrop = (floor(rect.origin.x / rect.size.width) / 2.0) - x; + float yCrop = (floor(rect.origin.y / rect.size.height) / 2.0) - y; + + CGRect cropBounds = CGRectMake(tileImage.size.width * xCrop, + tileImage.size.height * yCrop, + tileImage.size.width * 0.5, + tileImage.size.height * 0.5); + + CGImageRef imageRef = CGImageCreateWithImageInRect([tileImage CGImage], cropBounds); + tileImage = [UIImage imageWithCGImage:imageRef]; + CGImageRelease(imageRef); + } - CGContextRef debugContext = UIGraphicsGetCurrentContext(); + if (_mapView.debugTiles) + { + UIGraphicsBeginImageContext(tileImage.size); - CGRect debugRect = CGRectMake(0, 0, tileImage.size.width, tileImage.size.height); + CGContextRef debugContext = UIGraphicsGetCurrentContext(); - [tileImage drawInRect:debugRect]; + CGRect debugRect = CGRectMake(0, 0, tileImage.size.width, tileImage.size.height); - UIFont *font = [UIFont systemFontOfSize:32.0]; + [tileImage drawInRect:debugRect]; - CGContextSetStrokeColorWithColor(debugContext, [UIColor whiteColor].CGColor); - CGContextSetLineWidth(debugContext, 2.0); - CGContextSetShadowWithColor(debugContext, CGSizeMake(0.0, 0.0), 5.0, [UIColor blackColor].CGColor); + UIFont *font = [UIFont systemFontOfSize:32.0]; - CGContextStrokeRect(debugContext, debugRect); + CGContextSetStrokeColorWithColor(debugContext, [UIColor whiteColor].CGColor); + CGContextSetLineWidth(debugContext, 2.0); + CGContextSetShadowWithColor(debugContext, CGSizeMake(0.0, 0.0), 5.0, [UIColor blackColor].CGColor); - CGContextSetFillColorWithColor(debugContext, [UIColor whiteColor].CGColor); + CGContextStrokeRect(debugContext, debugRect); - NSString *debugString = [NSString stringWithFormat:@"Zoom %d", zoom]; - CGSize debugSize1 = [debugString sizeWithFont:font]; - [debugString drawInRect:CGRectMake(5.0, 5.0, debugSize1.width, debugSize1.height) withFont:font]; + CGContextSetFillColorWithColor(debugContext, [UIColor whiteColor].CGColor); - debugString = [NSString stringWithFormat:@"(%d, %d)", x, y]; - CGSize debugSize2 = [debugString sizeWithFont:font]; - [debugString drawInRect:CGRectMake(5.0, 5.0 + debugSize1.height + 5.0, debugSize2.width, debugSize2.height) withFont:font]; + NSString *debugString = [NSString stringWithFormat:@"Zoom %d", zoom]; + CGSize debugSize1 = [debugString sizeWithFont:font]; + [debugString drawInRect:CGRectMake(5.0, 5.0, debugSize1.width, debugSize1.height) withFont:font]; - tileImage = UIGraphicsGetImageFromCurrentImageContext(); + debugString = [NSString stringWithFormat:@"(%d, %d)", x, y]; + CGSize debugSize2 = [debugString sizeWithFont:font]; + [debugString drawInRect:CGRectMake(5.0, 5.0 + debugSize1.height + 5.0, debugSize2.width, debugSize2.height) withFont:font]; - UIGraphicsEndImageContext(); - } + tileImage = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + } - [tileImage drawInRect:rect]; + [tileImage drawInRect:rect]; + } + else + { +// NSLog(@"Invalid image for {%d,%d} @ %d", x, y, zoom); + } UIGraphicsPopContext(); } - - [pool release]; pool = nil; } @end diff --git a/MapView/Map/RMMapView.h b/MapView/Map/RMMapView.h index bdb8ac201..5f0e779a5 100644 --- a/MapView/Map/RMMapView.h +++ b/MapView/Map/RMMapView.h @@ -1,7 +1,7 @@ // // RMMapView.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -38,10 +38,6 @@ #import "RMMapScrollView.h" #import "RMTileSourcesContainer.h" -#define kRMUserLocationAnnotationTypeName @"RMUserLocationAnnotation" -#define kRMTrackingHaloAnnotationTypeName @"RMTrackingHaloAnnotation" -#define kRMAccuracyCircleAnnotationTypeName @"RMAccuracyCircleAnnotation" - @class RMProjection; @class RMFractalTileProjection; @class RMTileCache; @@ -53,31 +49,49 @@ @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, // default - RMMapDecelerationFast = 1, + RMMapDecelerationNormal = 0, + RMMapDecelerationFast = 1, // default RMMapDecelerationOff = 2 } RMMapDecelerationMode; +/** An RMMapView object provides an embeddable map interface, similar to the one provided by Apple's MapKit. You use this class to display map information and to manipulate the map contents from your application. You can center the map on a given coordinate, specify the size of the area you want to display, and annotate the map with custom information. +* +* @warning Please note that you are responsible for getting permission to use the map data, and for ensuring your use adheres to the relevant terms of use. */ +@interface RMMapView : UIView -@interface RMMapView : UIView +/** @name Accessing the Delegate */ -@property (nonatomic, assign) id delegate; +/** The receiver's delegate. +* +* A map view sends messages to its delegate regarding the loading of map data and changes in the portion of the map being displayed. The delegate also manages the annotation layers used to highlight points of interest on the map. +* +* The delegate should implement the methods of the RMMapViewDelegate protocol. */ +@property (nonatomic, weak) IBOutlet id delegate; #pragma mark - View properties -@property (nonatomic, assign) BOOL enableDragging; -@property (nonatomic, assign) BOOL enableBouncing; +/** @name Configuring Map Behavior */ + +/** A Boolean value that determines whether the user may scroll around the map. +* +* 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 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 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; + +/** A custom deceleration mode for the map view for drag operations. Set to `RMMapDecelerationOff` to disable map drag deceleration. The default value is `RMMapDecelerationFast`. */ @property (nonatomic, assign) RMMapDecelerationMode decelerationMode; @property (nonatomic, assign) double metersPerPixel; @@ -85,54 +99,124 @@ typedef enum : NSUInteger { @property (nonatomic, readonly) double scaleDenominator; // The denominator in a cartographic scale like 1/24000, 1/50000, 1/2000000. @property (nonatomic, readonly) float screenScale; +/** @name Supporting Retina Displays */ + +/** A Boolean value that adjusts the display of map tile images for retina-capable screens. +* +* If set to `YES`, the map tiles are drawn at double size, typically 512 pixels square instead of 256 pixels, in order to compensate for smaller features and to make them more legible. If tiles designed for retina devices are used, this value should be set to `NO` in order to display these tiles at the proper size. The default value is `NO`. */ @property (nonatomic, assign) BOOL adjustTilesForRetinaDisplay; + @property (nonatomic, readonly) float adjustedZoomForRetinaDisplay; // takes adjustTilesForRetinaDisplay and screen scale into account -// take missing tiles from lower zoom levels, up to #missingTilesDepth zoom levels (defaults to 0, which disables this feature) +/** @name Attributing Map Data */ + +/** Whether to hide map data attribution for the map view. +* +* If this is set to NO, a small disclosure button will be added to the lower-right of the map view, allowing the user to tap it to display a modal view showing map data attribution info. The modal presentation uses a page curl animation to reveal the attribution info under the map view. +* +* The default value is NO, meaning that attribution info will be shown. Please ensure that the terms & conditions of any map data used in your application are satisfied before setting this value to YES. */ +@property (nonatomic, assign) BOOL hideAttribution; + +/** @name Fine-Tuning the Map Appearance */ + +/** 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; -// subview for the background image displayed while tiles are loading. -@property (nonatomic, retain) UIView *backgroundView; +/** A custom image to use behind the map tiles. The default behavior is to show the default `backgroundView` and not a static image. +* +* @param backgroundImage The image to use. */ +- (void)setBackgroundImage:(UIImage *)backgroundImage; +/** A Boolean value indicating whether to draw tile borders and z/x/y numbers on tile images for debugging purposes. Defaults to `NO`. */ @property (nonatomic, assign) BOOL debugTiles; +/** A Boolean value indicating whether to show a small logo in the corner of the map view. Defaults to `YES`. */ +@property (nonatomic, assign) BOOL showLogoBug; + #pragma mark - Initializers +/** @name Initializing a Map View */ + +/** Initialize a map view with a given frame. A default watermarked Mapbox map tile source will be used. +* +* @param frame The frame with which to initialize the map view. +* @return An initialized map view, or `nil` if the map view was unable to be initialized. */ +- (id)initWithFrame:(CGRect)frame; + +/** Initialize a map view with a given frame and tile source. +* @param frame The frame with which to initialize the map view. +* @param newTilesource The tile source to use for the map tiles. +* @return An initialized map view, or `nil` if the map view was unable to be initialized. */ - (id)initWithFrame:(CGRect)frame andTilesource:(id )newTilesource; -// designated initializer +/** Designated initializer. Initialize a map view. +* @param frame The map view's frame. +* @param newTilesource A tile source to use for the map tiles. +* @param initialCenterCoordinate The starting map center coordinate. +* @param initialTileSourceZoomLevel The starting map zoom level, clamped to the zoom levels supported by the tile source(s). +* @param initialTileSourceMaxZoomLevel The maximum zoom level allowed by the map view, clamped to the zoom levels supported by the tile source(s). +* @param initialTileSourceMinZoomLevel The minimum zoom level allowed by the map view, clamped to the zoom levels supported by the tile source(s). +* @param backgroundImage A custom background image to use behind the map instead of the default gridded tile background that moves with the map. +* @return An initialized map view, or `nil` if a map view was unable to be initialized. */ - (id)initWithFrame:(CGRect)frame andTilesource:(id )newTilesource centerCoordinate:(CLLocationCoordinate2D)initialCenterCoordinate - zoomLevel:(float)initialZoomLevel - maxZoomLevel:(float)maxZoomLevel - minZoomLevel:(float)minZoomLevel + zoomLevel:(float)initialTileSourceZoomLevel + maxZoomLevel:(float)initialTileSourceMaxZoomLevel + minZoomLevel:(float)initialTileSourceMinZoomLevel backgroundImage:(UIImage *)backgroundImage; - (void)setFrame:(CGRect)frame; ++ (UIImage *)resourceImageNamed:(NSString *)imageName; ++ (NSString *)pathForBundleResourceNamed:(NSString *)name ofType:(NSString *)extension; + #pragma mark - Movement +/** @name Panning the Map */ + +/** The center coordinate of the map view. */ @property (nonatomic, assign) CLLocationCoordinate2D centerCoordinate; + +/** The center point of the map represented as a projected point. */ @property (nonatomic, assign) RMProjectedPoint centerProjectedPoint; -// recenter the map on #coordinate, expressed as CLLocationCoordinate2D (latitude/longitude) +/** Set the map center to a given coordinate. +* @param coordinate A coordinate to set as the map center. +* @param animated Whether to animate the change to the map center. */ - (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated; -// recenter the map on #aPoint, expressed in projected meters +/** Set the map center to a given projected point. +* @param aPoint A projected point to set as the map center. +* @param animated Whether to animate the change to the map center. */ - (void)setCenterProjectedPoint:(RMProjectedPoint)aPoint animated:(BOOL)animated; +/** Move the map center by a given delta. +* @param delta A `CGSize` by which to move the map center. */ - (void)moveBy:(CGSize)delta; #pragma mark - Zoom +/** @name Zooming the Map */ + // minimum and maximum zoom number allowed for the view. #minZoom and #maxZoom must be within the limits of #tileSource but can be stricter; they are clamped to tilesource limits (minZoom, maxZoom) if needed. + +/** The current zoom level of the map. */ @property (nonatomic, assign) float zoom; + +/** The minimum zoom level of the map, clamped to the range supported by the tile source(s). */ @property (nonatomic, assign) float minZoom; + +/** The maximum zoom level of the map, clamped to the range supported by the tile source(s). */ @property (nonatomic, assign) float maxZoom; +@property (nonatomic, assign) float tileSourcesZoom; +@property (nonatomic, assign) float tileSourcesMinZoom; +@property (nonatomic, assign) float tileSourcesMaxZoom; + @property (nonatomic, assign) RMProjectedRect projectedBounds; @property (nonatomic, readonly) RMProjectedPoint projectedOrigin; @property (nonatomic, readonly) RMProjectedSize projectedViewSize; @@ -140,11 +224,37 @@ typedef enum : NSUInteger { // recenter the map on #boundsRect, expressed in projected meters - (void)setProjectedBounds:(RMProjectedRect)boundsRect animated:(BOOL)animated; +/** Set zoom level, optionally with an animation. +* @param newZoom The desired zoom level. +* @param animated Whether to animate the map change. */ +- (void)setZoom:(float)newZoom animated:(BOOL)animated; + +/** Set both zoom level and center coordinate at the same time, optionally with an animation. +* @param newZoom The desired zoom level. +* @param newCenter The desired center coordinate. +* @param animated Whether to animate the map change. */ +- (void)setZoom:(float)newZoom atCoordinate:(CLLocationCoordinate2D)newCenter animated:(BOOL)animated; + +/** Zoom the map by a given factor near a certain point. +* @param zoomFactor The factor by which to zoom the map. +* @param center The point at which to zoom the map. +* @param animated Whether to animate the zoom. */ - (void)zoomByFactor:(float)zoomFactor near:(CGPoint)center animated:(BOOL)animated; +/** Zoom the map in at the next integral zoom level near a certain point. +* @param pivot The point at which to zoom the map. +* @param animated Whether to animate the zoom. */ - (void)zoomInToNextNativeZoomAt:(CGPoint)pivot animated:(BOOL)animated; + +/** Zoom the map out at the next integral zoom level near a certain point. +* @param pivot The point at which to zoom the map. +* @param animated Whether to animate the zoom. */ - (void)zoomOutToNextNativeZoomAt:(CGPoint)pivot animated:(BOOL)animated; +/** Zoom the map to a given latitude and longitude bounds. +* @param southWest The southwest point to zoom to. +* @param northEast The northeast point to zoom to. +* @param animated Whether to animate the zoom. */ - (void)zoomWithLatitudeLongitudeBoundsSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast animated:(BOOL)animated; - (float)nextNativeZoomFactor; @@ -154,82 +264,221 @@ typedef enum : NSUInteger { #pragma mark - Bounds -// returns the smallest bounding box containing the entire view +/** @name Querying the Map Bounds */ + +/** The smallest bounding box containing the entire map view. */ - (RMSphericalTrapezium)latitudeLongitudeBoundingBox; -// returns the smallest bounding box containing a rectangular region of the view + +/** The smallest bounding box containing a rectangular region of the map view. +* @param rect A rectangular region. */ - (RMSphericalTrapezium)latitudeLongitudeBoundingBoxFor:(CGRect) rect; - (BOOL)tileSourceBoundsContainProjectedPoint:(RMProjectedPoint)point; +/** @name Constraining the Map */ + +/** Contrain zooming and panning of the map view to a given coordinate boundary. +* @param southWest The southwest point to constrain to. +* @param northEast The northeast point to constrain to. */ - (void)setConstraintsSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast; + - (void)setProjectedConstraintsSouthWest:(RMProjectedPoint)southWest northEast:(RMProjectedPoint)northEast; #pragma mark - Snapshots +/** @name Capturing Snapshots of the Map View */ + +/** Take a snapshot of the map view. +* +* By default, the overlay containing any visible annotations is also captured. +* @return An image depicting the map view. */ - (UIImage *)takeSnapshot; + +/** Take a snapshot of the map view. +* @param includeOverlay Whether to include the overlay containing any visible annotations. +* @return An image depicting the map view. */ - (UIImage *)takeSnapshotAndIncludeOverlay:(BOOL)includeOverlay; #pragma mark - Annotations -@property (nonatomic, readonly) NSArray *annotations; -@property (nonatomic, readonly) NSArray *visibleAnnotations; +/** @name Annotating the Map */ + +/** The annotations currently added to the map. Includes user location annotations, if any. */ +@property (nonatomic, weak, readonly) NSArray *annotations; +/** The annotations currently visible on the map. May include annotations currently shown in clusters. */ +@property (nonatomic, weak, readonly) NSArray *visibleAnnotations; + +/** Add an annotation to the map. +* @param annotation The annotation to add. */ - (void)addAnnotation:(RMAnnotation *)annotation; + +/** Add one or more annotations to the map. +* @param annotations An array containing the annotations to add to the map. */ - (void)addAnnotations:(NSArray *)annotations; +/** Remove an annotation from the map. +* @param annotation The annotation to remove. */ - (void)removeAnnotation:(RMAnnotation *)annotation; + +/** Remove one or more annotations from the map. +* @param annotations An array containing the annotations to remove from the map. */ - (void)removeAnnotations:(NSArray *)annotations; + +/** Remove all annotations from the map. This does not remove user location annotations, if any. */ - (void)removeAllAnnotations; +/** 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; +/** 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, strong) RMAnnotation *selectedAnnotation; + #pragma mark - TileSources -@property (nonatomic, retain) RMQuadTree *quadTree; +@property (nonatomic, strong) RMQuadTree *quadTree; + +/** @name Configuring Annotation Clustering */ -@property (nonatomic, assign) BOOL enableClustering; +/** 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`. +* +* @warning This property has been deprecated in favor of [RMMapViewDelegate annotationSortingComparatorForMapView:]. */ +@property (nonatomic, assign) BOOL orderMarkersByYPosition DEPRECATED_MSG_ATTRIBUTE("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 `YES`. +* +* @warning This property has been deprecated in favor of [RMMapViewDelegate annotationSortingComparatorForMapView:]. */ +@property (nonatomic, assign) BOOL orderClusterMarkersAboveOthers DEPRECATED_MSG_ATTRIBUTE("use -[RMMapViewDelegate annotationSortingComparatorForMapView:] for annotation sorting"); + @property (nonatomic, assign) CGSize clusterMarkerSize; @property (nonatomic, assign) CGSize clusterAreaSize; -@property (nonatomic, retain) RMTileCache *tileCache; -@property (nonatomic, readonly) RMTileSourcesContainer *tileSourcesContainer; +@property (nonatomic, weak, readonly) RMTileSourcesContainer *tileSourcesContainer; -@property (nonatomic, retain) id tileSource; // the first tile source, for backwards compatibility -@property (nonatomic, retain) NSArray *tileSources; +/** @name Managing Tile Sources */ +/** The first tile source of a map view, ordered from bottom to top. */ +@property (nonatomic, strong) id tileSource; + +/** All of the tile sources for a map view, ordered bottom to top. */ +@property (nonatomic, strong) NSArray *tileSources; + +/** Add a tile source to a map view above the current tile sources. +* @param tileSource The tile source to add. */ - (void)addTileSource:(id )tileSource; + +/** Add a tile source to a map view at a given index. +* @param tileSource The tile source to add. +* @param index The index at which to add the tile source. A value of zero adds the tile source below all other tile sources. */ - (void)addTileSource:(id)tileSource atIndex:(NSUInteger)index; +/** Remove a tile source from the map view. +* @param tileSource The tile source to remove. */ - (void)removeTileSource:(id )tileSource; + +/** Remove the tile source at a given index from the map view. +* @param index The index of the tile source to remove. */ - (void)removeTileSourceAtIndex:(NSUInteger)index; +/** Move the tile source at one index to another index. +* @param fromIndex The index of the tile source to move. +* @param toIndex The destination index for the tile source. */ - (void)moveTileSourceAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex; +/** Hide or show a tile source. +* @param isHidden A Boolean indicating whether to hide the tile source or not. +* @param tileSource The tile source to hide or show. */ - (void)setHidden:(BOOL)isHidden forTileSource:(id )tileSource; + +/** Hide or show a tile source at a given index. +* @param isHidden A Boolean indicating whether to hide the tile source or not. +* @param index The index of the tile source to hide or show. */ - (void)setHidden:(BOOL)isHidden forTileSourceAtIndex:(NSUInteger)index; +/** Change a tile source's alpha value. +* @param alpha The desired alpha value. +* @param tileSource The tile source to change. */ +- (void)setAlpha:(CGFloat)alpha forTileSource:(id )tileSource; + +/** Change the alpha value of a tile source at a given index. +* @param alpha The desired alpha value. +* @param index The index of the tile source to change. */ +- (void)setAlpha:(CGFloat)alpha forTileSourceAtIndex:(NSUInteger)index; + +/** Reload the tiles for a given tile source. +* @param tileSource The tile source to reload. */ - (void)reloadTileSource:(id )tileSource; + +/** Reload the tiles for a tile source at a given index. +* @param index The index of the tile source to reload. */ - (void)reloadTileSourceAtIndex:(NSUInteger)index; #pragma mark - Cache -// Clear all images from the #tileSource's caching system. +/** @name Managing Tile Caching Behavior */ + +/** The tile cache for the map view, typically composed of both an in-memory RMMemoryCache and a disk-based RMDatabaseCache. */ +@property (nonatomic, strong) RMTileCache *tileCache; + +/** Clear all tile images from the caching system. */ -(void)removeAllCachedImages; #pragma mark - Conversions // projections to convert from latitude/longitude to meters, from projected meters to tile coordinates -@property (nonatomic, readonly) RMProjection *projection; -@property (nonatomic, readonly) id mercatorToTileProjection; +@property (nonatomic, weak, readonly) RMProjection *projection; +@property (nonatomic, weak, readonly) id mercatorToTileProjection; +/** @name Converting Map Coordinates */ + +/** Convert a projected point to a screen location. +* @param projectedPoint The projected point to convert. +* @return The equivalent screen location. */ - (CGPoint)projectedPointToPixel:(RMProjectedPoint)projectedPoint; + +/** Convert a coordinate to a screen location. +* @param coordinate The coordinate to convert. +* @return The equivalent screen location. */ - (CGPoint)coordinateToPixel:(CLLocationCoordinate2D)coordinate; +/** Convert a screen location to a projected point. +* @param pixelCoordinate A screen location to convert. +* @return The equivalent projected point. */ - (RMProjectedPoint)pixelToProjectedPoint:(CGPoint)pixelCoordinate; + +/** Convert a screen location to a coordinate. +* @param pixelCoordinate A screen location to convert. +* @return The equivalent coordinate. */ - (CLLocationCoordinate2D)pixelToCoordinate:(CGPoint)pixelCoordinate; +/** Convert a coordiante to a projected point. +* @param coordinate A coordinate to convert. +* @return The equivalent projected point. */ - (RMProjectedPoint)coordinateToProjectedPoint:(CLLocationCoordinate2D)coordinate; + +/** Convert a projected point to a coordinate. +* @param projectedPoint A projected point to convert. +* @return The equivalent coordinate. */ - (CLLocationCoordinate2D)projectedPointToCoordinate:(RMProjectedPoint)projectedPoint; - (RMProjectedSize)viewSizeToProjectedSize:(CGSize)screenSize; @@ -238,16 +487,49 @@ typedef enum : NSUInteger { - (CLLocationCoordinate2D)normalizeCoordinate:(CLLocationCoordinate2D)coordinate; - (RMTile)tileWithCoordinate:(CLLocationCoordinate2D)coordinate andZoom:(int)zoom; +/** Return the bounding box for a given map tile. +* @param aTile A map tile. +* @return The bounding box for the tile in the current projection. */ - (RMSphericalTrapezium)latitudeLongitudeBoundingBoxForTile:(RMTile)aTile; #pragma mark - #pragma mark User Location -@property (nonatomic, assign) BOOL showsUserLocation; +/** @name Tracking the User Location */ + +/** A Boolean value indicating whether the map may display the user location. +* +* This property does not indicate whether the user’s position is actually visible on the map, only whether the map view is allowed to display it. To determine whether the user’s position is visible, use the userLocationVisible property. The default value of this property is `NO`. +* +* Setting this property to `YES` causes the map view to use the Core Location framework to find the current location. As long as this property is `YES`, the map view continues to track the user’s location and update it periodically. +* +* On iOS 8 and above, your app must specify a value for `NSLocationWhenInUseUsageDescription` in its `Info.plist` to satisfy the requirements of the underlying Core Location framework when enabling this property. */ +@property (nonatomic, assign) BOOL showsUserLocation; + +/** The annotation object representing the user’s current location. (read-only) */ @property (nonatomic, readonly) RMUserLocation *userLocation; + +/** A Boolean value indicating whether the device’s current location is visible in the map view. (read-only) +* +* This property uses the horizontal accuracy of the current location to determine whether the user’s location is visible. Thus, this property is `YES` if the specific coordinate is offscreen but the rectangle surrounding that coordinate (and defined by the horizontal accuracy value) is partially onscreen. +* +* If the user’s location cannot be determined, this property contains the value `NO`. */ @property (nonatomic, readonly, getter=isUserLocationVisible) BOOL userLocationVisible; -@property (nonatomic, assign) RMUserTrackingMode userTrackingMode; +/** The mode used to track the user location. */ +@property (nonatomic, assign) RMUserTrackingMode userTrackingMode; + +/** Whether the map view should display a heading calibration alert when necessary. The default value is `YES`. */ +@property (nonatomic, assign) BOOL displayHeadingCalibration; + +/** Set the mode used to track the user location. +* +* Setting the tracking mode to `RMUserTrackingModeFollow` or `RMUserTrackingModeFollowWithHeading` causes the map view to center the map on that location and begin tracking the user’s location. If the map is zoomed out, the map view automatically zooms in on the user’s location, effectively changing the current visible region. +* +* On iOS 8 and above, your app must specify a value for `NSLocationWhenInUseUsageDescription` in its `Info.plist` to satisfy the requirements of the underlying Core Location framework when tracking the user location. +* +* @param mode The mode used to track the user location. +* @param animated Whether changes to the map center or rotation should be animated when the mode is changed. */ - (void)setUserTrackingMode:(RMUserTrackingMode)mode animated:(BOOL)animated; @end diff --git a/MapView/Map/RMMapView.m b/MapView/Map/RMMapView.m index 2660012c4..302118409 100644 --- a/MapView/Map/RMMapView.m +++ b/MapView/Map/RMMapView.m @@ -1,7 +1,7 @@ // // RMMapView.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -32,46 +32,66 @@ #import "RMFoundation.h" #import "RMProjection.h" #import "RMMarker.h" -#import "RMPath.h" #import "RMCircle.h" #import "RMShape.h" #import "RMAnnotation.h" #import "RMQuadTree.h" +#import "RMPointAnnotation.h" #import "RMFractalTileProjection.h" -#import "RMOpenStreetMapSource.h" #import "RMTileCache.h" #import "RMTileSource.h" +#import "RMMapboxSource.h" #import "RMMapTiledLayerView.h" #import "RMMapOverlayView.h" +#import "RMLoadingTileView.h" #import "RMUserLocation.h" +#import "RMUserTrackingBarButtonItem.h" + +#import "RMAttributionViewController.h" + +#import "SMCalloutView.h" #pragma mark --- begin constants ---- #define kZoomRectPixelBuffer 150.0 -#define kDefaultInitialLatitude 47.56 -#define kDefaultInitialLongitude 10.22 +#define kDefaultInitialLatitude 38.913175 +#define kDefaultInitialLongitude -77.032458 #define kDefaultMinimumZoomLevel 0.0 #define kDefaultMaximumZoomLevel 25.0 -#define kDefaultInitialZoomLevel 13.0 +#define kDefaultInitialZoomLevel 11.0 #pragma mark --- end constants ---- -@interface RMMapView (PrivateMethods) +@interface RMMapView (PrivateMethods) +@property (nonatomic, assign) UIViewController *viewControllerPresentingAttribution; @property (nonatomic, retain) RMUserLocation *userLocation; - (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 @@ -82,6 +102,9 @@ @interface RMUserLocation (PrivateMethods) @property (nonatomic, getter=isUpdating) BOOL updating; @property (nonatomic, retain) CLLocation *location; @property (nonatomic, retain) CLHeading *heading; +@property (nonatomic, assign) BOOL hasCustomLayer; + +- (void)updateTintColor; @end @@ -95,30 +118,39 @@ @interface RMAnnotation (PrivateMethods) #pragma mark - +@interface RMUserTrackingBarButtonItem (PrivateMethods) + +@property (nonatomic, assign) UIViewTintAdjustmentMode tintAdjustmentMode; + +@end + +#pragma mark - + @implementation RMMapView { - id _delegate; - BOOL _delegateHasBeforeMapMove; BOOL _delegateHasAfterMapMove; BOOL _delegateHasBeforeMapZoom; BOOL _delegateHasAfterMapZoom; BOOL _delegateHasMapViewRegionDidChange; BOOL _delegateHasDoubleTapOnMap; - BOOL _delegateHasDoubleTapTwoFingersOnMap; BOOL _delegateHasSingleTapOnMap; BOOL _delegateHasSingleTapTwoFingersOnMap; - BOOL _delegateHasLongSingleTapOnMap; + BOOL _delegateHasLongPressOnMap; BOOL _delegateHasTapOnAnnotation; BOOL _delegateHasDoubleTapOnAnnotation; + BOOL _delegateHasLongPressOnAnnotation; + BOOL _delegateHasTapOnCalloutAccessoryControlForAnnotation; BOOL _delegateHasTapOnLabelForAnnotation; BOOL _delegateHasDoubleTapOnLabelForAnnotation; - BOOL _delegateHasShouldDragMarker; - BOOL _delegateHasDidDragMarker; - BOOL _delegateHasDidEndDragMarker; + BOOL _delegateHasShouldDragAnnotation; + BOOL _delegateHasDidChangeDragState; BOOL _delegateHasLayerForAnnotation; + BOOL _delegateHasAnnotationSorting; BOOL _delegateHasWillHideLayerForAnnotation; BOOL _delegateHasDidHideLayerForAnnotation; + BOOL _delegateHasDidSelectAnnotation; + BOOL _delegateHasDidDeselectAnnotation; BOOL _delegateHasWillStartLocatingUser; BOOL _delegateHasDidStopLocatingUser; BOOL _delegateHasDidUpdateUserLocation; @@ -129,16 +161,19 @@ @implementation RMMapView RMMapScrollView *_mapScrollView; RMMapOverlayView *_overlayView; UIView *_tiledLayersSuperview; + RMLoadingTileView *_loadingTileView; RMProjection *_projection; RMFractalTileProjection *_mercatorToTileProjection; RMTileSourcesContainer *_tileSourcesContainer; + NSMutableArray *_earlyTileSources; + NSMutableSet *_annotations; NSMutableSet *_visibleAnnotations; - BOOL _constrainMovement; - RMProjectedRect _constrainingProjectedBounds; + BOOL _constrainMovement, _constrainMovementByUser; + RMProjectedRect _constrainingProjectedBounds, _constrainingProjectedBoundsByUser; double _metersPerPixel; float _zoom, _lastZoom; @@ -146,56 +181,81 @@ @implementation RMMapView CGSize _lastContentSize; BOOL _mapScrollViewIsZooming; - BOOL _enableDragging, _enableBouncing; + BOOL _draggingEnabled, _bouncingEnabled; - CGPoint _lastDraggingTranslation; RMAnnotation *_draggedAnnotation; + CGPoint _dragOffset; + + CLLocationManager *_locationManager; + + RMAnnotation *_accuracyCircleAnnotation; + RMAnnotation *_trackingHaloAnnotation; + + UIImageView *_userHeadingTrackingView; + + RMUserTrackingBarButtonItem *_userTrackingBarButtonItem; - CLLocationManager *locationManager; - RMUserLocation *userLocation; - BOOL showsUserLocation; - RMUserTrackingMode userTrackingMode; + __weak UIViewController *_viewControllerPresentingAttribution; + UIButton *_attributionButton; + UIPopoverController *_attributionPopover; - UIImageView *userLocationTrackingView; - UIImageView *userHeadingTrackingView; + CGAffineTransform _mapTransform; + CATransform3D _annotationTransform; + + NSOperationQueue *_moveDelegateQueue; + NSOperationQueue *_zoomDelegateQueue; + + UIImageView *_logoBug; + + UIButton *_compassButton; + + 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 orderMarkersByYPosition = _orderMarkersByYPosition; +@synthesize orderClusterMarkersAboveOthers = _orderClusterMarkersAboveOthers; @synthesize clusterMarkerSize = _clusterMarkerSize, clusterAreaSize = _clusterAreaSize; @synthesize adjustTilesForRetinaDisplay = _adjustTilesForRetinaDisplay; -@synthesize userLocation, showsUserLocation, userTrackingMode; +@synthesize userLocation = _userLocation; +@synthesize showsUserLocation = _showsUserLocation; +@synthesize userTrackingMode = _userTrackingMode; +@synthesize displayHeadingCalibration = _displayHeadingCalibration; @synthesize missingTilesDepth = _missingTilesDepth; @synthesize debugTiles = _debugTiles; +@synthesize hideAttribution = _hideAttribution; +@synthesize showLogoBug = _showLogoBug; #pragma mark - #pragma mark Initialization - (void)performInitializationWithTilesource:(id )newTilesource centerCoordinate:(CLLocationCoordinate2D)initialCenterCoordinate - zoomLevel:(float)initialZoomLevel - maxZoomLevel:(float)maxZoomLevel - minZoomLevel:(float)minZoomLevel + zoomLevel:(float)initialTileSourceZoomLevel + maxZoomLevel:(float)initialTileSourceMaxZoomLevel + minZoomLevel:(float)initialTileSourceMinZoomLevel backgroundImage:(UIImage *)backgroundImage { - _constrainMovement = _enableBouncing = _zoomingInPivotsAroundCenter = NO; - _enableDragging = YES; + _constrainMovement = _constrainMovementByUser = _bouncingEnabled = _zoomingInPivotsAroundCenter = NO; + _draggingEnabled = YES; - _lastDraggingTranslation = CGPointZero; _draggedAnnotation = nil; - self.backgroundColor = [UIColor grayColor]; + self.backgroundColor = (RMPostVersion6 ? [UIColor colorWithRed:0.970 green:0.952 blue:0.912 alpha:1.000] : [UIColor grayColor]); self.clipsToBounds = YES; - + _tileSourcesContainer = [RMTileSourcesContainer new]; _tiledLayersSuperview = nil; @@ -206,80 +266,121 @@ - (void)performInitializationWithTilesource:(id )newTilesource _screenScale = [UIScreen mainScreen].scale; - _boundingMask = RMMapMinWidthBound; _adjustTilesForRetinaDisplay = NO; - _missingTilesDepth = 0; + _missingTilesDepth = 1; _debugTiles = NO; + _orderMarkersByYPosition = YES; + _orderClusterMarkersAboveOthers = YES; + _annotations = [NSMutableSet new]; _visibleAnnotations = [NSMutableSet new]; - [self setQuadTree:[[[RMQuadTree alloc] initWithMapView:self] autorelease]]; - _enableClustering = _positionClusterMarkersAtTheGravityCenter = NO; + [self setQuadTree:[[RMQuadTree alloc] initWithMapView:self]]; + _clusteringEnabled = NO; + _positionClusterMarkersAtTheGravityCenter = YES; _clusterMarkerSize = CGSizeMake(100.0, 100.0); _clusterAreaSize = CGSizeMake(150.0, 150.0); - [self setTileCache:[[[RMTileCache alloc] init] autorelease]]; + _moveDelegateQueue = [NSOperationQueue new]; + [_moveDelegateQueue setMaxConcurrentOperationCount:1]; + + _zoomDelegateQueue = [NSOperationQueue new]; + [_zoomDelegateQueue setMaxConcurrentOperationCount:1]; + + [self setTileCache:[RMTileCache new]]; - [self setBackgroundView:[[[UIView alloc] initWithFrame:[self bounds]] autorelease]]; if (backgroundImage) + { + [self setBackgroundView:[[UIView alloc] initWithFrame:[self bounds]]]; self.backgroundView.layer.contents = (id)backgroundImage.CGImage; + } + else + { + [self setBackgroundView:nil]; + } + + if ([_earlyTileSources count]) + { + for (idearlyTileSource 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]; - if (minZoomLevel < newTilesource.minZoom) minZoomLevel = newTilesource.minZoom; - if (maxZoomLevel > newTilesource.maxZoom) maxZoomLevel = newTilesource.maxZoom; - [self setMinZoom:minZoomLevel]; - [self setMaxZoom:maxZoomLevel]; - [self setZoom:initialZoomLevel]; + if ([_earlyTileSources count]) + { + [self setTileSources:_earlyTileSources]; + [_earlyTileSources removeAllObjects]; + } + else + { + [self setTileSource:newTilesource]; + } - [self setTileSource:newTilesource]; [self setCenterCoordinate:initialCenterCoordinate animated:NO]; + [self setDecelerationMode:RMMapDecelerationFast]; + + self.showLogoBug = YES; + + if (RMPostVersion7) + { + _compassButton = [UIButton buttonWithType:UIButtonTypeCustom]; + UIImage *compassImage = [RMMapView resourceImageNamed:@"Compass.png"]; + _compassButton.frame = CGRectMake(0, 0, compassImage.size.width, compassImage.size.height); + [_compassButton setImage:compassImage forState:UIControlStateNormal]; + _compassButton.alpha = 0; + [_compassButton addTarget:self action:@selector(tappedHeadingCompass:) forControlEvents:UIControlEventTouchUpInside]; + UIView *container = [[UIView alloc] initWithFrame:CGRectMake(self.bounds.size.width - compassImage.size.width - 5, 5, compassImage.size.width, compassImage.size.height)]; + container.translatesAutoresizingMaskIntoConstraints = NO; + [container addSubview:_compassButton]; + [self addSubview:container]; + } + + self.displayHeadingCalibration = YES; + + _mapTransform = CGAffineTransformIdentity; + _annotationTransform = CATransform3DIdentity; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMemoryWarningNotification:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; - RMLog(@"Map initialised. tileSource:%@, minZoom:%f, maxZoom:%f, zoom:%f at {%f,%f}", newTilesource, self.minZoom, self.maxZoom, self.zoom, initialCenterCoordinate.longitude, initialCenterCoordinate.latitude); -} - -- (id)initWithCoder:(NSCoder *)aDecoder -{ - LogMethod(); - - if (!(self = [super initWithCoder:aDecoder])) - return nil; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleWillChangeOrientationNotification:) + name:UIApplicationWillChangeStatusBarOrientationNotification + object:nil]; - CLLocationCoordinate2D coordinate; - coordinate.latitude = kDefaultInitialLatitude; - coordinate.longitude = kDefaultInitialLongitude; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleDidChangeOrientationNotification:) + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; - [self performInitializationWithTilesource:[[RMOpenStreetMapSource new] autorelease] - centerCoordinate:coordinate - zoomLevel:kDefaultInitialZoomLevel - maxZoomLevel:kDefaultMaximumZoomLevel - minZoomLevel:kDefaultMinimumZoomLevel - backgroundImage:nil]; + RMLog(@"Map initialised. tileSource:%@, minZoom:%f, maxZoom:%f, zoom:%f at {%f,%f}", newTilesource, self.minZoom, self.maxZoom, self.zoom, initialCenterCoordinate.longitude, initialCenterCoordinate.latitude); - return self; + [self setNeedsUpdateConstraints]; } - (id)initWithFrame:(CGRect)frame { - LogMethod(); - - return [self initWithFrame:frame andTilesource:[[RMOpenStreetMapSource new] autorelease]]; + return [self initWithFrame:frame andTilesource:[RMMapboxSource new]]; } - (id)initWithFrame:(CGRect)frame andTilesource:(id )newTilesource { - LogMethod(); - - CLLocationCoordinate2D coordinate; - coordinate.latitude = kDefaultInitialLatitude; - coordinate.longitude = kDefaultInitialLongitude; - return [self initWithFrame:frame andTilesource:newTilesource - centerCoordinate:coordinate + centerCoordinate:CLLocationCoordinate2DMake(kDefaultInitialLatitude, kDefaultInitialLongitude) zoomLevel:kDefaultInitialZoomLevel maxZoomLevel:kDefaultMaximumZoomLevel minZoomLevel:kDefaultMinimumZoomLevel @@ -294,11 +395,11 @@ - (id)initWithFrame:(CGRect)frame minZoomLevel:(float)minZoomLevel backgroundImage:(UIImage *)backgroundImage { - LogMethod(); - - if (!(self = [super initWithFrame:frame])) + if (!newTilesource || !(self = [super initWithFrame:frame])) return nil; + _earlyTileSources = [NSMutableArray array]; + [self performInitializationWithTilesource:newTilesource centerCoordinate:initialCenterCoordinate zoomLevel:initialZoomLevel @@ -309,6 +410,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; @@ -327,34 +438,42 @@ - (void)setFrame:(CGRect)frame [self setCenterProjectedPoint:centerPoint animated:NO]; [self correctPositionOfAllAnnotations]; - [self correctMinZoomScaleForBoundingMask]; + + self.minZoom = 0; // force new minZoom calculation + + if (_loadingTileView) + _loadingTileView.mapZooming = NO; } } -- (void)dealloc ++ (UIImage *)resourceImageNamed:(NSString *)imageName { - LogMethod(); + if ( ! [[imageName pathExtension] length]) + imageName = [imageName stringByAppendingString:@".png"]; + + return [UIImage imageWithContentsOfFile:[[self class] pathForBundleResourceNamed:imageName ofType:nil]]; +} + ++ (NSString *)pathForBundleResourceNamed:(NSString *)name ofType:(NSString *)extension +{ + NSAssert([[NSBundle bundleForClass:[self class]] pathForResource:@"Mapbox" ofType:@"bundle"], @"Resource bundle not found in application."); + + NSString *bundlePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"Mapbox" ofType:@"bundle"]; + NSBundle *resourcesBundle = [NSBundle bundleWithPath:bundlePath]; + + return [resourcesBundle pathForResource:name ofType:extension]; +} - [self setDelegate:nil]; - [self setBackgroundView:nil]; - [self setQuadTree:nil]; - [_draggedAnnotation release]; _draggedAnnotation = nil; - [_annotations release]; _annotations = nil; - [_visibleAnnotations release]; _visibleAnnotations = nil; +- (void)dealloc +{ + [_moveDelegateQueue cancelAllOperations]; + [_zoomDelegateQueue cancelAllOperations]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [_mapScrollView removeObserver:self forKeyPath:@"contentOffset"]; - [_tiledLayersSuperview release]; _tiledLayersSuperview = nil; - [_mapScrollView release]; _mapScrollView = nil; - [_overlayView release]; _overlayView = nil; - [_tileSourcesContainer cancelAllDownloads]; [_tileSourcesContainer release]; _tileSourcesContainer = nil; - [_projection release]; _projection = nil; - [_mercatorToTileProjection release]; _mercatorToTileProjection = nil; - [self setTileCache:nil]; - [locationManager release]; locationManager = nil; - [userLocation release]; userLocation = nil; - [userLocationTrackingView release]; userLocationTrackingView = nil; - [userHeadingTrackingView release]; userHeadingTrackingView = nil; - [super dealloc]; + [_tileSourcesContainer cancelAllDownloads]; + _locationManager.delegate = nil; + [_locationManager stopUpdatingLocation]; + [_locationManager stopUpdatingHeading]; } - (void)didReceiveMemoryWarning @@ -370,6 +489,183 @@ - (void)handleMemoryWarningNotification:(NSNotification *)notification [self didReceiveMemoryWarning]; } +- (void)handleWillChangeOrientationNotification:(NSNotification *)notification +{ + // send a dummy heading update to force re-rotation + // + 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]; +} + +- (UIViewController *)viewController +{ + UIResponder *responder = self; + + while ((responder = [responder nextResponder])) + if ([responder isKindOfClass:[UIViewController class]]) + return (UIViewController *)responder; + + return nil; +} + +- (void)updateConstraints +{ + // Determine our view controller since it will be used frequently. + // + UIViewController *viewController = [self viewController]; + + // If we somehow didn't get a view controller, return early and + // just stick with the initial frames. + // + if ( ! viewController) + { + [super updateConstraints]; + return; + } + + // compass + // + if (RMPostVersion7 && _compassButton) + { + // The compass view has an intermediary container superview due to + // jitter caused by constraint math updates during its rotation + // transforms. Constraints are against this container instead so + // that the compass can rotate smootly within. + // + UIView *container = _compassButton.superview; + + if ( ! [[viewController.view valueForKeyPath:@"constraints.firstItem"] containsObject:container] && + ! [[viewController.view valueForKeyPath:@"constraints.secondItem"] containsObject:container]) + { + [viewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topLayoutGuide]-topSpacing-[container]" + options:0 + metrics:@{ @"topSpacing" : @(5) } + views:@{ @"topLayoutGuide" : viewController.topLayoutGuide, + @"container" : container }]]; + + + [viewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[container]-rightSpacing-|" + options:0 + metrics:@{ @"rightSpacing" : @(5) } + views:@{ @"container" : container }]]; + } + } + + if (_logoBug) + { + if ( ! [[viewController.view valueForKeyPath:@"constraints.firstItem"] containsObject:_logoBug] && + ! [[viewController.view valueForKeyPath:@"constraints.secondItem"] containsObject:_logoBug]) + { + NSString *formatString; + NSDictionary *views; + + if (RMPostVersion7) + { + formatString = @"V:[logoBug]-bottomSpacing-[bottomLayoutGuide]"; + views = @{ @"logoBug" : _logoBug, + @"bottomLayoutGuide" : viewController.bottomLayoutGuide }; + } + else + { + formatString = @"V:[logoBug]-bottomSpacing-|"; + views = @{ @"logoBug" : _logoBug }; + } + + [viewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:formatString + options:0 + metrics:@{ @"bottomSpacing" : @(4) } + views:views]]; + + [viewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-leftSpacing-[logoBug]" + options:0 + metrics:@{ @"leftSpacing" : @(8) } + views:views]]; + } + } + + if (_attributionButton) + { + if ( ! [[viewController.view valueForKeyPath:@"constraints.firstItem"] containsObject:_attributionButton] && + ! [[viewController.view valueForKeyPath:@"constraints.secondItem"] containsObject:_attributionButton]) + { + NSString *formatString; + NSDictionary *views; + + if (RMPostVersion7) + { + formatString = @"V:[attributionButton]-bottomSpacing-[bottomLayoutGuide]"; + views = @{ @"attributionButton" : _attributionButton, + @"bottomLayoutGuide" : viewController.bottomLayoutGuide }; + } + else + { + formatString = @"V:[attributionButton]-bottomSpacing-|"; + views = @{ @"attributionButton" : _attributionButton }; + } + + [viewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:formatString + options:0 + metrics:@{ @"bottomSpacing" : @(8) } + views:views]]; + + [viewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[attributionButton]-rightSpacing-|" + options:0 + metrics:@{ @"rightSpacing" : @(8) } + views:views]]; + } + } + + [super updateConstraints]; +} + +- (void)layoutSubviews +{ + if ( ! _mapScrollView) + { + // This will happen after initWithCoder: This needs to happen here because during + // unarchiving, the view won't have a frame yet and performInitialization... + // needs a scroll view frame in order to calculate _metersPerPixel. + // See https://github.com/mapbox/mapbox-ios-sdk/issues/270 + // + [self performInitializationWithTilesource:[RMMapboxSource new] + centerCoordinate:CLLocationCoordinate2DMake(kDefaultInitialLatitude, kDefaultInitialLongitude) + zoomLevel:kDefaultInitialZoomLevel + maxZoomLevel:kDefaultMaximumZoomLevel + minZoomLevel:kDefaultMinimumZoomLevel + backgroundImage:nil]; + } + + if ( ! self.viewControllerPresentingAttribution && ! _hideAttribution) + { + self.viewControllerPresentingAttribution = [self viewController]; + } + else if (self.viewControllerPresentingAttribution && _hideAttribution) + { + self.viewControllerPresentingAttribution = nil; + } + + [super layoutSubviews]; +} + +- (void)removeFromSuperview +{ + self.viewControllerPresentingAttribution = nil; + + [super removeFromSuperview]; +} + - (NSString *)description { CGRect bounds = self.bounds; @@ -380,11 +676,6 @@ - (NSString *)description #pragma mark - #pragma mark Delegate -- (id )delegate -{ - return _delegate; -} - - (void)setDelegate:(id )aDelegate { if (_delegate == aDelegate) @@ -392,33 +683,37 @@ - (void)setDelegate:(id )aDelegate _delegate = aDelegate; - _delegateHasBeforeMapMove = [_delegate respondsToSelector:@selector(beforeMapMove:)]; - _delegateHasAfterMapMove = [_delegate respondsToSelector:@selector(afterMapMove:)]; + _delegateHasBeforeMapMove = [_delegate respondsToSelector:@selector(beforeMapMove:byUser:)]; + _delegateHasAfterMapMove = [_delegate respondsToSelector:@selector(afterMapMove:byUser:)]; - _delegateHasBeforeMapZoom = [_delegate respondsToSelector:@selector(beforeMapZoom:)]; - _delegateHasAfterMapZoom = [_delegate respondsToSelector:@selector(afterMapZoom:)]; + _delegateHasBeforeMapZoom = [_delegate respondsToSelector:@selector(beforeMapZoom:byUser:)]; + _delegateHasAfterMapZoom = [_delegate respondsToSelector:@selector(afterMapZoom:byUser:)]; _delegateHasMapViewRegionDidChange = [_delegate respondsToSelector:@selector(mapViewRegionDidChange:)]; _delegateHasDoubleTapOnMap = [_delegate respondsToSelector:@selector(doubleTapOnMap:at:)]; - _delegateHasDoubleTapTwoFingersOnMap = [_delegate respondsToSelector:@selector(doubleTapTwoFingersOnMap:at:)]; _delegateHasSingleTapOnMap = [_delegate respondsToSelector:@selector(singleTapOnMap:at:)]; _delegateHasSingleTapTwoFingersOnMap = [_delegate respondsToSelector:@selector(singleTapTwoFingersOnMap:at:)]; - _delegateHasLongSingleTapOnMap = [_delegate respondsToSelector:@selector(longSingleTapOnMap:at:)]; + _delegateHasLongPressOnMap = [_delegate respondsToSelector:@selector(longPressOnMap:at:)]; _delegateHasTapOnAnnotation = [_delegate respondsToSelector:@selector(tapOnAnnotation:onMap:)]; _delegateHasDoubleTapOnAnnotation = [_delegate respondsToSelector:@selector(doubleTapOnAnnotation:onMap:)]; + _delegateHasLongPressOnAnnotation = [_delegate respondsToSelector:@selector(longPressOnAnnotation:onMap:)]; + _delegateHasTapOnCalloutAccessoryControlForAnnotation = [_delegate respondsToSelector:@selector(tapOnCalloutAccessoryControl:forAnnotation:onMap:)]; _delegateHasTapOnLabelForAnnotation = [_delegate respondsToSelector:@selector(tapOnLabelForAnnotation:onMap:)]; _delegateHasDoubleTapOnLabelForAnnotation = [_delegate respondsToSelector:@selector(doubleTapOnLabelForAnnotation:onMap:)]; - _delegateHasShouldDragMarker = [_delegate respondsToSelector:@selector(mapView:shouldDragAnnotation:)]; - _delegateHasDidDragMarker = [_delegate respondsToSelector:@selector(mapView:didDragAnnotation:withDelta:)]; - _delegateHasDidEndDragMarker = [_delegate respondsToSelector:@selector(mapView:didEndDragAnnotation:)]; + _delegateHasShouldDragAnnotation = [_delegate respondsToSelector:@selector(mapView:shouldDragAnnotation:)]; + _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:)]; + _delegateHasDidSelectAnnotation = [_delegate respondsToSelector:@selector(mapView:didSelectAnnotation:)]; + _delegateHasDidDeselectAnnotation = [_delegate respondsToSelector:@selector(mapView:didDeselectAnnotation:)]; + _delegateHasWillStartLocatingUser = [_delegate respondsToSelector:@selector(mapViewWillStartLocatingUser:)]; _delegateHasDidStopLocatingUser = [_delegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)]; _delegateHasDidUpdateUserLocation = [_delegate respondsToSelector:@selector(mapView:didUpdateUserLocation:)]; @@ -426,6 +721,94 @@ - (void)setDelegate:(id )aDelegate _delegateHasDidChangeUserTrackingMode = [_delegate respondsToSelector:@selector(mapView:didChangeUserTrackingMode:animated:)]; } +- (void)registerMoveEventByUser:(BOOL)wasUserEvent +{ + @synchronized (_moveDelegateQueue) + { + BOOL flag = wasUserEvent; + + __weak RMMapView *weakSelf = self; + __weak id weakDelegate = _delegate; + BOOL hasBeforeMapMove = _delegateHasBeforeMapMove; + BOOL hasAfterMapMove = _delegateHasAfterMapMove; + + if ([_moveDelegateQueue operationCount] == 0) + { + dispatch_async(dispatch_get_main_queue(), ^(void) + { + if (hasBeforeMapMove) + [weakDelegate beforeMapMove:weakSelf byUser:flag]; + }); + } + + [_moveDelegateQueue setSuspended:YES]; + + if ([_moveDelegateQueue operationCount] == 0) + { + [_moveDelegateQueue addOperationWithBlock:^(void) + { + dispatch_async(dispatch_get_main_queue(), ^(void) + { + if (hasAfterMapMove) + [weakDelegate afterMapMove:weakSelf byUser:flag]; + }); + }]; + } + } +} + +- (void)completeMoveEventAfterDelay:(NSTimeInterval)delay +{ + if ( ! delay) + [_moveDelegateQueue setSuspended:NO]; + else + [_moveDelegateQueue performSelector:@selector(setSuspended:) withObject:[NSNumber numberWithBool:NO] afterDelay:delay]; +} + +- (void)registerZoomEventByUser:(BOOL)wasUserEvent +{ + @synchronized (_zoomDelegateQueue) + { + BOOL flag = wasUserEvent; + + __weak RMMapView *weakSelf = self; + __weak id weakDelegate = _delegate; + BOOL hasBeforeMapZoom = _delegateHasBeforeMapZoom; + BOOL hasAfterMapZoom = _delegateHasAfterMapZoom; + + if ([_zoomDelegateQueue operationCount] == 0) + { + dispatch_async(dispatch_get_main_queue(), ^(void) + { + if (hasBeforeMapZoom) + [weakDelegate beforeMapZoom:weakSelf byUser:flag]; + }); + } + + [_zoomDelegateQueue setSuspended:YES]; + + if ([_zoomDelegateQueue operationCount] == 0) + { + [_zoomDelegateQueue addOperationWithBlock:^(void) + { + dispatch_async(dispatch_get_main_queue(), ^(void) + { + if (hasAfterMapZoom) + [weakDelegate afterMapZoom:weakSelf byUser:flag]; + }); + }]; + } + } +} + +- (void)completeZoomEventAfterDelay:(NSTimeInterval)delay +{ + if ( ! delay) + [_zoomDelegateQueue setSuspended:NO]; + else + [_zoomDelegateQueue performSelector:@selector(setSuspended:) withObject:[NSNumber numberWithBool:NO] afterDelay:delay]; +} + #pragma mark - #pragma mark Bounds @@ -455,8 +838,6 @@ - (RMProjectedRect)fitProjectedRect:(RMProjectedRect)rect1 intoRect:(RMProjected - (RMProjectedRect)projectedRectFromLatitudeLongitudeBounds:(RMSphericalTrapezium)bounds { - float pixelBuffer = kZoomRectPixelBuffer; - CLLocationCoordinate2D southWest = bounds.southWest; CLLocationCoordinate2D northEast = bounds.northEast; CLLocationCoordinate2D midpoint = { @@ -481,26 +862,24 @@ - (RMProjectedRect)projectedRectFromLatitudeLongitudeBounds:(RMSphericalTrapeziu if ((myPoint.x / self.bounds.size.width) < (myPoint.y / self.bounds.size.height)) { - if ((myPoint.y / (self.bounds.size.height - pixelBuffer)) > 1) + if ((myPoint.y / self.bounds.size.height) > 1) { - zoomRect.size.width = self.bounds.size.width * (myPoint.y / (self.bounds.size.height - pixelBuffer)); - zoomRect.size.height = self.bounds.size.height * (myPoint.y / (self.bounds.size.height - pixelBuffer)); + zoomRect.size.width = self.bounds.size.width * (myPoint.y / self.bounds.size.height); + zoomRect.size.height = self.bounds.size.height * (myPoint.y / self.bounds.size.height); } } else { - if ((myPoint.x / (self.bounds.size.width - pixelBuffer)) > 1) + if ((myPoint.x / self.bounds.size.width) > 1) { - zoomRect.size.width = self.bounds.size.width * (myPoint.x / (self.bounds.size.width - pixelBuffer)); - zoomRect.size.height = self.bounds.size.height * (myPoint.x / (self.bounds.size.width - pixelBuffer)); + zoomRect.size.width = self.bounds.size.width * (myPoint.x / self.bounds.size.width); + zoomRect.size.height = self.bounds.size.height * (myPoint.x / self.bounds.size.width); } } myOrigin.x = myOrigin.x - (zoomRect.size.width / 2); myOrigin.y = myOrigin.y - (zoomRect.size.height / 2); - RMLog(@"Origin is calculated at: %f, %f", [_projection projectedPointToCoordinate:myOrigin].longitude, [_projection projectedPointToCoordinate:myOrigin].latitude); - zoomRect.origin = myOrigin; // RMLog(@"Origin: x=%f, y=%f, w=%f, h=%f", zoomRect.origin.easting, zoomRect.origin.northing, zoomRect.size.width, zoomRect.size.height); @@ -540,8 +919,38 @@ - (void)setConstraintsSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLL - (void)setProjectedConstraintsSouthWest:(RMProjectedPoint)southWest northEast:(RMProjectedPoint)northEast { - _constrainMovement = YES; + _constrainMovement = _constrainMovementByUser = YES; _constrainingProjectedBounds = RMProjectedRectMake(southWest.x, southWest.y, northEast.x - southWest.x, northEast.y - southWest.y); + _constrainingProjectedBoundsByUser = RMProjectedRectMake(southWest.x, southWest.y, northEast.x - southWest.x, northEast.y - southWest.y); +} + +- (void)setTileSourcesConstraintsFromLatitudeLongitudeBoundingBox:(RMSphericalTrapezium)bounds +{ + BOOL tileSourcesConstrainMovement = !(bounds.northEast.latitude == 90.0 && bounds.northEast.longitude == 180.0 && bounds.southWest.latitude == -90.0 && bounds.southWest.longitude == -180.0); + + if (tileSourcesConstrainMovement) + { + _constrainMovement = YES; + RMProjectedRect tileSourcesConstrainingProjectedBounds = [self projectedRectFromLatitudeLongitudeBounds:bounds]; + + if (_constrainMovementByUser) + { + _constrainingProjectedBounds = RMProjectedRectIntersection(_constrainingProjectedBoundsByUser, tileSourcesConstrainingProjectedBounds); + + if (RMProjectedRectIsZero(_constrainingProjectedBounds)) + RMLog(@"The constraining bounds from tilesources and user don't intersect!"); + } + else + _constrainingProjectedBounds = tileSourcesConstrainingProjectedBounds; + } + else if (_constrainMovementByUser) + { + _constrainingProjectedBounds = _constrainingProjectedBoundsByUser; + } + else + { + _constrainingProjectedBounds = _projection.planetBounds; + } } #pragma mark - @@ -554,7 +963,7 @@ - (CLLocationCoordinate2D)centerCoordinate - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate { - [self setCenterProjectedPoint:[_projection coordinateToProjectedPoint:centerCoordinate]]; + [self setCenterCoordinate:centerCoordinate animated:NO]; } - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate animated:(BOOL)animated @@ -580,13 +989,15 @@ - (RMProjectedPoint)centerProjectedPoint - (void)setCenterProjectedPoint:(RMProjectedPoint)centerProjectedPoint { - [self setCenterProjectedPoint:centerProjectedPoint animated:YES]; + [self setCenterProjectedPoint:centerProjectedPoint animated:NO]; } - (void)setCenterProjectedPoint:(RMProjectedPoint)centerProjectedPoint animated:(BOOL)animated { - if (_delegateHasBeforeMapMove) - [_delegate beforeMapMove:self]; + if (RMProjectedPointEqualToProjectedPoint(centerProjectedPoint, [self centerProjectedPoint])) + return; + + [self registerMoveEventByUser:NO]; // RMLog(@"Current contentSize: {%.0f,%.0f}, zoom: %f", mapScrollView.contentSize.width, mapScrollView.contentSize.height, self.zoom); @@ -601,8 +1012,8 @@ - (void)setCenterProjectedPoint:(RMProjectedPoint)centerProjectedPoint animated: // RMLog(@"setMapCenterProjectedPoint: {%f,%f} -> {%.0f,%.0f}", centerProjectedPoint.x, centerProjectedPoint.y, mapScrollView.contentOffset.x, mapScrollView.contentOffset.y); - if (_delegateHasAfterMapMove && !animated) - [_delegate afterMapMove:self]; + if ( ! animated) + [self completeMoveEventAfterDelay:0]; [self correctPositionOfAllAnnotations]; } @@ -611,46 +1022,19 @@ - (void)setCenterProjectedPoint:(RMProjectedPoint)centerProjectedPoint animated: - (void)moveBy:(CGSize)delta { - if (_delegateHasBeforeMapMove) - [_delegate beforeMapMove:self]; + [self registerMoveEventByUser:NO]; CGPoint contentOffset = _mapScrollView.contentOffset; contentOffset.x += delta.width; contentOffset.y += delta.height; _mapScrollView.contentOffset = contentOffset; - if (_delegateHasAfterMapMove) - [_delegate afterMapMove:self]; + [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)); @@ -688,55 +1072,13 @@ - (void)setProjectedBounds:(RMProjectedRect)boundsRect animated:(BOOL)animated [_mapScrollView zoomToRect:zoomRect animated:animated]; } -- (float)adjustedZoomForCurrentBoundingMask:(float)zoomFactor +- (BOOL)shouldZoomToTargetZoom:(float)targetZoom withZoomFactor:(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 - BOOL zoomAtMax = ([self zoom] == [self maxZoom]); - BOOL zoomAtMin = ([self zoom] == [self minZoom]); - BOOL zoomGreaterMin = ([self zoom] > [self minZoom]); - BOOL zoomLessMax = ([self zoom] < [self maxZoom]); + // bools for syntactical sugar to understand the logic in the if statement below + BOOL zoomAtMax = ([self zoom] == [self maxZoom]); + BOOL zoomAtMin = ([self zoom] == [self minZoom]); + BOOL zoomGreaterMin = ([self zoom] > [self minZoom]); + BOOL zoomLessMax = ([self zoom] < [self maxZoom]); //zooming in zoomFactor > 1 //zooming out zoomFactor < 1 @@ -746,12 +1088,41 @@ - (BOOL)shouldZoomToTargetZoom:(float)targetZoom withZoomFactor:(float)zoomFacto return NO; } +- (void)setZoom:(float)newZoom animated:(BOOL)animated +{ + [self setZoom:newZoom atCoordinate:self.centerCoordinate animated:animated]; +} + +- (void)setZoom:(float)newZoom atCoordinate:(CLLocationCoordinate2D)newCenter animated:(BOOL)animated +{ + if (animated) + { + [UIView animateWithDuration:0.3 + delay:0.0 + options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseInOut + animations:^(void) + { + [self setZoom:newZoom]; + [self setCenterCoordinate:newCenter animated:NO]; + + self.userTrackingMode = RMUserTrackingModeNone; + } + completion:nil]; + } + else + { + [self setZoom:newZoom]; + [self setCenterCoordinate:newCenter animated:NO]; + + self.userTrackingMode = RMUserTrackingModeNone; + } +} + - (void)zoomByFactor:(float)zoomFactor near:(CGPoint)pivot animated:(BOOL)animated { if (![self tileSourceBoundsContainScreenPoint:pivot]) return; - zoomFactor = [self adjustedZoomForCurrentBoundingMask:zoomFactor]; float zoomDelta = log2f(zoomFactor); float targetZoom = zoomDelta + [self zoom]; @@ -817,20 +1188,17 @@ - (void)zoomInToNextNativeZoomAt:(CGPoint)pivot - (void)zoomInToNextNativeZoomAt:(CGPoint)pivot animated:(BOOL)animated { - if (self.userTrackingMode != RMUserTrackingModeNone && ! CGPointEqualToPoint(pivot, self.center)) + if (self.userTrackingMode != RMUserTrackingModeNone && ! CGPointEqualToPoint(pivot, [self coordinateToPixel:self.userLocation.location.coordinate])) self.userTrackingMode = RMUserTrackingModeNone; // Calculate rounded zoom - float newZoom = fmin(ceilf([self zoom]) + 0.99, [self maxZoom]); - - if (newZoom == self.zoom) - return; + float newZoom = fmin(ceilf([self zoom]) + 1.0, [self maxZoom]); float factor = exp2f(newZoom - [self zoom]); if (factor > 2.25) { - newZoom = fmin(ceilf([self zoom]) - 0.01, [self maxZoom]); + newZoom = fmin(ceilf([self zoom]), [self maxZoom]); factor = exp2f(newZoom - [self zoom]); } @@ -846,16 +1214,13 @@ - (void)zoomOutToNextNativeZoomAt:(CGPoint)pivot - (void)zoomOutToNextNativeZoomAt:(CGPoint)pivot animated:(BOOL) animated { // Calculate rounded zoom - float newZoom = fmax(floorf([self zoom]) - 0.01, [self minZoom]); - - if (newZoom == self.zoom) - return; + float newZoom = fmax(floorf([self zoom]), [self minZoom]); float factor = exp2f(newZoom - [self zoom]); if (factor > 0.75) { - newZoom = fmax(floorf([self zoom]) - 1.01, [self minZoom]); + newZoom = fmax(floorf([self zoom]) - 1.0, [self minZoom]); factor = exp2f(newZoom - [self zoom]); } @@ -885,8 +1250,6 @@ - (void)zoomWithLatitudeLongitudeBoundsSouthWest:(CLLocationCoordinate2D)southWe else { // Convert northEast/southWest into RMMercatorRect and call zoomWithBounds - float pixelBuffer = kZoomRectPixelBuffer; - CLLocationCoordinate2D midpoint = { .latitude = (northEast.latitude + southWest.latitude) / 2, .longitude = (northEast.longitude + southWest.longitude) / 2 @@ -909,18 +1272,18 @@ - (void)zoomWithLatitudeLongitudeBoundsSouthWest:(CLLocationCoordinate2D)southWe if ((myPoint.x / self.bounds.size.width) < (myPoint.y / self.bounds.size.height)) { - if ((myPoint.y / (self.bounds.size.height - pixelBuffer)) > 1) + if ((myPoint.y / self.bounds.size.height) > 1) { - zoomRect.size.width = self.bounds.size.width * (myPoint.y / (self.bounds.size.height - pixelBuffer)); - zoomRect.size.height = self.bounds.size.height * (myPoint.y / (self.bounds.size.height - pixelBuffer)); + zoomRect.size.width = self.bounds.size.width * (myPoint.y / self.bounds.size.height); + zoomRect.size.height = self.bounds.size.height * (myPoint.y / self.bounds.size.height); } } else { - if ((myPoint.x / (self.bounds.size.width - pixelBuffer)) > 1) + if ((myPoint.x / self.bounds.size.width) > 1) { - zoomRect.size.width = self.bounds.size.width * (myPoint.x / (self.bounds.size.width - pixelBuffer)); - zoomRect.size.height = self.bounds.size.height * (myPoint.x / (self.bounds.size.width - pixelBuffer)); + zoomRect.size.width = self.bounds.size.width * (myPoint.x / self.bounds.size.width); + zoomRect.size.height = self.bounds.size.height * (myPoint.x / self.bounds.size.width); } } @@ -947,39 +1310,40 @@ - (void)createMapView { [_tileSourcesContainer cancelAllDownloads]; - [_overlayView removeFromSuperview]; [_overlayView release]; _overlayView = nil; + [_overlayView removeFromSuperview]; _overlayView = nil; - for (RMMapTiledLayerView *tiledLayerView in _tiledLayersSuperview.subviews) + for (__strong RMMapTiledLayerView *tiledLayerView in _tiledLayersSuperview.subviews) { tiledLayerView.layer.contents = nil; - [tiledLayerView removeFromSuperview]; [tiledLayerView release]; tiledLayerView = nil; + [tiledLayerView removeFromSuperview]; tiledLayerView = nil; } - [_tiledLayersSuperview removeFromSuperview]; [_tiledLayersSuperview release]; _tiledLayersSuperview = nil; + [_tiledLayersSuperview removeFromSuperview]; _tiledLayersSuperview = nil; [_mapScrollView removeObserver:self forKeyPath:@"contentOffset"]; - [_mapScrollView removeFromSuperview]; [_mapScrollView release]; _mapScrollView = nil; + [_mapScrollView removeFromSuperview]; _mapScrollView = nil; _mapScrollViewIsZooming = NO; - int tileSideLength = [_tileSourcesContainer tileSideLength]; + NSUInteger tileSideLength = [_tileSourcesContainer tileSideLength]; CGSize contentSize = CGSizeMake(tileSideLength, tileSideLength); // zoom level 1 - _mapScrollView = [[RMMapScrollView alloc] initWithFrame:[self bounds]]; + _mapScrollView = [[RMMapScrollView alloc] initWithFrame:self.bounds]; _mapScrollView.delegate = self; _mapScrollView.opaque = NO; _mapScrollView.backgroundColor = [UIColor clearColor]; _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]); _mapScrollView.contentOffset = CGPointMake(0.0, 0.0); _mapScrollView.clipsToBounds = NO; + _mapScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _tiledLayersSuperview = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height)]; _tiledLayersSuperview.userInteractionEnabled = NO; @@ -988,10 +1352,7 @@ - (void)createMapView { RMMapTiledLayerView *tiledLayerView = [[RMMapTiledLayerView alloc] initWithFrame:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) mapView:self forTileSource:tileSource]; - if (self.adjustTilesForRetinaDisplay && _screenScale > 1.0) - ((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength * 2.0, tileSideLength * 2.0); - else - ((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength, tileSideLength); + ((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength, tileSideLength); [_tiledLayersSuperview addSubview:tiledLayerView]; } @@ -1016,50 +1377,38 @@ - (void)createMapView _overlayView = [[RMMapOverlayView alloc] initWithFrame:[self bounds]]; _overlayView.userInteractionEnabled = NO; + _overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self insertSubview:_overlayView aboveSubview:_mapScrollView]; // add gesture recognizers // one finger taps - UITapGestureRecognizer *doubleTapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)] autorelease]; + UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)]; doubleTapRecognizer.numberOfTouchesRequired = 1; doubleTapRecognizer.numberOfTapsRequired = 2; + doubleTapRecognizer.delegate = self; - UITapGestureRecognizer *singleTapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)] autorelease]; + UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; singleTapRecognizer.numberOfTouchesRequired = 1; [singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer]; + singleTapRecognizer.delegate = self; - UILongPressGestureRecognizer *longPressRecognizer = [[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)] autorelease]; + UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; + longPressRecognizer.minimumPressDuration = 0.25; + longPressRecognizer.allowableMovement = MAXFLOAT; + longPressRecognizer.delegate = self; [self addGestureRecognizer:singleTapRecognizer]; [self addGestureRecognizer:doubleTapRecognizer]; [self addGestureRecognizer:longPressRecognizer]; // two finger taps - UITapGestureRecognizer *twoFingerDoubleTapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerDoubleTap:)] autorelease]; - twoFingerDoubleTapRecognizer.numberOfTapsRequired = 2; - twoFingerDoubleTapRecognizer.numberOfTouchesRequired = 2; - - UITapGestureRecognizer *twoFingerSingleTapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerSingleTap:)] autorelease]; + UITapGestureRecognizer *twoFingerSingleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerSingleTap:)]; twoFingerSingleTapRecognizer.numberOfTouchesRequired = 2; - [twoFingerSingleTapRecognizer requireGestureRecognizerToFail:twoFingerDoubleTapRecognizer]; + twoFingerSingleTapRecognizer.delegate = self; [self addGestureRecognizer:twoFingerSingleTapRecognizer]; - [self addGestureRecognizer:twoFingerDoubleTapRecognizer]; - - // pan - UIPanGestureRecognizer *panGestureRecognizer = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)] autorelease]; - panGestureRecognizer.minimumNumberOfTouches = 1; - panGestureRecognizer.maximumNumberOfTouches = 1; - - // the delegate is used to decide whether a pan should be handled by this - // recognizer or by the pan gesture recognizer of the scrollview - panGestureRecognizer.delegate = self; - - // the pan recognizer is added to the scrollview as it competes with the - // pan recognizer of the scrollview - [_mapScrollView addGestureRecognizer:panGestureRecognizer]; [_visibleAnnotations removeAllObjects]; [self correctPositionOfAllAnnotations]; @@ -1072,17 +1421,16 @@ - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + [self registerMoveEventByUser:YES]; + if (self.userTrackingMode != RMUserTrackingModeNone) self.userTrackingMode = RMUserTrackingModeNone; - - if (_delegateHasBeforeMapMove) - [_delegate beforeMapMove:self]; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { - if (!decelerate && _delegateHasAfterMapMove) - [_delegate afterMapMove:self]; + if ( ! decelerate) + [self completeMoveEventAfterDelay:0]; } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView @@ -1093,43 +1441,66 @@ - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { - if (_delegateHasAfterMapMove) - [_delegate afterMapMove:self]; + [self completeMoveEventAfterDelay:0]; } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { - if (_delegateHasAfterMapMove) - [_delegate afterMapMove:self]; + [self completeMoveEventAfterDelay:0]; } - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { + [self registerZoomEventByUser:(scrollView.pinchGestureRecognizer.state == UIGestureRecognizerStateBegan)]; + _mapScrollViewIsZooming = YES; - if (_delegateHasBeforeMapZoom) - [_delegate beforeMapZoom:self]; + if (_loadingTileView) + _loadingTileView.mapZooming = YES; } - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale { + [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) + _loadingTileView.mapZooming = NO; +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + if (_loadingTileView) + { + CGSize delta = CGSizeMake(scrollView.contentOffset.x - _lastContentOffset.x, scrollView.contentOffset.y - _lastContentOffset.y); + CGPoint newOffset = CGPointMake(_loadingTileView.contentOffset.x + delta.width, _loadingTileView.contentOffset.y + delta.height); + _loadingTileView.contentOffset = newOffset; + } } - (void)scrollViewDidZoom:(UIScrollView *)scrollView { - if (self.userTrackingMode != RMUserTrackingModeNone && scrollView.pinchGestureRecognizer.state == UIGestureRecognizerStateChanged) + BOOL wasUserAction = (scrollView.pinchGestureRecognizer.state == UIGestureRecognizerStateChanged); + + [self registerZoomEventByUser:wasUserAction]; + + if (self.userTrackingMode != RMUserTrackingModeNone && wasUserAction) self.userTrackingMode = RMUserTrackingModeNone; [self correctPositionOfAllAnnotations]; if (_zoom < 3 && self.userTrackingMode == RMUserTrackingModeFollowWithHeading) self.userTrackingMode = RMUserTrackingModeFollow; - - if (_delegateHasAfterMapZoom) - [_delegate afterMapZoom:self]; } // Detect dragging/zooming @@ -1260,13 +1631,13 @@ - (void)observeValueForKeyPath:(NSString *)aKeyPath ofObject:(id)anObject change else { [self correctPositionOfAllAnnotationsIncludingInvisibles:NO animated:(_mapScrollViewIsZooming && !_mapScrollView.zooming)]; + _lastZoom = _zoom; } _lastContentOffset = _mapScrollView.contentOffset; _lastContentSize = _mapScrollView.contentSize; - // Don't do anything stupid here or your scrolling experience will suck if (_delegateHasMapViewRegionDidChange) [_delegate mapViewRegionDidChange:self]; } @@ -1296,7 +1667,12 @@ - (void)singleTapAtPoint:(CGPoint)aPoint - (void)handleSingleTap:(UIGestureRecognizer *)recognizer { - CALayer *hit = [_overlayView.layer hitTest:[recognizer locationInView:_overlayView]]; + CALayer *hit = [_overlayView overlayHitTest:[recognizer locationInView:self]]; + + if (_currentAnnotation && ! [hit isEqual:_currentAnnotation.layer]) + { + [self deselectAnnotation:_currentAnnotation animated:( ! [hit isKindOfClass:[RMMarker class]])]; + } if ( ! hit) { @@ -1306,10 +1682,10 @@ - (void)handleSingleTap:(UIGestureRecognizer *)recognizer CALayer *superlayer = [hit superlayer]; - // See if tap was on a marker or marker label and send delegate protocol method - if ([hit isKindOfClass:[RMMarker class]]) + // See if tap was on an annotation layer or marker label and send delegate protocol method + if ([hit isKindOfClass:[RMMapLayer class]]) { - [self tapOnAnnotation:[((RMMarker *)hit) annotation] atPoint:[recognizer locationInView:self]]; + [self tapOnAnnotation:[((RMMapLayer *)hit) annotation] atPoint:[recognizer locationInView:self]]; } else if (superlayer != nil && [superlayer isKindOfClass:[RMMarker class]]) { @@ -1327,10 +1703,25 @@ - (void)handleSingleTap:(UIGestureRecognizer *)recognizer - (void)doubleTapAtPoint:(CGPoint)aPoint { - if (self.zoomingInPivotsAroundCenter) - [self zoomInToNextNativeZoomAt:[self convertPoint:self.center fromView:self.superview] animated:YES]; - else - [self zoomInToNextNativeZoomAt:aPoint animated:YES]; + if (self.zoom < self.maxZoom) + { + [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]; + } + } if (_delegateHasDoubleTapOnMap) [_delegate doubleTapOnMap:self at:aPoint]; @@ -1338,7 +1729,7 @@ - (void)doubleTapAtPoint:(CGPoint)aPoint - (void)handleDoubleTap:(UIGestureRecognizer *)recognizer { - CALayer *hit = [_overlayView.layer hitTest:[recognizer locationInView:_overlayView]]; + CALayer *hit = [_overlayView overlayHitTest:[recognizer locationInView:self]]; if ( ! hit) { @@ -1367,17 +1758,19 @@ - (void)handleDoubleTap:(UIGestureRecognizer *)recognizer } } -- (void)handleTwoFingerDoubleTap:(UIGestureRecognizer *)recognizer +- (void)handleTwoFingerSingleTap:(UIGestureRecognizer *)recognizer { - [self zoomOutToNextNativeZoomAt:[self convertPoint:self.center fromView:self.superview] animated:YES]; + if (self.zoom > self.minZoom) + { + [self registerZoomEventByUser:YES]; - if (_delegateHasDoubleTapTwoFingersOnMap) - [_delegate doubleTapTwoFingersOnMap:self at:[recognizer locationInView:self]]; -} + CGPoint centerPoint = [self convertPoint:self.center fromView:self.superview]; -- (void)handleTwoFingerSingleTap:(UIGestureRecognizer *)recognizer -{ - [self zoomOutToNextNativeZoomAt:[self convertPoint:self.center fromView:self.superview] animated:YES]; + if (self.userTrackingMode != RMUserTrackingModeNone) + centerPoint = [self coordinateToPixel:self.userLocation.location.coordinate]; + + [self zoomOutToNextNativeZoomAt:centerPoint animated:YES]; + } if (_delegateHasSingleTapTwoFingersOnMap) [_delegate singleTapTwoFingersOnMap:self at:[recognizer locationInView:self]]; @@ -1385,73 +1778,112 @@ - (void)handleTwoFingerSingleTap:(UIGestureRecognizer *)recognizer - (void)handleLongPress:(UILongPressGestureRecognizer *)recognizer { - if (recognizer.state != UIGestureRecognizerStateBegan) + if ( ! _delegateHasLongPressOnMap && ! _delegateHasLongPressOnAnnotation && ! _delegateHasShouldDragAnnotation) return; - if (_delegateHasLongSingleTapOnMap) - [_delegate longSingleTapOnMap:self at:[recognizer locationInView:self]]; -} + CALayer *hit = _draggedAnnotation.layer; -// defines when the additional pan gesture recognizer on the scroll should handle the gesture -- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)recognizer -{ - if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) + if ( ! _draggedAnnotation) { - // check whether our custom pan gesture recognizer should start recognizing the gesture - CALayer *hit = [_overlayView.layer hitTest:[recognizer locationInView:_overlayView]]; - - if ([hit isEqual:_overlayView.layer]) - return NO; - - if (!hit || ([hit respondsToSelector:@selector(enableDragging)] && ![(RMMarker *)hit enableDragging])) - return NO; + hit = [_overlayView overlayHitTest:[recognizer locationInView:self]]; - if ( ! [self shouldDragAnnotation:[self findAnnotationInLayer:hit]]) - return NO; + // deselect any annotation that we're about to drag + // + if (_currentAnnotation && [hit isEqual:_currentAnnotation.layer]) + [self deselectAnnotation:_currentAnnotation animated:NO]; } - return YES; -} - -- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer -{ - if (recognizer.state == UIGestureRecognizerStateBegan) + if ([hit isKindOfClass:[RMMapLayer class]] && [self shouldDragAnnotation:[((RMMapLayer *)hit) annotation]]) { - CALayer *hit = [_overlayView.layer hitTest:[recognizer locationInView:self]]; + // handle annotation drags + // + if ( ! _draggedAnnotation && recognizer.state == UIGestureRecognizerStateBegan) + { + // note the annotation + // + _draggedAnnotation = [((RMMapLayer *)hit) annotation]; - if ( ! hit) - return; + // remember where in the layer the gesture occurred + // + _dragOffset = [_draggedAnnotation.layer convertPoint:[recognizer locationInView:self] fromLayer:self.layer]; - if ([hit respondsToSelector:@selector(enableDragging)] && ![(RMMarker *)hit enableDragging]) - return; + // inform the layer + // + [_draggedAnnotation.layer setDragState:RMMapLayerDragStateStarting animated:YES]; - _lastDraggingTranslation = CGPointZero; - [_draggedAnnotation release]; - _draggedAnnotation = [[self findAnnotationInLayer:hit] retain]; - } + // bring to top + // + _draggedAnnotation.layer.zPosition = MAXFLOAT; + } + else if (_draggedAnnotation && recognizer.state == UIGestureRecognizerStateChanged && _draggedAnnotation.layer.dragState == RMMapLayerDragStateDragging) + { + // perform the drag (unanimated for fluidity) + // + [CATransaction begin]; + [CATransaction setDisableActions:YES]; - if (recognizer.state == UIGestureRecognizerStateChanged) - { - CGPoint translation = [recognizer translationInView:_overlayView]; - CGPoint delta = CGPointMake(_lastDraggingTranslation.x - translation.x, _lastDraggingTranslation.y - translation.y); - _lastDraggingTranslation = translation; + CGSize layerSize = _draggedAnnotation.layer.bounds.size; + CGPoint gesturePoint = [recognizer locationInView:self]; + CGPoint newPosition = CGPointMake(gesturePoint.x + ((layerSize.width / 2) - _dragOffset.x), gesturePoint.y + ((layerSize.height / 2) - _dragOffset.y)); - [CATransaction begin]; - [CATransaction setAnimationDuration:0]; - [self didDragAnnotation:_draggedAnnotation withDelta:delta]; - [CATransaction commit]; + _draggedAnnotation.position = newPosition; + + [CATransaction commit]; + } + else if (_draggedAnnotation && recognizer.state == UIGestureRecognizerStateCancelled) + { + // cancel & go back to start point + // + [_draggedAnnotation.layer setDragState:RMMapLayerDragStateCanceling animated:YES]; + + _draggedAnnotation.position = [self coordinateToPixel:_draggedAnnotation.coordinate]; + + [self correctOrderingOfAllAnnotations]; + + _draggedAnnotation = nil; + } + else if (_draggedAnnotation && recognizer.state == UIGestureRecognizerStateEnded) + { + // complete drag & update coordinate + // + [_draggedAnnotation.layer setDragState:RMMapLayerDragStateEnding animated:YES]; + + _draggedAnnotation.coordinate = [self pixelToCoordinate:_draggedAnnotation.position]; + + [self correctOrderingOfAllAnnotations]; + + _draggedAnnotation = nil; + } } - else if (recognizer.state == UIGestureRecognizerStateEnded) + else if (recognizer.state == UIGestureRecognizerStateBegan && [hit isKindOfClass:[RMMapLayer class]] && _delegateHasLongPressOnAnnotation) { - [self didEndDragAnnotation:_draggedAnnotation]; - [_draggedAnnotation release]; _draggedAnnotation = nil; + // pass annotation long-press to delegate + // + [_delegate longPressOnAnnotation:[((RMMapLayer *)hit) annotation] onMap:self]; + } + else if (recognizer.state == UIGestureRecognizerStateBegan && _delegateHasLongPressOnMap) + { + // pass map long-press to delegate + // + [_delegate longPressOnMap:self at:[recognizer locationInView:self]]; } } +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch +{ + if ([touch.view isKindOfClass:[UIControl class]]) + return NO; + + return YES; +} + // Overlay - (void)tapOnAnnotation:(RMAnnotation *)anAnnotation atPoint:(CGPoint)aPoint { + if (anAnnotation.isEnabled && ! [anAnnotation isEqual:_currentAnnotation]) + [self selectAnnotation:anAnnotation animated:YES]; + if (_delegateHasTapOnAnnotation && anAnnotation) { [_delegate tapOnAnnotation:anAnnotation onMap:self]; @@ -1463,6 +1895,134 @@ - (void)tapOnAnnotation:(RMAnnotation *)anAnnotation atPoint:(CGPoint)aPoint } } +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event +{ + if (_currentCallout) + { + UIView *calloutCandidate = [_currentCallout hitTest:[_currentCallout convertPoint:point fromView:self] withEvent:event]; + + if (calloutCandidate) + return calloutCandidate; + } + + return [super hitTest:point withEvent:event]; +} + +- (void)selectAnnotation:(RMAnnotation *)anAnnotation animated:(BOOL)animated +{ + if ( ! anAnnotation && _currentAnnotation) + { + [self deselectAnnotation:_currentAnnotation animated:animated]; + } + else if (anAnnotation.isEnabled && ! [anAnnotation isEqual:_currentAnnotation]) + { + self.userTrackingMode = RMUserTrackingModeNone; + + [self deselectAnnotation:_currentAnnotation animated:NO]; + + _currentAnnotation = anAnnotation; + + if (anAnnotation.layer.canShowCallout && anAnnotation.title) + { + _currentCallout = [SMCalloutView platformCalloutView]; + + if (RMPostVersion7) + _currentCallout.tintColor = self.tintColor; + + _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:)]]; + + _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:)]]; + + _currentCallout.rightAccessoryView = anAnnotation.layer.rightCalloutAccessoryView; + } + + _currentCallout.delegate = self; + + _currentCallout.permittedArrowDirection = SMCalloutArrowDirectionDown; + + [_currentCallout presentCalloutFromRect:anAnnotation.layer.bounds + inLayer:anAnnotation.layer + constrainedToLayer:self.layer + animated:animated]; + } + + [self correctPositionOfAllAnnotations]; + + anAnnotation.layer.zPosition = _currentCallout.layer.zPosition = MAXFLOAT; + + if (_delegateHasDidSelectAnnotation) + [_delegate mapView:self didSelectAnnotation:anAnnotation]; + } +} + +- (void)deselectAnnotation:(RMAnnotation *)annotation animated:(BOOL)animated +{ + if ([annotation isEqual:_currentAnnotation]) + { + [_currentCallout dismissCalloutAnimated:animated]; + + if (animated) + [self performSelector:@selector(correctPositionOfAllAnnotations) withObject:nil afterDelay:1.0/3.0]; + else + [self correctPositionOfAllAnnotations]; + + _currentAnnotation = nil; + _currentCallout = nil; + + if (_delegateHasDidDeselectAnnotation) + [_delegate mapView:self didDeselectAnnotation:annotation]; + } +} + +- (void)setSelectedAnnotation:(RMAnnotation *)selectedAnnotation +{ + [self selectAnnotation:selectedAnnotation animated:YES]; +} + +- (RMAnnotation *)selectedAnnotation +{ + return _currentAnnotation; +} + +- (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset +{ + [self registerMoveEventByUser:NO]; + + CGPoint contentOffset = _mapScrollView.contentOffset; + + contentOffset.x -= offset.width; + contentOffset.y -= offset.height; + + if (RMPostVersion7) + contentOffset.y -= [[[self viewController] topLayoutGuide] length]; + + [_mapScrollView setContentOffset:contentOffset animated:YES]; + + [self completeMoveEventAfterDelay:kSMCalloutViewRepositionDelayForUIScrollView]; + + return kSMCalloutViewRepositionDelayForUIScrollView; +} + +- (void)tapOnCalloutAccessoryWithGestureRecognizer:(UIGestureRecognizer *)recognizer +{ + if (_delegateHasTapOnCalloutAccessoryControlForAnnotation) + [_delegate tapOnCalloutAccessoryControl:(UIControl *)recognizer.view forAnnotation:_currentAnnotation onMap:self]; +} + - (void)doubleTapOnAnnotation:(RMAnnotation *)anAnnotation atPoint:(CGPoint)aPoint { if (_delegateHasDoubleTapOnAnnotation && anAnnotation) @@ -1510,22 +2070,16 @@ - (void)doubleTapOnLabelForAnnotation:(RMAnnotation *)anAnnotation atPoint:(CGPo - (BOOL)shouldDragAnnotation:(RMAnnotation *)anAnnotation { - if (_delegateHasShouldDragMarker) + if ( ! anAnnotation.isUserLocationAnnotation && ! anAnnotation.isClusterAnnotation && _delegateHasShouldDragAnnotation) return [_delegate mapView:self shouldDragAnnotation:anAnnotation]; else return NO; } -- (void)didDragAnnotation:(RMAnnotation *)anAnnotation withDelta:(CGPoint)delta -{ - if (_delegateHasDidDragMarker) - [_delegate mapView:self didDragAnnotation:anAnnotation withDelta:delta]; -} - -- (void)didEndDragAnnotation:(RMAnnotation *)anAnnotation +- (void)annotation:(RMAnnotation *)annotation didChangeDragState:(RMMapLayerDragState)newState fromOldState:(RMMapLayerDragState)oldState { - if (_delegateHasDidEndDragMarker) - [_delegate mapView:self didEndDragAnnotation:anAnnotation]; + if (_delegateHasDidChangeDragState) + [_delegate mapView:self annotation:annotation didChangeDragState:newState fromOldState:oldState]; } #pragma mark - @@ -1563,7 +2117,7 @@ - (UIImage *)takeSnapshot - (RMTileSourcesContainer *)tileSourcesContainer { - return [[_tileSourcesContainer retain] autorelease]; + return _tileSourcesContainer; } - (id )tileSource @@ -1583,34 +2137,38 @@ - (NSArray *)tileSources - (void)setTileSource:(id )tileSource { - [_tileSourcesContainer removeAllTileSources]; - [self addTileSource:tileSource]; + if (tileSource) + { + [_tileSourcesContainer removeAllTileSources]; + [self addTileSource: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; RMProjectedPoint centerPoint = [self centerProjectedPoint]; - [_projection release]; - _projection = [[_tileSourcesContainer projection] retain]; - - [_mercatorToTileProjection release]; - _mercatorToTileProjection = [[_tileSourcesContainer mercatorToTileProjection] retain]; + _projection = [_tileSourcesContainer projection]; - RMSphericalTrapezium bounds = [_tileSourcesContainer latitudeLongitudeBoundingBox]; + _mercatorToTileProjection = [_tileSourcesContainer mercatorToTileProjection]; - _constrainMovement = !(bounds.northEast.latitude == 90.0 && bounds.northEast.longitude == 180.0 && bounds.southWest.latitude == -90.0 && bounds.southWest.longitude == -180.0); + [self setTileSourcesConstraintsFromLatitudeLongitudeBoundingBox:[_tileSourcesContainer latitudeLongitudeBoundingBox]]; - if (_constrainMovement) - _constrainingProjectedBounds = (RMProjectedRect)[self projectedRectFromLatitudeLongitudeBounds:bounds]; - else - _constrainingProjectedBounds = _projection.planetBounds; - - [self setMinZoom:_tileSourcesContainer.minZoom]; - [self setMaxZoom:_tileSourcesContainer.maxZoom]; + [self setTileSourcesMinZoom:_tileSourcesContainer.minZoom]; + [self setTileSourcesMaxZoom:_tileSourcesContainer.maxZoom]; [self setZoom:[self zoom]]; // setZoom clamps zoom level to min/max limits // Recreate the map layer @@ -1626,6 +2184,16 @@ - (void)addTileSource:(id )tileSource - (void)addTileSource:(id)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; @@ -1634,23 +2202,14 @@ - (void)addTileSource:(id)newTileSource atIndex:(NSUInteger)index RMProjectedPoint centerPoint = [self centerProjectedPoint]; - [_projection release]; - _projection = [[_tileSourcesContainer projection] retain]; - - [_mercatorToTileProjection release]; - _mercatorToTileProjection = [[_tileSourcesContainer mercatorToTileProjection] retain]; + _projection = [_tileSourcesContainer projection]; - RMSphericalTrapezium bounds = [_tileSourcesContainer latitudeLongitudeBoundingBox]; + _mercatorToTileProjection = [_tileSourcesContainer mercatorToTileProjection]; - _constrainMovement = !(bounds.northEast.latitude == 90.0 && bounds.northEast.longitude == 180.0 && bounds.southWest.latitude == -90.0 && bounds.southWest.longitude == -180.0); - - if (_constrainMovement) - _constrainingProjectedBounds = (RMProjectedRect)[self projectedRectFromLatitudeLongitudeBounds:bounds]; - else - _constrainingProjectedBounds = _projection.planetBounds; + [self setTileSourcesConstraintsFromLatitudeLongitudeBoundingBox:[_tileSourcesContainer latitudeLongitudeBoundingBox]]; - [self setMinZoom:_tileSourcesContainer.minZoom]; - [self setMaxZoom:_tileSourcesContainer.maxZoom]; + [self setTileSourcesMinZoom:_tileSourcesContainer.minZoom]; + [self setTileSourcesMaxZoom:_tileSourcesContainer.maxZoom]; [self setZoom:[self zoom]]; // setZoom clamps zoom level to min/max limits // Recreate the map layer @@ -1662,15 +2221,12 @@ - (void)addTileSource:(id)newTileSource atIndex:(NSUInteger)index } else { - int tileSideLength = [_tileSourcesContainer tileSideLength]; + NSUInteger tileSideLength = [_tileSourcesContainer tileSideLength]; CGSize contentSize = CGSizeMake(tileSideLength, tileSideLength); // zoom level 1 RMMapTiledLayerView *tiledLayerView = [[RMMapTiledLayerView alloc] initWithFrame:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) mapView:self forTileSource:newTileSource]; - if (self.adjustTilesForRetinaDisplay && _screenScale > 1.0) - ((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength * 2.0, tileSideLength * 2.0); - else - ((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength, tileSideLength); + ((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength, tileSideLength); if (index >= [[_tileSourcesContainer tileSources] count]) [_tiledLayersSuperview addSubview:tiledLayerView]; @@ -1689,10 +2245,12 @@ - (void)removeTileSource:(id )tileSource if ([_tileSourcesContainer.tileSources count] == 0) { - [_projection release]; - [_mercatorToTileProjection release]; _constrainMovement = NO; } + else + { + [self setTileSourcesConstraintsFromLatitudeLongitudeBoundingBox:[_tileSourcesContainer latitudeLongitudeBoundingBox]]; + } // Remove the map layer RMMapTiledLayerView *tileSourceTiledLayerView = nil; @@ -1707,7 +2265,7 @@ - (void)removeTileSource:(id )tileSource } tileSourceTiledLayerView.layer.contents = nil; - [tileSourceTiledLayerView removeFromSuperview]; [tileSourceTiledLayerView release]; tileSourceTiledLayerView = nil; + [tileSourceTiledLayerView removeFromSuperview]; tileSourceTiledLayerView = nil; [self setCenterProjectedPoint:centerPoint animated:NO]; } @@ -1720,16 +2278,18 @@ - (void)removeTileSourceAtIndex:(NSUInteger)index if ([_tileSourcesContainer.tileSources count] == 0) { - [_projection release]; - [_mercatorToTileProjection release]; _constrainMovement = NO; } + else + { + [self setTileSourcesConstraintsFromLatitudeLongitudeBoundingBox:[_tileSourcesContainer latitudeLongitudeBoundingBox]]; + } // Remove the map layer RMMapTiledLayerView *tileSourceTiledLayerView = [_tiledLayersSuperview.subviews objectAtIndex:index]; tileSourceTiledLayerView.layer.contents = nil; - [tileSourceTiledLayerView removeFromSuperview]; [tileSourceTiledLayerView release]; tileSourceTiledLayerView = nil; + [tileSourceTiledLayerView removeFromSuperview]; tileSourceTiledLayerView = nil; [self setCenterProjectedPoint:centerPoint animated:NO]; } @@ -1757,13 +2317,13 @@ - (void)setHidden:(BOOL)isHidden forTileSource:(id )tileSource NSArray *tileSources = [self tileSources]; [tileSources enumerateObjectsUsingBlock:^(id currentTileSource, NSUInteger index, BOOL *stop) - { + { if (tileSource == currentTileSource) { [self setHidden:isHidden forTileSourceAtIndex:index]; *stop = YES; } - }]; + }]; } - (void)setHidden:(BOOL)isHidden forTileSourceAtIndex:(NSUInteger)index @@ -1774,6 +2334,28 @@ - (void)setHidden:(BOOL)isHidden forTileSourceAtIndex:(NSUInteger)index ((RMMapTiledLayerView *)[_tiledLayersSuperview.subviews objectAtIndex:index]).hidden = isHidden; } +- (void)setAlpha:(CGFloat)alpha forTileSource:(id )tileSource +{ + NSArray *tileSources = [self tileSources]; + + [tileSources enumerateObjectsUsingBlock:^(id currentTileSource, NSUInteger index, BOOL *stop) + { + if (tileSource == currentTileSource) + { + [self setAlpha:alpha forTileSourceAtIndex:index]; + *stop = YES; + } + }]; +} + +- (void)setAlpha:(CGFloat)alpha forTileSourceAtIndex:(NSUInteger)index +{ + if (index >= [_tiledLayersSuperview.subviews count]) + return; + + ((RMMapTiledLayerView *)[_tiledLayersSuperview.subviews objectAtIndex:index]).alpha = alpha; +} + - (void)reloadTileSource:(id )tileSource { // Reload the map layer @@ -1803,32 +2385,50 @@ - (void)reloadTileSourceAtIndex:(NSUInteger)index - (UIView *)backgroundView { - return [[_backgroundView retain] autorelease]; + return _backgroundView; } - (void)setBackgroundView:(UIView *)aView { - if (_backgroundView == aView) + if ([_backgroundView isEqual:aView]) return; - if (_backgroundView != nil) - { + if (_backgroundView) [_backgroundView removeFromSuperview]; - [_backgroundView release]; + + if ( ! aView) + { + if ( ! _loadingTileView) + _loadingTileView = [[RMLoadingTileView alloc] initWithFrame:self.bounds]; + + aView = _loadingTileView; } + else + _loadingTileView = nil; - _backgroundView = [aView retain]; - if (_backgroundView == nil) - return; + _backgroundView = aView; - _backgroundView.frame = [self bounds]; + _backgroundView.frame = self.bounds; [self insertSubview:_backgroundView atIndex:0]; } -- (double)metersPerPixel +- (void)setBackgroundImage:(UIImage *)backgroundImage { - return _metersPerPixel; + if (backgroundImage) + { + [self setBackgroundView:[[UIView alloc] initWithFrame:self.bounds]]; + self.backgroundView.layer.contents = (id)backgroundImage.CGImage; + } + else + { + [self setBackgroundView:nil]; + } +} + +- (double)metersPerPixel +{ + return _metersPerPixel; } - (void)setMetersPerPixel:(double)newMetersPerPixel @@ -1872,17 +2472,43 @@ - (double)scaleDenominator - (void)setMinZoom:(float)newMinZoom { + 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; + + if (newMinZoom < 0.0) + newMinZoom = 0.0; + _minZoom = newMinZoom; // RMLog(@"New minZoom:%f", newMinZoom); _mapScrollView.minimumZoomScale = exp2f(newMinZoom); +} + +- (float)tileSourcesMinZoom +{ + return self.tileSourcesContainer.minZoom; +} + +- (void)setTileSourcesMinZoom:(float)tileSourcesMinZoom +{ + tileSourcesMinZoom = ceilf(tileSourcesMinZoom) - 0.99; + + if ( ! self.adjustTilesForRetinaDisplay && _screenScale > 1.0 && ! [RMMapboxSource isUsingLargeTiles]) + tileSourcesMinZoom -= 1.0; - [self correctMinZoomScaleForBoundingMask]; + [self setMinZoom:tileSourcesMinZoom]; } - (void)setMaxZoom:(float)newMaxZoom { + if (newMaxZoom < 0.0) + newMaxZoom = 0.0; + _maxZoom = newMaxZoom; // RMLog(@"New maxZoom:%f", newMaxZoom); @@ -1890,6 +2516,21 @@ - (void)setMaxZoom:(float)newMaxZoom _mapScrollView.maximumZoomScale = exp2f(newMaxZoom); } +- (float)tileSourcesMaxZoom +{ + return self.tileSourcesContainer.maxZoom; +} + +- (void)setTileSourcesMaxZoom:(float)tileSourcesMaxZoom +{ + tileSourcesMaxZoom = floorf(tileSourcesMaxZoom); + + if ( ! self.adjustTilesForRetinaDisplay && _screenScale > 1.0 && ! [RMMapboxSource isUsingLargeTiles]) + tileSourcesMaxZoom -= 1.0; + + [self setMaxZoom:tileSourcesMaxZoom]; +} + - (float)zoom { return _zoom; @@ -1898,17 +2539,44 @@ - (float)zoom // if #zoom is outside of range #minZoom to #maxZoom, zoom level is clamped to that range. - (void)setZoom:(float)newZoom { + if (_zoom == newZoom) + return; + + [self registerZoomEventByUser:NO]; + _zoom = (newZoom > _maxZoom) ? _maxZoom : newZoom; _zoom = (_zoom < _minZoom) ? _minZoom : _zoom; -// RMLog(@"New zoom:%f", zoom); +// RMLog(@"New zoom:%f", _zoom); _mapScrollView.zoomScale = exp2f(_zoom); + + [self completeZoomEventAfterDelay:0]; } -- (void)setEnableClustering:(BOOL)doEnableClustering +- (float)tileSourcesZoom { - _enableClustering = doEnableClustering; + float zoom = ceilf(_zoom); + + if ( ! self.adjustTilesForRetinaDisplay && _screenScale > 1.0 && ! [RMMapboxSource isUsingLargeTiles]) + zoom += 1.0; + + return zoom; +} + +- (void)setTileSourcesZoom:(float)tileSourcesZoom +{ + tileSourcesZoom = floorf(tileSourcesZoom); + + if ( ! self.adjustTilesForRetinaDisplay && _screenScale > 1.0 && ! [RMMapboxSource isUsingLargeTiles]) + tileSourcesZoom -= 1.0; + + [self setZoom:tileSourcesZoom]; +} + +- (void)setClusteringEnabled:(BOOL)doEnableClustering +{ + _clusteringEnabled = doEnableClustering; [self correctPositionOfAllAnnotations]; } @@ -1927,25 +2595,25 @@ - (void)setDecelerationMode:(RMMapDecelerationMode)aDecelerationMode [_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; } @@ -1966,7 +2634,7 @@ - (void)setAdjustTilesForRetinaDisplay:(BOOL)doAdjustTilesForRetinaDisplay - (float)adjustedZoomForRetinaDisplay { - if (!self.adjustTilesForRetinaDisplay && _screenScale > 1.0) + if (!self.adjustTilesForRetinaDisplay && _screenScale > 1.0 && ! [RMMapboxSource isUsingLargeTiles]) return [self zoom] + 1.0; return [self zoom]; @@ -1974,12 +2642,12 @@ - (float)adjustedZoomForRetinaDisplay - (RMProjection *)projection { - return [[_projection retain] autorelease]; + return _projection; } - (RMFractalTileProjection *)mercatorToTileProjection { - return [[_mercatorToTileProjection retain] autorelease]; + return _mercatorToTileProjection; } - (void)setDebugTiles:(BOOL)shouldDebug; @@ -1993,6 +2661,85 @@ - (void)setDebugTiles:(BOOL)shouldDebug; } } +- (void)setShowLogoBug:(BOOL)showLogoBug +{ + if (showLogoBug && ! _logoBug) + { + _logoBug = [[UIImageView alloc] initWithImage:[RMMapView resourceImageNamed:@"mapbox.png"]]; + _logoBug.frame = CGRectMake(8, self.bounds.size.height - _logoBug.bounds.size.height - 4, _logoBug.bounds.size.width, _logoBug.bounds.size.height); + _logoBug.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin; + _logoBug.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_logoBug]; + [self updateConstraints]; + } + else if ( ! showLogoBug && _logoBug) + { + [_logoBug removeFromSuperview]; + _logoBug = nil; + } + + _showLogoBug = showLogoBug; +} + +- (void)tintColorDidChange +{ + // update user location annotations + // + if (CLLocationCoordinate2DIsValid(self.userLocation.coordinate)) + { + // update user dot + // + [self.userLocation updateTintColor]; + + // update user halo + // + [(RMMarker *)_trackingHaloAnnotation.layer replaceUIImage:[self trackingDotHaloImage]]; + + // update accuracy circle + // + ((RMCircle *)_accuracyCircleAnnotation.layer).fillColor = [self.tintColor colorWithAlphaComponent:0.1]; + + // update heading tracking views + // + if (self.userTrackingMode == RMUserTrackingModeFollowWithHeading) + _userHeadingTrackingView.image = [self headingAngleImageForAccuracy:_locationManager.heading.headingAccuracy]; + } + + // update tracking button + // + if (_userTrackingBarButtonItem) + { + if (self.tintAdjustmentMode == UIViewTintAdjustmentModeDimmed || _userTrackingBarButtonItem.tintAdjustmentMode == UIViewTintAdjustmentModeDimmed) + { + _userTrackingBarButtonItem.tintAdjustmentMode = self.tintAdjustmentMode; + _userTrackingBarButtonItem.tintColor = self.tintColor; + } + } + + // update point annotations with managed layers + // + BOOL updatePoints = NO; + + for (RMAnnotation *annotation in self.annotations) + { + if ([annotation isKindOfClass:[RMPointAnnotation class]] && annotation.isAnnotationVisibleOnScreen) + { + [annotation.layer removeFromSuperlayer]; + annotation.layer = nil; + [_overlayView addSublayer:annotation.layer]; + updatePoints = YES; + } + } + + if (updatePoints) + [self correctPositionOfAllAnnotations]; + + // update callout view hierarchy + // + if (_currentCallout) + _currentCallout.tintColor = self.tintColor; +} + #pragma mark - #pragma mark LatLng/Pixel translation functions @@ -2235,7 +2982,7 @@ - (void)correctPositionOfAllAnnotationsIncludingInvisibles:(BOOL)correctAllAnnot 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]; @@ -2245,10 +2992,13 @@ - (void)correctPositionOfAllAnnotationsIncludingInvisibles:(BOOL)correctAllAnnot { if (annotation.layer == nil && _delegateHasLayerForAnnotation) annotation.layer = [_delegate mapView:self layerForAnnotation:annotation]; + if (annotation.layer == nil) continue; - // Use the zPosition property to order the layer hierarchy + if ([annotation.layer isKindOfClass:[RMMarker class]]) + annotation.layer.transform = _annotationTransform; + if ( ! [_visibleAnnotations containsObject:annotation]) { [_overlayView addSublayer:annotation.layer]; @@ -2276,7 +3026,7 @@ - (void)correctPositionOfAllAnnotationsIncludingInvisibles:(BOOL)correctAllAnnot } } - [previousVisibleAnnotations release]; + previousVisibleAnnotations = nil; // RMLog(@"%d annotations on screen, %d total", [overlayView sublayersCount], [annotations count]); } @@ -2296,9 +3046,13 @@ - (void)correctPositionOfAllAnnotationsIncludingInvisibles:(BOOL)correctAllAnnot { if (annotation.layer == nil && _delegateHasLayerForAnnotation) annotation.layer = [_delegate mapView:self layerForAnnotation:annotation]; + if (annotation.layer == nil) continue; + if ([annotation.layer isKindOfClass:[RMMarker class]]) + annotation.layer.transform = _annotationTransform; + if (![_visibleAnnotations containsObject:annotation]) { if (!lastLayer) @@ -2338,6 +3092,8 @@ - (void)correctPositionOfAllAnnotationsIncludingInvisibles:(BOOL)correctAllAnnot } } + [self correctOrderingOfAllAnnotations]; + [CATransaction commit]; } @@ -2346,6 +3102,97 @@ - (void)correctPositionOfAllAnnotations [self correctPositionOfAllAnnotationsIncludingInvisibles:YES animated:NO]; } +- (void)correctOrderingOfAllAnnotations +{ + NSMutableArray *sortedAnnotations = [NSMutableArray arrayWithArray:[_visibleAnnotations allObjects]]; + + NSComparator comparator; + + if (_delegateHasAnnotationSorting && (comparator = [_delegate annotationSortingComparatorForMapView:self])) + { + // Sort using the custom comparator. + // + [sortedAnnotations sortUsingComparator:comparator]; + } + else + { + // Sort using the default comparator. + // + [sortedAnnotations sortUsingComparator:^(RMAnnotation *annotation1, RMAnnotation *annotation2) + { + // Sort user location annotations below all. + // + if ( annotation1.isUserLocationAnnotation && ! annotation2.isUserLocationAnnotation) + return NSOrderedAscending; + + if ( ! annotation1.isUserLocationAnnotation && annotation2.isUserLocationAnnotation) + 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 ([annotation2 isKindOfClass:[RMUserLocation class]]) + return NSOrderedAscending; + + // Halo above accuracy circle. + // + if ([annotation1.annotationType isEqualToString:kRMTrackingHaloAnnotationTypeName]) + return NSOrderedDescending; + + if ([annotation2.annotationType isEqualToString:kRMTrackingHaloAnnotationTypeName]) + return NSOrderedAscending; + } + + // Return early if we're not otherwise sorting annotations. + // + if ( ! _orderMarkersByYPosition) + 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. + // + if (_currentAnnotation) + _currentAnnotation.layer.zPosition = _currentCallout.layer.zPosition = MAXFLOAT; +} + - (NSArray *)annotations { return [_annotations allObjects]; @@ -2358,13 +3205,19 @@ - (NSArray *)visibleAnnotations - (void)addAnnotation:(RMAnnotation *)annotation { + if ( ! annotation) + return; + @synchronized (_annotations) { + if ([_annotations containsObject:annotation]) + return; + [_annotations addObject:annotation]; [self.quadTree addAnnotation:annotation]; } - if (_enableClustering) + if (_clusteringEnabled) { [self correctPositionOfAllAnnotations]; } @@ -2380,11 +3233,16 @@ - (void)addAnnotation:(RMAnnotation *)annotation [_overlayView addSublayer:annotation.layer]; [_visibleAnnotations addObject:annotation]; } + + [self correctOrderingOfAllAnnotations]; } } - (void)addAnnotations:(NSArray *)newAnnotations { + if ( ! newAnnotations || ! [newAnnotations count]) + return; + @synchronized (_annotations) { [_annotations addObjectsFromArray:newAnnotations]; @@ -2400,12 +3258,11 @@ - (void)removeAnnotation:(RMAnnotation *)annotation { [_annotations removeObject:annotation]; [_visibleAnnotations removeObject:annotation]; + [self.quadTree removeAnnotation:annotation]; + annotation.layer = nil; } - [self.quadTree removeAnnotation:annotation]; - - // Remove the layer from the screen - annotation.layer = nil; + [self correctPositionOfAllAnnotations]; } - (void)removeAnnotations:(NSArray *)annotationsToRemove @@ -2443,72 +3300,74 @@ - (CGPoint)mapPositionForAnnotation:(RMAnnotation *)annotation - (void)setShowsUserLocation:(BOOL)newShowsUserLocation { - if (newShowsUserLocation == showsUserLocation) + if (newShowsUserLocation == _showsUserLocation) return; - showsUserLocation = newShowsUserLocation; + _showsUserLocation = newShowsUserLocation; if (newShowsUserLocation) { if (_delegateHasWillStartLocatingUser) [_delegate mapViewWillStartLocatingUser:self]; - self.userLocation = [RMUserLocation annotationWithMapView:self coordinate:CLLocationCoordinate2DMake(0, 0) andTitle:nil]; + self.userLocation = [RMUserLocation annotationWithMapView:self coordinate:CLLocationCoordinate2DMake(MAXFLOAT, MAXFLOAT) andTitle:nil]; + + _locationManager = [CLLocationManager new]; - locationManager = [[CLLocationManager alloc] init]; - locationManager.headingFilter = 5; - locationManager.delegate = self; - [locationManager startUpdatingLocation]; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + // enable iOS 8+ location authorization API + // + if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) + { + BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] || + [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]; + NSAssert(hasLocationDescription, @"For iOS 8 and above, your app must have a value for NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in its Info.plist"); + [_locationManager requestWhenInUseAuthorization]; + } +#endif + + _locationManager.headingFilter = 5.0; + _locationManager.delegate = self; + [_locationManager startUpdatingLocation]; } else { - [locationManager stopUpdatingLocation]; - [locationManager stopUpdatingHeading]; - locationManager.delegate = nil; - [locationManager release]; - locationManager = nil; + [_locationManager stopUpdatingLocation]; + [_locationManager stopUpdatingHeading]; + _locationManager.delegate = nil; + _locationManager = nil; if (_delegateHasDidStopLocatingUser) [_delegate mapViewDidStopLocatingUser:self]; [self setUserTrackingMode:RMUserTrackingModeNone animated:YES]; - NSMutableArray *annotationsToRemove = [NSMutableArray array]; + for (RMAnnotation *annotation in [NSArray arrayWithObjects:_trackingHaloAnnotation, _accuracyCircleAnnotation, self.userLocation, nil]) + [self removeAnnotation:annotation]; - for (RMAnnotation *annotation in _annotations) - { - if (annotation.isUserLocationAnnotation) - [annotationsToRemove addObject:annotation]; - } - - for (RMAnnotation *annotationToRemove in annotationsToRemove) - { - [self removeAnnotation:annotationToRemove]; - } + _trackingHaloAnnotation = nil; + _accuracyCircleAnnotation = nil; self.userLocation = nil; - } + } } - (void)setUserLocation:(RMUserLocation *)newUserLocation { - if ( ! [newUserLocation isEqual:userLocation]) - { - [userLocation release]; - userLocation = [newUserLocation retain]; - } + if ( ! [newUserLocation isEqual:_userLocation]) + _userLocation = newUserLocation; } - (BOOL)isUserLocationVisible { - if (userLocation) + if (self.userLocation) { - CGPoint locationPoint = [self mapPositionForAnnotation:userLocation]; + CGPoint locationPoint = [self mapPositionForAnnotation:self.userLocation]; - CGRect locationRect = CGRectMake(locationPoint.x - userLocation.location.horizontalAccuracy, - locationPoint.y - userLocation.location.horizontalAccuracy, - userLocation.location.horizontalAccuracy * 2, - userLocation.location.horizontalAccuracy * 2); + CGRect locationRect = CGRectMake(locationPoint.x - self.userLocation.location.horizontalAccuracy, + locationPoint.y - self.userLocation.location.horizontalAccuracy, + self.userLocation.location.horizontalAccuracy * 2, + self.userLocation.location.horizontalAccuracy * 2); return CGRectIntersectsRect([self bounds], locationRect); } @@ -2523,40 +3382,48 @@ - (void)setUserTrackingMode:(RMUserTrackingMode)mode - (void)setUserTrackingMode:(RMUserTrackingMode)mode animated:(BOOL)animated { - if (mode == userTrackingMode) + if (mode == _userTrackingMode) return; - userTrackingMode = mode; + if (mode == RMUserTrackingModeFollowWithHeading && ! CLLocationCoordinate2DIsValid(self.userLocation.coordinate)) + mode = RMUserTrackingModeNone; - switch (userTrackingMode) + _userTrackingMode = mode; + + switch (_userTrackingMode) { case RMUserTrackingModeNone: default: { - [locationManager stopUpdatingHeading]; + [_locationManager stopUpdatingHeading]; + + [CATransaction setAnimationDuration:0.5]; + [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [UIView animateWithDuration:(animated ? 0.5 : 0.0) delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseInOut animations:^(void) { - _mapScrollView.transform = CGAffineTransformIdentity; - _overlayView.transform = CGAffineTransformIdentity; - + _mapTransform = CGAffineTransformIdentity; + _annotationTransform = CATransform3DIdentity; + + _mapScrollView.transform = _mapTransform; + _compassButton.transform = _mapTransform; + _overlayView.transform = _mapTransform; + + _compassButton.alpha = 0; + for (RMAnnotation *annotation in _annotations) - annotation.layer.transform = CATransform3DIdentity; + if ([annotation.layer isKindOfClass:[RMMarker class]]) + annotation.layer.transform = _annotationTransform; } completion:nil]; - if (userLocationTrackingView || userHeadingTrackingView) - { - [userLocationTrackingView removeFromSuperview]; - userLocationTrackingView = nil; - [userHeadingTrackingView removeFromSuperview]; - userHeadingTrackingView = nil; - } + [CATransaction commit]; - userLocation.layer.hidden = NO; + if (_userHeadingTrackingView) + [_userHeadingTrackingView removeFromSuperview]; _userHeadingTrackingView = nil; break; } @@ -2564,33 +3431,41 @@ - (void)setUserTrackingMode:(RMUserTrackingMode)mode animated:(BOOL)animated { self.showsUserLocation = YES; - [locationManager stopUpdatingHeading]; + [_locationManager stopUpdatingHeading]; if (self.userLocation) - [self locationManager:locationManager didUpdateToLocation:self.userLocation.location fromLocation:self.userLocation.location]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + [self locationManager:_locationManager didUpdateToLocation:self.userLocation.location fromLocation:self.userLocation.location]; + #pragma clang diagnostic pop - if (userLocationTrackingView || userHeadingTrackingView) - { - [userLocationTrackingView removeFromSuperview]; - userLocationTrackingView = nil; - [userHeadingTrackingView removeFromSuperview]; - userHeadingTrackingView = nil; - } + if (_userHeadingTrackingView) + [_userHeadingTrackingView removeFromSuperview]; _userHeadingTrackingView = nil; + + [CATransaction setAnimationDuration:0.5]; + [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [UIView animateWithDuration:(animated ? 0.5 : 0.0) delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseInOut animations:^(void) { - _mapScrollView.transform = CGAffineTransformIdentity; - _overlayView.transform = CGAffineTransformIdentity; + _mapTransform = CGAffineTransformIdentity; + _annotationTransform = CATransform3DIdentity; + + _mapScrollView.transform = _mapTransform; + _compassButton.transform = _mapTransform; + _overlayView.transform = _mapTransform; + + _compassButton.alpha = 0; for (RMAnnotation *annotation in _annotations) - annotation.layer.transform = CATransform3DIdentity; + if ([annotation.layer isKindOfClass:[RMMarker class]]) + annotation.layer.transform = _annotationTransform; } completion:nil]; - userLocation.layer.hidden = NO; + [CATransaction commit]; break; } @@ -2598,142 +3473,177 @@ - (void)setUserTrackingMode:(RMUserTrackingMode)mode animated:(BOOL)animated { self.showsUserLocation = YES; - userLocation.layer.hidden = YES; - - userHeadingTrackingView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"HeadingAngleSmall.png"]]; - - userHeadingTrackingView.center = CGPointMake(round([self bounds].size.width / 2), - round([self bounds].size.height / 2) - (userHeadingTrackingView.bounds.size.height / 2) - 4); + _userHeadingTrackingView = [[UIImageView alloc] initWithImage:[self headingAngleImageForAccuracy:MAXFLOAT]]; - userHeadingTrackingView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | - UIViewAutoresizingFlexibleRightMargin | - UIViewAutoresizingFlexibleTopMargin | - UIViewAutoresizingFlexibleBottomMargin; + _userHeadingTrackingView.frame = CGRectMake((self.bounds.size.width / 2) - (_userHeadingTrackingView.bounds.size.width / 2), + (self.bounds.size.height / 2) - _userHeadingTrackingView.bounds.size.height, + _userHeadingTrackingView.bounds.size.width, + _userHeadingTrackingView.bounds.size.height * 2); - userHeadingTrackingView.alpha = 0.0; + _userHeadingTrackingView.contentMode = UIViewContentModeTop; - [self addSubview:userHeadingTrackingView]; - - [UIView animateWithDuration:0.5 animations:^(void) { userHeadingTrackingView.alpha = 1.0; }]; - - userLocationTrackingView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TrackingDot.png"]]; - - userLocationTrackingView.center = CGPointMake(round([self bounds].size.width / 2), - round([self bounds].size.height / 2)); - - userLocationTrackingView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | + _userHeadingTrackingView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; - - [self addSubview:userLocationTrackingView]; + + _userHeadingTrackingView.alpha = 0.0; + + [self insertSubview:_userHeadingTrackingView belowSubview:_overlayView]; if (self.zoom < 3) [self zoomByFactor:exp2f(3 - [self zoom]) near:self.center animated:YES]; if (self.userLocation) - [self locationManager:locationManager didUpdateToLocation:self.userLocation.location fromLocation:self.userLocation.location]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + [self locationManager:_locationManager didUpdateToLocation:self.userLocation.location fromLocation:self.userLocation.location]; + #pragma clang diagnostic pop - [locationManager startUpdatingHeading]; + [self updateHeadingForDeviceOrientation]; + + [_locationManager startUpdatingHeading]; break; } } if (_delegateHasDidChangeUserTrackingMode) - [_delegate mapView:self didChangeUserTrackingMode:userTrackingMode animated:animated]; + [_delegate mapView:self didChangeUserTrackingMode:_userTrackingMode animated:animated]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { - if ( ! showsUserLocation || _mapScrollView.isDragging) + if ( ! _showsUserLocation || _mapScrollView.isDragging || ! newLocation || ! CLLocationCoordinate2DIsValid(newLocation.coordinate)) return; if ([newLocation distanceFromLocation:oldLocation]) { - userLocation.location = newLocation; + self.userLocation.location = newLocation; if (_delegateHasDidUpdateUserLocation) - [_delegate mapView:self didUpdateUserLocation:userLocation]; + { + [_delegate mapView:self didUpdateUserLocation:self.userLocation]; + + if ( ! _showsUserLocation) + return; + } } if (self.userTrackingMode != RMUserTrackingModeNone) { - // zoom centered on user location unless we're already centered there (or very close) + // center on user location unless we're already centered there (or very close) // CGPoint mapCenterPoint = [self convertPoint:self.center fromView:self.superview]; - CGPoint userLocationPoint = [self mapPositionForAnnotation:userLocation]; + CGPoint userLocationPoint = [self mapPositionForAnnotation:self.userLocation]; - if (fabsf(userLocationPoint.x - mapCenterPoint.x) > 2 || fabsf(userLocationPoint.y - mapCenterPoint.y > 2)) + if (fabsf(userLocationPoint.x - mapCenterPoint.x) > 1.0 || fabsf(userLocationPoint.y - mapCenterPoint.y) > 1.0) { - float delta = newLocation.horizontalAccuracy / 110000; // approx. meter per degree latitude - - CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(newLocation.coordinate.latitude - delta, - newLocation.coordinate.longitude - delta); - - CLLocationCoordinate2D northEast = CLLocationCoordinate2DMake(newLocation.coordinate.latitude + delta, - newLocation.coordinate.longitude + delta); - - if (northEast.latitude != [self latitudeLongitudeBoundingBox].northEast.latitude || - northEast.longitude != [self latitudeLongitudeBoundingBox].northEast.longitude || - southWest.latitude != [self latitudeLongitudeBoundingBox].southWest.latitude || - southWest.longitude != [self latitudeLongitudeBoundingBox].southWest.longitude) - [self zoomWithLatitudeLongitudeBoundsSouthWest:southWest northEast:northEast animated:YES]; - } - } + if (round(_zoom) >= 10) + { + // at sufficient detail, just re-center the map; don't zoom + // + [self setCenterCoordinate:self.userLocation.location.coordinate animated:YES]; + } + else + { + // otherwise re-center and zoom in to near accuracy confidence + // + float delta = (newLocation.horizontalAccuracy / 110000) * 1.2; // approx. meter per degree latitude, plus some margin - RMAnnotation *accuracyCircleAnnotation = nil; + CLLocationCoordinate2D desiredSouthWest = CLLocationCoordinate2DMake(newLocation.coordinate.latitude - delta, + newLocation.coordinate.longitude - delta); - for (RMAnnotation *annotation in _annotations) - { - if ([annotation.annotationType isEqualToString:kRMAccuracyCircleAnnotationTypeName]) - accuracyCircleAnnotation = annotation; + CLLocationCoordinate2D desiredNorthEast = CLLocationCoordinate2DMake(newLocation.coordinate.latitude + delta, + newLocation.coordinate.longitude + delta); + + CGFloat pixelRadius = fminf(self.bounds.size.width, self.bounds.size.height) / 2; + + CLLocationCoordinate2D actualSouthWest = [self pixelToCoordinate:CGPointMake(userLocationPoint.x - pixelRadius, userLocationPoint.y - pixelRadius)]; + CLLocationCoordinate2D actualNorthEast = [self pixelToCoordinate:CGPointMake(userLocationPoint.x + pixelRadius, userLocationPoint.y + pixelRadius)]; + + if (desiredNorthEast.latitude != actualNorthEast.latitude || + desiredNorthEast.longitude != actualNorthEast.longitude || + desiredSouthWest.latitude != actualSouthWest.latitude || + desiredSouthWest.longitude != actualSouthWest.longitude) + { + [self zoomWithLatitudeLongitudeBoundsSouthWest:desiredSouthWest northEast:desiredNorthEast animated:YES]; + } + } + } } - if ( ! accuracyCircleAnnotation) + if ( ! _accuracyCircleAnnotation) { - accuracyCircleAnnotation = [RMAnnotation annotationWithMapView:self coordinate:newLocation.coordinate andTitle:nil]; - accuracyCircleAnnotation.annotationType = kRMAccuracyCircleAnnotationTypeName; - accuracyCircleAnnotation.clusteringEnabled = NO; - accuracyCircleAnnotation.layer = [[RMCircle alloc] initWithView:self radiusInMeters:newLocation.horizontalAccuracy]; - accuracyCircleAnnotation.isUserLocationAnnotation = YES; + _accuracyCircleAnnotation = [RMAnnotation annotationWithMapView:self coordinate:newLocation.coordinate andTitle:nil]; + _accuracyCircleAnnotation.annotationType = kRMAccuracyCircleAnnotationTypeName; + _accuracyCircleAnnotation.clusteringEnabled = NO; + _accuracyCircleAnnotation.enabled = NO; + _accuracyCircleAnnotation.layer = [[RMCircle alloc] initWithView:self radiusInMeters:newLocation.horizontalAccuracy]; + _accuracyCircleAnnotation.isUserLocationAnnotation = YES; - ((RMCircle *)accuracyCircleAnnotation.layer).lineColor = [UIColor colorWithRed:0.378 green:0.552 blue:0.827 alpha:0.7]; - ((RMCircle *)accuracyCircleAnnotation.layer).fillColor = [UIColor colorWithRed:0.378 green:0.552 blue:0.827 alpha:0.15]; + ((RMCircle *)_accuracyCircleAnnotation.layer).lineColor = (RMPreVersion7 ? [UIColor colorWithRed:0.378 green:0.552 blue:0.827 alpha:0.7] : [UIColor clearColor]); + ((RMCircle *)_accuracyCircleAnnotation.layer).fillColor = (RMPreVersion7 ? [UIColor colorWithRed:0.378 green:0.552 blue:0.827 alpha:0.15] : [self.tintColor colorWithAlphaComponent:0.1]); - ((RMCircle *)accuracyCircleAnnotation.layer).lineWidthInPixels = 2.0; + ((RMCircle *)_accuracyCircleAnnotation.layer).lineWidthInPixels = 2.0; - [self addAnnotation:accuracyCircleAnnotation]; + [self addAnnotation:_accuracyCircleAnnotation]; } - if ([newLocation distanceFromLocation:oldLocation]) - accuracyCircleAnnotation.coordinate = newLocation.coordinate; + if ( ! oldLocation) + { + // make accuracy circle bounce until we get our second update + // + [CATransaction begin]; + [CATransaction setAnimationDuration:0.75]; + [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; - if (newLocation.horizontalAccuracy != oldLocation.horizontalAccuracy) - ((RMCircle *)accuracyCircleAnnotation.layer).radiusInMeters = newLocation.horizontalAccuracy; + 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; - RMAnnotation *trackingHaloAnnotation = nil; + [_accuracyCircleAnnotation.layer addAnimation:bounceAnimation forKey:@"animateScale"]; - for (RMAnnotation *annotation in _annotations) + [CATransaction commit]; + } + else { - if ([annotation.annotationType isEqualToString:kRMTrackingHaloAnnotationTypeName]) - trackingHaloAnnotation = annotation; + [_accuracyCircleAnnotation.layer removeAnimationForKey:@"animateScale"]; } - if ( ! trackingHaloAnnotation) + if ([newLocation distanceFromLocation:oldLocation]) + _accuracyCircleAnnotation.coordinate = newLocation.coordinate; + + if (newLocation.horizontalAccuracy != oldLocation.horizontalAccuracy) + ((RMCircle *)_accuracyCircleAnnotation.layer).radiusInMeters = newLocation.horizontalAccuracy; + + if ( ! _trackingHaloAnnotation) { - trackingHaloAnnotation = [RMAnnotation annotationWithMapView:self coordinate:newLocation.coordinate andTitle:nil]; - trackingHaloAnnotation.annotationType = kRMTrackingHaloAnnotationTypeName; - trackingHaloAnnotation.clusteringEnabled = NO; + _trackingHaloAnnotation = [RMAnnotation annotationWithMapView:self coordinate:newLocation.coordinate andTitle:nil]; + _trackingHaloAnnotation.annotationType = kRMTrackingHaloAnnotationTypeName; + _trackingHaloAnnotation.clusteringEnabled = NO; + _trackingHaloAnnotation.enabled = NO; // create image marker // - trackingHaloAnnotation.layer = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:@"TrackingDotHalo.png"]]; - trackingHaloAnnotation.isUserLocationAnnotation = YES; + _trackingHaloAnnotation.layer = [[RMMarker alloc] initWithUIImage:[self trackingDotHaloImage]]; + _trackingHaloAnnotation.isUserLocationAnnotation = YES; [CATransaction begin]; - [CATransaction setAnimationDuration:2.5]; - [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; + + if (RMPreVersion7) + { + [CATransaction setAnimationDuration:2.5]; + [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; + } + else + { + [CATransaction setAnimationDuration:3.5]; + [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; + } // scale out radially // @@ -2742,9 +3652,8 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLoca 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"]; + [_trackingHaloAnnotation.layer addAnimation:boundsAnimation forKey:@"animateScale"]; // go transparent as scaled out // @@ -2753,62 +3662,84 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLoca opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0]; opacityAnimation.toValue = [NSNumber numberWithFloat:-1.0]; opacityAnimation.removedOnCompletion = NO; - opacityAnimation.fillMode = kCAFillModeForwards; - [trackingHaloAnnotation.layer addAnimation:opacityAnimation forKey:@"animateOpacity"]; + [_trackingHaloAnnotation.layer addAnimation:opacityAnimation forKey:@"animateOpacity"]; [CATransaction commit]; - [self addAnnotation:trackingHaloAnnotation]; + [self addAnnotation:_trackingHaloAnnotation]; } if ([newLocation distanceFromLocation:oldLocation]) - trackingHaloAnnotation.coordinate = newLocation.coordinate; + _trackingHaloAnnotation.coordinate = newLocation.coordinate; - userLocation.layer.hidden = ((trackingHaloAnnotation.coordinate.latitude == 0 && trackingHaloAnnotation.coordinate.longitude == 0) || self.userTrackingMode == RMUserTrackingModeFollowWithHeading); + self.userLocation.layer.hidden = ( ! CLLocationCoordinate2DIsValid(self.userLocation.coordinate)); - accuracyCircleAnnotation.layer.hidden = newLocation.horizontalAccuracy <= 10; + _accuracyCircleAnnotation.layer.hidden = newLocation.horizontalAccuracy <= 10 || self.userLocation.hasCustomLayer; - trackingHaloAnnotation.layer.hidden = ((trackingHaloAnnotation.coordinate.latitude == 0 && trackingHaloAnnotation.coordinate.longitude == 0) || newLocation.horizontalAccuracy > 10); + _trackingHaloAnnotation.layer.hidden = ( ! CLLocationCoordinate2DIsValid(self.userLocation.coordinate) || newLocation.horizontalAccuracy > 10 || self.userLocation.hasCustomLayer); - if ( ! [_annotations containsObject:userLocation]) - [self addAnnotation:userLocation]; + if ( ! [_annotations containsObject:self.userLocation]) + [self addAnnotation:self.userLocation]; } - (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager { - return YES; + if (self.displayHeadingCalibration) + [_locationManager performSelector:@selector(dismissHeadingCalibrationDisplay) withObject:nil afterDelay:10.0]; + + return self.displayHeadingCalibration; } - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { - if ( ! showsUserLocation || _mapScrollView.isDragging) + if ( ! _showsUserLocation || _mapScrollView.isDragging || newHeading.headingAccuracy < 0) return; - userLocation.heading = newHeading; + _userHeadingTrackingView.image = [self headingAngleImageForAccuracy:newHeading.headingAccuracy]; + + self.userLocation.heading = newHeading; if (_delegateHasDidUpdateUserLocation) - [_delegate mapView:self didUpdateUserLocation:userLocation]; + { + [_delegate mapView:self didUpdateUserLocation:self.userLocation]; - if (newHeading.trueHeading != 0 && self.userTrackingMode == RMUserTrackingModeFollowWithHeading) + if ( ! _showsUserLocation) + return; + } + + CLLocationDirection headingDirection = (newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading); + + if (headingDirection != 0 && self.userTrackingMode == RMUserTrackingModeFollowWithHeading) { + if (_userHeadingTrackingView.alpha < 1.0) + [UIView animateWithDuration:0.5 animations:^(void) { _userHeadingTrackingView.alpha = 1.0; }]; + [CATransaction begin]; - [CATransaction setAnimationDuration:1.0]; + [CATransaction setAnimationDuration:0.5]; [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; - [UIView animateWithDuration:1.0 + [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseInOut animations:^(void) { - CGFloat angle = (M_PI / -180) * newHeading.trueHeading; + CGFloat angle = (M_PI / -180) * headingDirection; + + _mapTransform = CGAffineTransformMakeRotation(angle); + _annotationTransform = CATransform3DMakeAffineTransform(CGAffineTransformMakeRotation(-angle)); - _mapScrollView.transform = CGAffineTransformMakeRotation(angle); - _overlayView.transform = CGAffineTransformMakeRotation(angle); + _mapScrollView.transform = _mapTransform; + _compassButton.transform = _mapTransform; + _overlayView.transform = _mapTransform; + + _compassButton.alpha = 1.0; for (RMAnnotation *annotation in _annotations) - if ([annotation.layer isKindOfClass:[RMMarker class]] && ! annotation.isUserLocationAnnotation) - annotation.layer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMakeRotation(-angle)); + if ([annotation.layer isKindOfClass:[RMMarker class]]) + annotation.layer.transform = _annotationTransform; + + [self correctPositionOfAllAnnotations]; } completion:nil]; @@ -2816,15 +3747,310 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading } } +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status +{ + if (status == kCLAuthorizationStatusDenied || status == kCLAuthorizationStatusRestricted) + { + self.userTrackingMode = RMUserTrackingModeNone; + self.showsUserLocation = NO; + } +} + - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { - if ([error code] != kCLErrorLocationUnknown) + if ([error code] == kCLErrorDenied) { - self.userTrackingMode = RMUserTrackingModeNone; + self.userTrackingMode = RMUserTrackingModeNone; + self.showsUserLocation = NO; if (_delegateHasDidFailToLocateUserWithError) [_delegate mapView:self didFailToLocateUserWithError:error]; } } +- (void)updateHeadingForDeviceOrientation +{ + if (_locationManager) + { + // note that right/left device and interface orientations are opposites (see UIApplication.h) + // + switch ([[UIApplication sharedApplication] statusBarOrientation]) + { + case (UIInterfaceOrientationLandscapeLeft): + { + _locationManager.headingOrientation = CLDeviceOrientationLandscapeRight; + break; + } + case (UIInterfaceOrientationLandscapeRight): + { + _locationManager.headingOrientation = CLDeviceOrientationLandscapeLeft; + break; + } + case (UIInterfaceOrientationPortraitUpsideDown): + { + _locationManager.headingOrientation = CLDeviceOrientationPortraitUpsideDown; + break; + } + case (UIInterfaceOrientationPortrait): + default: + { + _locationManager.headingOrientation = CLDeviceOrientationPortrait; + break; + } + } + } +} + +- (void)tappedHeadingCompass:(id)sender +{ + self.userTrackingMode = RMUserTrackingModeFollow; +} + +- (UIImage *)trackingDotHaloImage +{ + if (RMPreVersion7) + { + return [RMMapView resourceImageNamed:@"TrackingDotHalo.png"]; + } + else + { + UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, [[UIScreen mainScreen] scale]); + CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [[self.tintColor colorWithAlphaComponent:0.75] CGColor]); + CGContextFillEllipseInRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, 100, 100)); + UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return finalImage; + } +} + +- (UIImage *)headingAngleImageForAccuracy:(CLLocationDirection)accuracy +{ + NSString *sizeString; + + if (accuracy > 40) + sizeString = @"Large"; + else if (accuracy >= 25 && accuracy <= 40) + sizeString = @"Medium"; + else + sizeString = @"Small"; + + UIImage *headingAngleImage = [RMMapView resourceImageNamed:[NSString stringWithFormat:@"HeadingAngle%@%@.png", (RMPostVersion7 ? @"Mask" : @""), sizeString]]; + + if (RMPostVersion7) + { + UIGraphicsBeginImageContextWithOptions(headingAngleImage.size, NO, [[UIScreen mainScreen] scale]); + [headingAngleImage drawAtPoint:CGPointMake(0, 0)]; + CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeSourceIn); + CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [self.tintColor CGColor]); + CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, headingAngleImage.size.width, headingAngleImage.size.height)); + headingAngleImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + } + + return headingAngleImage; +} + +- (void)setUserTrackingBarButtonItem:(RMUserTrackingBarButtonItem *)userTrackingBarButtonItem +{ + _userTrackingBarButtonItem = userTrackingBarButtonItem; +} + +#pragma mark - +#pragma mark Attribution + +- (void)setHideAttribution:(BOOL)flag +{ + if (_hideAttribution == flag) + return; + + _hideAttribution = flag; + + [self layoutSubviews]; +} + +- (UIViewController *)viewControllerPresentingAttribution +{ + return _viewControllerPresentingAttribution; +} + +- (void)setViewControllerPresentingAttribution:(UIViewController *)viewController +{ + _viewControllerPresentingAttribution = viewController; + + if (_viewControllerPresentingAttribution && ! _attributionButton) + { + _attributionButton = [UIButton buttonWithType:UIButtonTypeInfoLight]; + _attributionButton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin; + _attributionButton.translatesAutoresizingMaskIntoConstraints = NO; + [_attributionButton addTarget:self action:@selector(showAttribution:) forControlEvents:UIControlEventTouchUpInside]; + _attributionButton.frame = CGRectMake(self.bounds.size.width - _attributionButton.bounds.size.width - 8, + self.bounds.size.height - _attributionButton.bounds.size.height - 8, + _attributionButton.bounds.size.width, + _attributionButton.bounds.size.height); + [self addSubview:_attributionButton]; + [self updateConstraints]; + } + else if ( ! _viewControllerPresentingAttribution && _attributionButton) + { + [_attributionButton removeFromSuperview]; + _attributionButton = nil; + } +} + +- (void)showAttribution:(id)sender +{ + if (_viewControllerPresentingAttribution) + { + RMAttributionViewController *attributionViewController = [[RMAttributionViewController alloc] initWithMapView:self]; + + if (RMPostVersion7) + { + attributionViewController.view.tintColor = self.tintColor; + attributionViewController.edgesForExtendedLayout = UIRectEdgeNone; + + if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) + { + // show popover + // + _attributionPopover = [[UIPopoverController alloc] initWithContentViewController:attributionViewController]; + _attributionPopover.backgroundColor = [UIColor whiteColor]; + _attributionPopover.popoverContentSize = CGSizeMake(320, 320); + _attributionPopover.delegate = self; + [_attributionPopover presentPopoverFromRect:_attributionButton.frame + inView:self + permittedArrowDirections:UIPopoverArrowDirectionDown + animated:NO]; + } + else + { + // slide up see-through modal + // + attributionViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissAttribution:)]; + + UINavigationController *wrapper = [[UINavigationController alloc] initWithRootViewController:attributionViewController]; + wrapper.navigationBar.tintColor = self.tintColor; + wrapper.modalPresentationStyle = UIModalPresentationCustom; + wrapper.transitioningDelegate = self; + [_viewControllerPresentingAttribution presentViewController:wrapper animated:YES completion:nil]; + } + } + else + { + // page curl reveal behind map + // + attributionViewController.modalTransitionStyle = UIModalTransitionStylePartialCurl; + [_viewControllerPresentingAttribution presentViewController:attributionViewController animated:YES completion:nil]; + } + } +} + +- (void)dismissAttribution:(id)sender +{ + [_viewControllerPresentingAttribution dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView **)view +{ + *rect = _attributionButton.frame; +} + +- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController +{ + _attributionPopover = nil; +} + +- (id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source +{ + return self; +} + +- (id )animationControllerForDismissedController:(UIViewController *)dismissed +{ + return self; +} + +- (NSTimeInterval)transitionDuration:(id )transitionContext +{ + return (1.0 / 3.0); +} + +- (void)animateTransition:(id )transitionContext +{ + UIView *inView = [transitionContext containerView]; + UIView *fromView = [[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey] view]; + UIView *toView = [[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey] view]; + + CGPoint onScreenCenter = fromView.center; + + CGPoint offScreenCenter; + + if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) + { + CGFloat factor = ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft ? 1.0 : -1.0); + + offScreenCenter = CGPointMake(fromView.bounds.size.height * factor, fromView.bounds.size.width / 2); + } + else + { + offScreenCenter = CGPointMake(fromView.center.x, fromView.center.y + toView.bounds.size.height); + } + + BOOL isPresentation; + + if ([[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey] isKindOfClass:[UINavigationController class]] && + [[(UINavigationController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey] topViewController] isKindOfClass:[RMAttributionViewController class]]) + { + isPresentation = YES; + + [inView addSubview:toView]; + + toView.bounds = fromView.bounds; + + toView.center = offScreenCenter; + } + else + { + isPresentation = NO; + + fromView.center = onScreenCenter; + } + + [UIView animateWithDuration:[self transitionDuration:transitionContext] + delay:0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^(void) + { + fromView.userInteractionEnabled = NO; + + if (isPresentation) + { + toView.center = onScreenCenter; + } + else + { + fromView.center = offScreenCenter; + + toView.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic; + } + } + completion:^(BOOL finished) + { + if (isPresentation) + { + fromView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed; + } + else + { + toView.userInteractionEnabled = YES; + + [fromView removeFromSuperview]; + } + + [transitionContext completeTransition:YES]; + }]; +} + @end diff --git a/MapView/Map/RMMapViewDelegate.h b/MapView/Map/RMMapViewDelegate.h index ef19cb4cd..3557ca784 100644 --- a/MapView/Map/RMMapViewDelegate.h +++ b/MapView/Map/RMMapViewDelegate.h @@ -1,7 +1,7 @@ // // RMMapViewDelegate.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -31,53 +31,224 @@ @class RMAnnotation; @class RMUserLocation; +typedef enum : NSUInteger { + RMMapLayerDragStateNone = 0, + RMMapLayerDragStateStarting, + RMMapLayerDragStateDragging, + RMMapLayerDragStateCanceling, + RMMapLayerDragStateEnding +} RMMapLayerDragState; + typedef enum : NSUInteger { RMUserTrackingModeNone = 0, RMUserTrackingModeFollow = 1, RMUserTrackingModeFollowWithHeading = 2 } RMUserTrackingMode; -// Use this for notifications of map panning, zooming, and taps on the RMMapView. +/** The RMMapViewDelegate protocol defines a set of optional methods that you can use to receive map-related update messages. Because many map operations require the RMMapView class to load data asynchronously, the map view calls these methods to notify your application when specific operations complete. The map view also uses these methods to request annotation layers and to manage interactions with those layers. */ @protocol RMMapViewDelegate @optional +/** @name Working With Annotation Layers */ + +/** Returns (after creating or reusing) the layer associated with the specified annotation object. +* +* An annotation layer can be created using RMMapLayer and its subclasses, such as RMMarker for points and RMShape for shapes such as lines and polygons. +* +* If the object in the annotation parameter is an instance of the RMUserLocation class, you can provide a custom layer to denote the user’s location. To display the user’s location using the default system layer, return `nil`. +* +* If you do not implement this method, or if you return `nil` from your implementation for annotations other than the user location annotation, the map view does not display a layer for the annotation. +* +* @param mapView The map view that requested the annotation layer. +* @param annotation The object representing the annotation that is about to be displayed. In addition to your custom annotations, this object could be an RMUserLocation object representing the user’s current location. +* @return The annotation layer to display for the specified annotation or `nil` if you do not want to display a layer. */ - (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation; + +/** Returns a block used for determining the display sort order of annotation layers. The block will be called repeatedly during map change events to ensure annotation layers stay sorted in the desired order. +* +* If you do not implement this method, a default sort order will be used as follows: +* +* 1. User location annotations are below all others. These can be distinguished by `annotation.isUserLocationAnnotation = YES`. +* +* 1. Amongst user location annotations, the accuracy circle is below the tracking halo, which is below the user location. These can be distinguished by `annotation.annotationType = kRMTrackingHaloAnnotationTypeName`, `annotation.annotationType = kRMAccuracyCircleAnnotationTypeName`, and checking annotation object type against RMUserLocation. +* +* 1. Cluster annotations are above non-cluster annotations. These can be distinguished by `annotation.isClusterAnnotation = YES`. +* +* 1. Markers are above shapes. These can be distinguished by checking annotation object type against RMMarker. +* +* 1. The remaining annotations are sorted with those closer to the bottom of the view above those closer to the top of the view. This includes during user tracking mode map rotation events, when markers always remain upright and their relative layer positions change. +* +* In all cases, any currently selected annotation (and its callout, if visible) are shown above all other annotations. When deselected, the desired sort order is reapplied. +* +* Your implementation of this method should be as lightweight as possible to avoid affecting map renderering performance. +* +* @see [RMAnnotation isUserLocationAnnotation] +* @see [RMAnnotation annotationType] +* @see [RMAnnotation isClusterAnnotation] +* @see [RMMapView coordinateToPixel:] +* +* @param mapView The map view whose annotations need sorting. +* @return A comparison block to use in order to sort the annotations. */ +- (NSComparator)annotationSortingComparatorForMapView:(RMMapView *)mapView; + +/** Tells the delegate that the visible layer for an annotation is about to be hidden from view due to scrolling or zooming the map. +* @param mapView The map view whose annotation alyer will be hidden. +* @param annotation The annotation whose layer will be hidden. */ - (void)mapView:(RMMapView *)mapView willHideLayerForAnnotation:(RMAnnotation *)annotation; + +/** Tells the delegate that the visible layer for an annotation has been hidden from view due to scrolling or zooming the map. +* @param mapView The map view whose annotation layer was hidden. +* @param annotation The annotation whose layer was hidden. */ - (void)mapView:(RMMapView *)mapView didHideLayerForAnnotation:(RMAnnotation *)annotation; -- (void)beforeMapMove:(RMMapView *)map; -- (void)afterMapMove:(RMMapView *)map; +/** Tells the delegate that one of its annotations was selected. +* +* You can use this method to track changes in the selection state of annotations. +* @param mapView The map view containing the annotation. +* @param annotation The annotation that was selected. */ +- (void)mapView:(RMMapView *)mapView didSelectAnnotation:(RMAnnotation *)annotation; + +/** Tells the delegate that one of its annotations was deselected. +* +* You can use this method to track changes in the selection state of annotations. +* @param mapView The map view containing the annotation. +* @param annotation The annotation that was deselected. */ +- (void)mapView:(RMMapView *)mapView didDeselectAnnotation:(RMAnnotation *)annotation; -- (void)beforeMapZoom:(RMMapView *)map; -- (void)afterMapZoom:(RMMapView *)map; +/** @name Responding to Map Position Changes */ -/* - \brief Tells the delegate that the region displayed by the map view just changed. - \details This method is called whenever the currently displayed map region changes. - During scrolling and zooming, this method may be called many times to report updates to the map position. - Therefore, your implementation of this method should be as lightweight as possible to avoid affecting scrolling and zooming performance. - */ +/** Tells the delegate when a map is about to move. +* @param map The map view that is about to move. +* @param wasUserAction A Boolean indicating whether the map move is in response to a user action or not. */ +- (void)beforeMapMove:(RMMapView *)map byUser:(BOOL)wasUserAction; + +/** Tells the delegate when a map has finished moving. +* @param map The map view that has finished moving. +* @param wasUserAction A Boolean indicating whether the map move was in response to a user action or not. */ +- (void)afterMapMove:(RMMapView *)map byUser:(BOOL)wasUserAction; + +/** Tells the delegate when a map is about to zoom. +* @param map The map view that is about to zoom. +* @param wasUserAction A Boolean indicating whether the map zoom is in response to a user action or not. */ +- (void)beforeMapZoom:(RMMapView *)map byUser:(BOOL)wasUserAction; + +/** Tells the delegate when a map has finished zooming. +* @param map The map view that has finished zooming. +* @param wasUserAction A Boolean indicating whether the map zoom was in response to a user action or not. */ +- (void)afterMapZoom:(RMMapView *)map byUser:(BOOL)wasUserAction; + +/** Tells the delegate that the region displayed by the map view just changed. +* +* This method is called whenever the currently displayed map region changes. During scrolling, this method may be called many times to report updates to the map position. Therefore, your implementation of this method should be as lightweight as possible to avoid affecting scrolling performance. +* @param mapView The map view whose visible region changed. */ - (void)mapViewRegionDidChange:(RMMapView *)mapView; +/** @name Responding to Map Gestures */ + +/** Tells the delegate when the user double-taps a map view. +* @param map The map that was double-tapped. +* @param point The point at which the map was double-tapped. */ - (void)doubleTapOnMap:(RMMapView *)map at:(CGPoint)point; -- (void)doubleTapTwoFingersOnMap:(RMMapView *)map at:(CGPoint)point; + +/** Tells the delegate when the user taps a map view. +* @param map The map that was tapped. +* @param point The point at which the map was tapped. */ - (void)singleTapOnMap:(RMMapView *)map at:(CGPoint)point; + +/** Tells the delegate when the user taps a map view with two fingers. +* @param map The map that was tapped. +* @param point The center point at which the map was tapped. */ - (void)singleTapTwoFingersOnMap:(RMMapView *)map at:(CGPoint)point; -- (void)longSingleTapOnMap:(RMMapView *)map at:(CGPoint)point; +/** Tells the delegate when the user long-presses a map view. +* @param map The map that was long-pressed. +* @param point The point at which the map was long-pressed. */ +- (void)longPressOnMap:(RMMapView *)map at:(CGPoint)point; + +/** @name Responding to User Annotation Gestures */ + +/** Tells the delegate when the user taps the layer for an annotation. +* @param annotation The annotation that was tapped. +* @param map The map view. */ - (void)tapOnAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map; + +/** Tells the delegate when the user double-taps the layer for an annotation. +* @param annotation The annotation that was double-tapped. +* @param map The map view. */ - (void)doubleTapOnAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map; + +/** Tells the delegate when the user long-presses the layer for an annotation. +* @param annotation The annotation that was long-pressed. +* @param map The map view. */ +- (void)longPressOnAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map; + +/** Tells the delegate when the user taps the label for an annotation. +* @param annotation The annotation whose label was was tapped. +* @param map The map view. */ - (void)tapOnLabelForAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map; + +/** Tells the delegate when the user double-taps the label for an annotation. +* @param annotation The annotation whose label was was double-tapped. +* @param map The map view. */ - (void)doubleTapOnLabelForAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map; -- (BOOL)mapView:(RMMapView *)map shouldDragAnnotation:(RMAnnotation *)annotation; -- (void)mapView:(RMMapView *)map didDragAnnotation:(RMAnnotation *)annotation withDelta:(CGPoint)delta; -- (void)mapView:(RMMapView *)map didEndDragAnnotation:(RMAnnotation *)annotation; +/** Tells the delegate that the user tapped one of the annotation layer's accessory buttons. +* +* Accessory views contain custom content and are positioned on either side of the annotation title text. If a view you specify is a descendant of the UIControl class, the map view calls this method as a convenience whenever the user taps your view. You can use this method to respond to taps and perform any actions associated with that control. For example, if your control displayed additional information about the annotation, you could use this method to present a modal panel with that information. +* +* If your custom accessory views are not descendants of the UIControl class, the map view does not call this method. +* @param control The control that was tapped. +* @param annotation The annotation whose callout control was tapped. +* @param map The map view containing the specified annotation. */ +- (void)tapOnCalloutAccessoryControl:(UIControl *)control forAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map; + +/** Asks the delegate whether the user should be allowed to drag the layer for an annotation. +* @param mapView The map view. +* @param annotation The annotation the user is attempting to drag. +* @return A Boolean value indicating whether the user should be allowed to drag the annotation's layer. */ +- (BOOL)mapView:(RMMapView *)mapView shouldDragAnnotation:(RMAnnotation *)annotation; +/** Tells the delegate that the drag state of one of its annotations changed. +* +* The drag state typically changes in response to user interactions with the annotation layer. However, the annotation layer itself is responsible for changing that state as well. +* @param mapView The map view containing the annotation layer. +* @param annotation The annotation whose drag state changed. +* @param newState The new drag state of the annotation layer. +* @param oldState The previous drag state of the annotation layer. */ +- (void)mapView:(RMMapView *)mapView annotation:(RMAnnotation *)annotation didChangeDragState:(RMMapLayerDragState)newState fromOldState:(RMMapLayerDragState)oldState; + +/** @name Tracking the User Location */ + +/** Tells the delegate that the map view will start tracking the user’s position. +* +* This method is called when the value of the showsUserLocation property changes to YES. +* @param mapView The map view that is tracking the user’s location. */ - (void)mapViewWillStartLocatingUser:(RMMapView *)mapView; + +/** Tells the delegate that the map view stopped tracking the user’s location. +* +* This method is called when the value of the showsUserLocation property changes to NO. +* @param mapView The map view that stopped tracking the user’s location. */ - (void)mapViewDidStopLocatingUser:(RMMapView *)mapView; + +/** Tells the delegate that the location of the user was updated. +* +* While the showsUserLocation property is set to YES, this method is called whenever a new location update is received by the map view. This method is also called if the map view’s user tracking mode is set to RMUserTrackingModeFollowWithHeading and the heading changes. +* +* This method is not called if the application is currently running in the background. If you want to receive location updates while running in the background, you must use the Core Location framework. +* @param mapView The map view that is tracking the user’s location. +* @param userLocation The location object representing the user’s latest location. */ - (void)mapView:(RMMapView *)mapView didUpdateUserLocation:(RMUserLocation *)userLocation; + +/** Tells the delegate that an attempt to locate the user’s position failed. +* @param mapView The map view that is tracking the user’s location. +* @param error An error object containing the reason why location tracking failed. */ - (void)mapView:(RMMapView *)mapView didFailToLocateUserWithError:(NSError *)error; + +/** Tells the delegate that the user tracking mode changed. +* @param mapView The map view whose user tracking mode changed. +* @param mode The mode used to track the user’s location. +* @param animated If YES, the change from the current mode to the new mode is animated; otherwise, it is not. This parameter affects only tracking mode changes. Changes to the user location or heading are always animated. */ - (void)mapView:(RMMapView *)mapView didChangeUserTrackingMode:(RMUserTrackingMode)mode animated:(BOOL)animated; @end diff --git a/MapView/Map/RMMapboxSource.h b/MapView/Map/RMMapboxSource.h new file mode 100644 index 000000000..15c1f656c --- /dev/null +++ b/MapView/Map/RMMapboxSource.h @@ -0,0 +1,152 @@ +// +// RMMapboxSource.h +// +// Created by Justin R. Miller on 5/17/11. +// Copyright 2012-2013 Mapbox. +// 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. +// +// * Neither the name of Mapbox, nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// 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. +// + +#import "RMAbstractWebMapSource.h" + +#define kMapboxDefaultTileSize 256 +#define kMapboxDefaultMinTileZoom 0 +#define kMapboxDefaultMaxTileZoom 18 +#define kMapboxDefaultLatLonBoundingBox ((RMSphericalTrapezium){ .northEast = { .latitude = 90, .longitude = 180 }, \ + .southWest = { .latitude = -90, .longitude = -180 } }) + +#define kMapboxPlaceholderMapID @"examples.map-z2effxa8" + +// constants for the image quality API (see https://www.mapbox.com/developers/api/maps/#format) +typedef enum : NSUInteger { + RMMapboxSourceQualityFull = 0, // default + RMMapboxSourceQualityPNG32 = 1, // 32 color indexed PNG + RMMapboxSourceQualityPNG64 = 2, // 64 color indexed PNG + RMMapboxSourceQualityPNG128 = 3, // 128 color indexed PNG + RMMapboxSourceQualityPNG256 = 4, // 256 color indexed PNG + RMMapboxSourceQualityJPEG70 = 5, // 70% quality JPEG + RMMapboxSourceQualityJPEG80 = 6, // 80% quality JPEG + RMMapboxSourceQualityJPEG90 = 7 // 90% quality JPEG +} RMMapboxSourceQuality; + +@class RMMapView; + +/** An RMMapboxSource is used to display map tiles from a network-based map hosted on [Mapbox](https://mapbox.com/plans) or the open source [TileStream](https://github.com/mapbox/tilestream) software. Maps are referenced by their Mapbox map ID or by a file or URL containing [TileJSON](https://www.mapbox.com/foundations/an-open-platform/#tilejson). */ +@interface RMMapboxSource : RMAbstractWebMapSource + +/** @name Creating Tile Sources */ + +- (id)init DEPRECATED_MSG_ATTRIBUTE("please use an explicit map ID, URL, or TileJSON string."); + +/** Initialize a tile source using the Mapbox map ID. +* +* This method requires a network connection in order to download the TileJSON used to define the tile source. +* +* @param mapID The Mapbox map ID string, typically in the format `.map-`. +* @return An initialized Mapbox tile source. */ +- (id)initWithMapID:(NSString *)mapID; + +/** Initialize a tile source with either a remote or local TileJSON structure. +* +* Passing a remote URL requires a network connection. If offline functionality is desired, you should cache the TileJSON locally at a prior date, then pass a file path URL to this method. +* +* @see tileJSON +* +* @param referenceURL A remote or file path URL pointing to a TileJSON structure. +* @return An initialized Mapbox tile source. */ +- (id)initWithReferenceURL:(NSURL *)referenceURL; + +/** Initialize a tile source with TileJSON. +* @param tileJSON A string containing TileJSON. +* @return An initialized Mapbox tile source. */ +- (id)initWithTileJSON:(NSString *)tileJSON; + +/** For TileJSON 2.1.0+ layers, initialize a tile source and automatically find and add point annotations from [simplestyle](https://www.mapbox.com/foundations/an-open-platform/#simplestyle) data. +* +* This method requires a network connection in order to download the TileJSON used to define the tile source. +* +* @param mapID The Mapbox map ID string, typically in the format `.map-`. +* @param mapView A map view on which to display the annotations. +* @return An initialized Mapbox tile source. */ +- (id)initWithMapID:(NSString *)mapID enablingDataOnMapView:(RMMapView *)mapView; + +/** For TileJSON 2.1.0+ layers, initialize a tile source and automatically find and add point annotations from [simplestyle](https://www.mapbox.com/foundations/an-open-platform/#simplestyle) data. +* @param tileJSON A string containing TileJSON. +* @param mapView A map view on which to display the annotations. +* @return An initialized Mapbox tile source. */ +- (id)initWithTileJSON:(NSString *)tileJSON enablingDataOnMapView:(RMMapView *)mapView; + +/** For TileJSON 2.1.0+ layers, initialize a tile source and automatically find and add point annotations from [simplestyle](https://www.mapbox.com/foundations/an-open-platform/#simplestyle) data. +* +* Passing a remote URL requires a network connection. If offline functionality is desired, you should cache the TileJSON locally at a prior date, then pass a file path URL to this method. +* +* @see tileJSON +* +* @param referenceURL A remote or file path URL pointing to a TileJSON structure. +* @param mapView A map view on which to display the annotations. +* @return An initialized Mapbox tile source. */ +- (id)initWithReferenceURL:(NSURL *)referenceURL enablingDataOnMapView:(RMMapView *)mapView; + +/** @name Querying Tile Source Information */ + +/** Any available HTML-formatted map legend data for the tile source, suitable for display in a `UIWebView`. */ +- (NSString *)legend; + +/** A suggested starting center coordinate for the map layer. */ +- (CLLocationCoordinate2D)centerCoordinate; + +/** A suggested starting center zoom level for the map layer. */ +- (float)centerZoom; + +/** Returns `YES` if the tile source provides full-world coverage; otherwise, returns `NO`. */ +- (BOOL)coversFullWorld; + +/** The TileJSON for the map layer. Useful for saving locally to use in instantiating a tile source while offline. */ +@property (nonatomic, readonly, strong) NSString *tileJSON; + +/** The TileJSON URL for the map layer. Useful for retrieving TileJSON to save locally to use in instantiating a tile source while offline. */ +@property (nonatomic, readonly, strong) NSURL *tileJSONURL; + +/** The TileJSON data in dictionary format. Useful for retrieving info about the layer without having to parse TileJSON. */ +@property (nonatomic, readonly, strong) NSDictionary *infoDictionary; + +/** @name Configuring Map Options */ + +/** Image quality that is retrieved from the network. Useful for lower-bandwidth environments. The default is to provide full-quality imagery. +* +* Note that you may want to clear the tile cache after changing this value in order to provide a consistent experience. */ +@property (nonatomic, assign) RMMapboxSourceQuality imageQuality; + ++ (BOOL)isUsingLargeTiles; + +#if OS_OBJECT_USE_OBJC +@property (nonatomic, readonly, strong) dispatch_queue_t dataQueue; +#else +@property (nonatomic, readonly, assign) dispatch_queue_t dataQueue; +#endif + +@end diff --git a/MapView/Map/RMMapboxSource.m b/MapView/Map/RMMapboxSource.m new file mode 100644 index 000000000..5e4b0278e --- /dev/null +++ b/MapView/Map/RMMapboxSource.m @@ -0,0 +1,407 @@ +// +// RMMapboxSource.m +// +// Created by Justin R. Miller on 5/17/11. +// Copyright 2012-2013 Mapbox. +// 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. +// +// * Neither the name of Mapbox, nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// 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. +// + +#import "RMMapboxSource.h" + +#import "RMMapView.h" +#import "RMPointAnnotation.h" +#import "RMConfiguration.h" + +@interface RMMapboxSource () + +@property (nonatomic, strong) NSDictionary *infoDictionary; +@property (nonatomic, strong) NSString *tileJSON; +@property (nonatomic, strong) NSString *uniqueTilecacheKey; + +@end + +#pragma mark - + +@implementation RMMapboxSource + +@synthesize infoDictionary=_infoDictionary, tileJSON=_tileJSON, imageQuality=_imageQuality, dataQueue=_dataQueue, uniqueTilecacheKey=_uniqueTilecacheKey; + +- (id)init +{ + return [self initWithMapID:kMapboxPlaceholderMapID]; +} + +- (id)initWithMapID:(NSString *)mapID +{ + return [self initWithMapID:mapID enablingDataOnMapView:nil]; +} + +- (id)initWithTileJSON:(NSString *)tileJSON +{ + return [self initWithTileJSON:tileJSON enablingDataOnMapView:nil]; +} + +- (id)initWithTileJSON:(NSString *)tileJSON enablingDataOnMapView:(RMMapView *)mapView +{ + if (self = [super init]) + { + NSAssert([[[RMConfiguration sharedInstance] accessToken] length], @"an access token is required to use Mapbox map tiles"); + + _dataQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + + _infoDictionary = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:[tileJSON dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:nil]; + if ( ! _infoDictionary) + return nil; + + _tileJSON = tileJSON; + + if ([_infoDictionary[@"id"] hasPrefix:@"examples."]) + RMLog(@"Using watermarked example map ID %@. Please go to https://mapbox.com and create your own map style.", _infoDictionary[@"id"]); + + _uniqueTilecacheKey = [NSString stringWithFormat:@"Mapbox-%@%@%@", _infoDictionary[@"id"], (_infoDictionary[@"version"] ? [@"-" stringByAppendingString:_infoDictionary[@"version"]] : @""), + ([RMMapboxSource isUsingLargeTiles] ? @"-512" : @"")]; + + id dataObject = nil; + + if (mapView && (dataObject = _infoDictionary[@"data"]) && dataObject) + { + dispatch_async(_dataQueue, ^(void) + { + if ([dataObject isKindOfClass:[NSArray class]] && [[dataObject objectAtIndex:0] isKindOfClass:[NSString class]]) + { + NSURL *dataURL = [NSURL URLWithString:[dataObject objectAtIndex:0]]; + + NSMutableString *jsonString = nil; + + if (dataURL && (jsonString = [NSMutableString brandedStringWithContentsOfURL:dataURL encoding:NSUTF8StringEncoding error:nil]) && jsonString) + { + if ([jsonString hasPrefix:@"grid("]) + { + [jsonString replaceCharactersInRange:NSMakeRange(0, 5) withString:@""]; + [jsonString replaceCharactersInRange:NSMakeRange([jsonString length] - 2, 2) withString:@""]; + } + + id jsonObject = nil; + + if ((jsonObject = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]) && [jsonObject isKindOfClass:[NSDictionary class]]) + { + for (NSDictionary *feature in jsonObject[@"features"]) + { + if ([feature[@"geometry"][@"type"] isEqualToString:@"Point"]) + { + NSDictionary *properties = feature[@"properties"]; + + CLLocationCoordinate2D coordinate = { + .longitude = [feature[@"geometry"][@"coordinates"][0] floatValue], + .latitude = [feature[@"geometry"][@"coordinates"][1] floatValue] + }; + + RMAnnotation *annotation = nil; + + if ([mapView.delegate respondsToSelector:@selector(mapView:layerForAnnotation:)]) + annotation = [RMAnnotation annotationWithMapView:mapView coordinate:coordinate andTitle:properties[@"title"]]; + else + annotation = [RMPointAnnotation annotationWithMapView:mapView coordinate:coordinate andTitle:properties[@"title"]]; + + annotation.userInfo = properties; + + dispatch_async(dispatch_get_main_queue(), ^(void) + { + [mapView addAnnotation:annotation]; + }); + } + } + } + } + } + }); + } + } + + return self; +} + +- (id)initWithReferenceURL:(NSURL *)referenceURL +{ + return [self initWithReferenceURL:referenceURL enablingDataOnMapView:nil]; +} + +- (id)initWithReferenceURL:(NSURL *)referenceURL enablingDataOnMapView:(RMMapView *)mapView +{ + id dataObject = nil; + + if ([[referenceURL pathExtension] isEqualToString:@"jsonp"]) + { + referenceURL = [NSURL URLWithString:[[referenceURL absoluteString] stringByReplacingOccurrencesOfString:@".jsonp" + withString:@".json" + options:NSAnchoredSearch & NSBackwardsSearch + range:NSMakeRange(0, [[referenceURL absoluteString] length])]]; + } + + NSError *error = nil; + + if ([[referenceURL pathExtension] isEqualToString:@"json"] && (dataObject = [NSString brandedStringWithContentsOfURL:referenceURL encoding:NSUTF8StringEncoding error:&error]) && dataObject) + { + if (error && [error.domain isEqual:NSURLErrorDomain] && error.code == -1012) + { +#ifdef DEBUG + NSAssert(![[dataObject lowercaseString] hasSuffix:@"invalid token\"}"], @"invalid token in use"); +#endif + } + + return [self initWithTileJSON:dataObject enablingDataOnMapView:mapView]; + } + + return nil; +} + +- (id)initWithMapID:(NSString *)mapID enablingDataOnMapView:(RMMapView *)mapView +{ + return [self initWithReferenceURL:[self canonicalURLForMapID:mapID] enablingDataOnMapView:mapView]; +} + +- (void)dealloc +{ +#if ! OS_OBJECT_USE_OBJC + if (_dataQueue) + dispatch_release(_dataQueue); +#endif +} + +#pragma mark + +- (NSURL *)canonicalURLForMapID:(NSString *)mapID +{ + return [NSURL URLWithString:[NSString stringWithFormat:@"https://api.tiles.mapbox.com/v4/%@.json?secure%@", mapID, + [@"&access_token=" stringByAppendingString:[[RMConfiguration sharedInstance] accessToken]]]]; +} + +- (NSURL *)tileJSONURL +{ + return [self canonicalURLForMapID:self.infoDictionary[@"id"]]; +} + +- (NSURL *)URLForTile:(RMTile)tile +{ + NSInteger zoom = tile.zoom; + NSInteger x = tile.x; + NSInteger y = tile.y; + + if (self.infoDictionary[@"scheme"] && [self.infoDictionary[@"scheme"] isEqual:@"tms"]) + y = pow(2, zoom) - tile.y - 1; + + NSString *tileURLString = nil; + + if (self.infoDictionary[@"tiles"]) + tileURLString = self.infoDictionary[@"tiles"][0]; + + else + tileURLString = self.infoDictionary[@"tileURL"]; + + tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@"{z}" withString:[[NSNumber numberWithInteger:zoom] stringValue]]; + tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@"{x}" withString:[[NSNumber numberWithInteger:x] stringValue]]; + tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@"{y}" withString:[[NSNumber numberWithInteger:y] stringValue]]; + + if ([[UIScreen mainScreen] scale] > 1.0) + tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@".png" withString:@"@2x.png"]; + + if (_imageQuality != RMMapboxSourceQualityFull) + { + NSString *qualityExtension = nil; + + switch (_imageQuality) + { + case RMMapboxSourceQualityPNG32: + { + qualityExtension = @".png32"; + break; + } + case RMMapboxSourceQualityPNG64: + { + qualityExtension = @".png64"; + break; + } + case RMMapboxSourceQualityPNG128: + { + qualityExtension = @".png128"; + break; + } + case RMMapboxSourceQualityPNG256: + { + qualityExtension = @".png256"; + break; + } + case RMMapboxSourceQualityJPEG70: + { + qualityExtension = @".jpg70"; + break; + } + case RMMapboxSourceQualityJPEG80: + { + qualityExtension = @".jpg80"; + break; + } + case RMMapboxSourceQualityJPEG90: + { + qualityExtension = @".jpg90"; + break; + } + case RMMapboxSourceQualityFull: + default: + { + qualityExtension = @".png"; + break; + } + } + + tileURLString = [tileURLString stringByReplacingOccurrencesOfString:@".png" + withString:qualityExtension + options:NSAnchoredSearch | NSBackwardsSearch + range:NSMakeRange(0, [tileURLString length])]; + } + + return [NSURL URLWithString:tileURLString]; +} + +- (float)minZoom +{ + return [self.infoDictionary[@"minzoom"] floatValue]; +} + +- (float)maxZoom +{ + return [self.infoDictionary[@"maxzoom"] floatValue]; +} + +- (RMSphericalTrapezium)latitudeLongitudeBoundingBox +{ + id bounds = self.infoDictionary[@"bounds"]; + + NSArray *parts = nil; + + if ([bounds isKindOfClass:[NSArray class]]) + parts = bounds; + + else + parts = [bounds componentsSeparatedByString:@","]; + + if ([parts count] == 4) + { + RMSphericalTrapezium bounds = { + .southWest = { + .longitude = [[parts objectAtIndex:0] doubleValue], + .latitude = [[parts objectAtIndex:1] doubleValue], + }, + .northEast = { + .longitude = [[parts objectAtIndex:2] doubleValue], + .latitude = [[parts objectAtIndex:3] doubleValue], + }, + }; + + return bounds; + } + + return kMapboxDefaultLatLonBoundingBox; +} + +- (BOOL)coversFullWorld +{ + RMSphericalTrapezium ownBounds = [self latitudeLongitudeBoundingBox]; + RMSphericalTrapezium defaultBounds = kMapboxDefaultLatLonBoundingBox; + + if (ownBounds.southWest.longitude <= defaultBounds.southWest.longitude + 10 && + ownBounds.northEast.longitude >= defaultBounds.northEast.longitude - 10) + return YES; + + return NO; +} + +- (NSString *)legend +{ + return self.infoDictionary[@"legend"]; +} + +- (CLLocationCoordinate2D)centerCoordinate +{ + if (self.infoDictionary[@"center"]) + { + return CLLocationCoordinate2DMake([self.infoDictionary[@"center"][1] doubleValue], + [self.infoDictionary[@"center"][0] doubleValue]); + } + + return CLLocationCoordinate2DMake(0, 0); +} + +- (float)centerZoom +{ + if (self.infoDictionary[@"center"]) + { + return [self.infoDictionary[@"center"][2] floatValue]; + } + + return roundf(([self maxZoom] + [self minZoom]) / 2); +} + ++ (BOOL)isUsingLargeTiles +{ + return ([[UIScreen mainScreen] scale] > 1.0); +} + +- (NSString *)uniqueTilecacheKey +{ + return _uniqueTilecacheKey; +} + +- (NSUInteger)tileSideLength +{ + return ([RMMapboxSource isUsingLargeTiles] ? 512 : kMapboxDefaultTileSize); +} + +- (NSString *)shortName +{ + return self.infoDictionary[@"name"]; +} + +- (NSString *)longDescription +{ + return self.infoDictionary[@"description"]; +} + +- (NSString *)shortAttribution +{ + return self.infoDictionary[@"attribution"]; +} + +- (NSString *)longAttribution +{ + return [self shortAttribution]; +} + +@end diff --git a/MapView/Map/RMMarker.h b/MapView/Map/RMMarker.h index 04ac8ddcb..b0756c06a 100644 --- a/MapView/Map/RMMarker.h +++ b/MapView/Map/RMMarker.h @@ -1,7 +1,7 @@ // // RMMarker.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -29,10 +29,13 @@ #import "RMMapLayer.h" #import "RMFoundation.h" -@class RMMarkerStyle; +typedef enum : NSUInteger { + RMMarkerMapboxImageSizeSmall, + RMMarkerMapboxImageSizeMedium, + RMMarkerMapboxImageSizeLarge +} RMMarkerMapboxImageSize; -// one marker drawn on the map. Note that RMMarker ultimately descends from CALayer, and has an image contents. -// RMMarker inherits "position" and "anchorPoint" from CALayer. +/** An RMMarker object is used for simple point annotations on a map view, represented as a single image. RMMarker objects do not change in size when the map view zooms in or out, but instead stay the same size to consistently represent a point on the map view. */ @interface RMMarker : RMMapLayer { // Text label, visible by default if it has content, but not required. @@ -41,39 +44,110 @@ UIColor *textBackgroundColor; } -@property (nonatomic, retain) UIView *label; -@property (nonatomic, retain) UIColor *textForegroundColor; -@property (nonatomic, retain) UIColor *textBackgroundColor; +/** @name Setting Label Properties */ -// the font used for labels when another font is not explicitly requested; currently [UIFont systemFontOfSize:15] +/** A custom label for the marker. The label is shown when first set. */ +@property (nonatomic, strong) UIView *label; + +/** The marker object's label text foreground color. Defaults to black. */ +@property (nonatomic, strong) UIColor *textForegroundColor; + +/** The marker object's label text background color. Defaults to clear. */ +@property (nonatomic, strong) UIColor *textBackgroundColor; + +/** The font used for labels when another font is not explicitly requested. The default is the system font with size `15`. */ + (UIFont *)defaultFont; -// returns RMMarker initialized with #image, and the default anchor point (0.5, 0.5) +/** @name Creating Markers With Images */ + +/** Initializes and returns a newly allocated marker object using the specified image. +* @param image An image to use for the marker. */ - (id)initWithUIImage:(UIImage *)image; -// \brief returns RMMarker initialized with provided image and anchorPoint. -// #anchorPoint x and y range from 0 to 1, normalized to the width and height of image, -// referenced to upper left corner, y increasing top to bottom. To put the image's upper right corner on the marker's -// #projectedLocation, use an anchor point of (1.0, 0.0); +/** Initializes and returns a newly allocated marker object using the specified image and anchor point. +* @param image An image to use for the marker. +* @param anchorPoint A point representing a range from `0` to `1` in each of the height and width coordinate space, normalized to the size of the image, at which to place the image. +* @return An initialized marker object. */ - (id)initWithUIImage:(UIImage *)image anchorPoint:(CGPoint)anchorPoint; -// changes the labelView to a UILabel with supplied #text and default marker font, using existing text foreground/background color. +/** @name Creating Markers Using Mapbox Images */ + +/** Initializes and returns a newly allocated marker object using a red, medium-sized star pin image. */ +- (id)initWithMapboxMarkerImage; + +/** Initializes and returns a newly allocated marker object using a red, medium-sized pin image and a given symbol name, e.g., `bus`. +* @param symbolName A symbol name from the [Maki](https://mapbox.com/maki/) icon set. +* @return An initialized RMMarker layer. */ +- (id)initWithMapboxMarkerImage:(NSString *)symbolName; + +/** Initializes and returns a newly allocated marker object using a medium-sized pin image, a given symbol name, e.g., `bus`, and a given color. +* @param symbolName A symbol name from the [Maki](https://mapbox.com/maki/) icon set. +* @param color A color for the marker. +* @return An initialized RMMarker layer. */ +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColor:(UIColor *)color; + +/** Initializes and returns a newly allocated marker object using a pin image, a given symbol name, e.g., `bus`, a given color, and a given size. +* @param symbolName A symbol name from the [Maki](https://mapbox.com/maki/) icon set. +* @param color A color for the marker. +* @param size A size for the marker. +* @return An initialized RMMarker layer. */ +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColor:(UIColor *)color size:(RMMarkerMapboxImageSize)size; + +/** Initializes and returns a newly allocated marker object using a medium-sized pin image, a given symbol name, e.g., `bus`, and a given HTML hex color, e.g., `ff0000`. +* @param symbolName A symbol name from the [Maki](https://mapbox.com/maki/) icon set. +* @param colorHex A color for the marker specified as an HTML hex code. +* @return An initialized RMMarker layer. */ +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColorHex:(NSString *)colorHex; + +/** Initializes and returns a newly allocated marker object using a pin image, a given symbol name, e.g., `bus`, a given HTML hex color, e.g., `ff0000`, and a given size, e.g., `large`. +* @param symbolName A symbol name from the [Maki](https://mapbox.com/maki/) icon set. +* @param colorHex A color for the marker specified as an HTML hex code. +* @param sizeString A size such as `small`, `medium`, or `large`. +* @return An initialized RMMarker layer. */ +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColorHex:(NSString *)colorHex sizeString:(NSString *)sizeString; + +/** Clears the local cache of Mapbox Marker images. Images are cached locally upon first use so that if the application goes offline, markers can still be used. */ ++ (void)clearCachedMapboxMarkers; + +/** @name Altering Labels */ + +/** Changes the label to a UILabel with the supplied text and default marker font and using the existing text foreground and background colors. +* @param text The text for the label. */ - (void)changeLabelUsingText:(NSString *)text; // changes the labelView to a UILabel with supplied #text and default marker font, positioning the text some weird way i don't understand yet. Uses existing text color/background color. - (void)changeLabelUsingText:(NSString *)text position:(CGPoint)position; -// changes the labelView to a UILabel with supplied #text and default marker font, changing this marker's text foreground/background colors for this and future text strings. +/** Changes the label to a UILabel with the supplied text and font and using the given text foreground and background colors. +* @param text The text for the label. +* @param font A font to use for the label text. +* @param textColor The color for the label text. +* @param backgroundColor The color for the label background. */ - (void)changeLabelUsingText:(NSString *)text font:(UIFont *)font foregroundColor:(UIColor *)textColor backgroundColor:(UIColor *)backgroundColor; // changes the labelView to a UILabel with supplied #text and default marker font, changing this marker's text foreground/background colors for this and future text strings; modifies position as in #changeLabelUsingText:position. - (void)changeLabelUsingText:(NSString *)text position:(CGPoint)position font:(UIFont *)font foregroundColor:(UIColor *)textColor backgroundColor:(UIColor *)backgroundColor; +/** @name Showing and Hiding Labels */ + +/** Toggle the display of the marker's label, if any. If hidden, show and if shown, hide. */ - (void)toggleLabel; + +/** Show the marker's label, if any. */ - (void)showLabel; + +/** Hide the marker's label, if any. */ - (void)hideLabel; +/** @name Altering Images */ + +/** Replace the image for a marker. +* @param image An image to use for the marker. */ - (void)replaceUIImage:(UIImage *)image; + +/** Replace the image for a marker using a custom anchor point. +* @param image An image to use for the marker. +* @param anchorPoint A point representing a range from `0` to `1` in each of the height and width coordinate space, normalized to the size of the image, at which to place the image. */ - (void)replaceUIImage:(UIImage *)image anchorPoint:(CGPoint)anchorPoint; @end diff --git a/MapView/Map/RMMarker.m b/MapView/Map/RMMarker.m index f91fefb7f..bf220bf8b 100644 --- a/MapView/Map/RMMarker.m +++ b/MapView/Map/RMMarker.m @@ -1,7 +1,7 @@ // // RMMarker.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -26,7 +26,9 @@ // POSSIBILITY OF SUCH DAMAGE. #import "RMMarker.h" + #import "RMPixel.h" +#import "RMConfiguration.h" @implementation RMMarker @@ -36,6 +38,8 @@ @implementation RMMarker #define defaultMarkerAnchorPoint CGPointMake(0.5, 0.5) +#define kCachesPath [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] + + (UIFont *)defaultFont { return [UIFont systemFontOfSize:15]; @@ -65,6 +69,7 @@ - (id)initWithUIImage:(UIImage *)image anchorPoint:(CGPoint)_anchorPoint return nil; self.contents = (id)[image CGImage]; + self.contentsScale = image.scale; self.bounds = CGRectMake(0, 0, image.size.width, image.size.height); self.anchorPoint = _anchorPoint; @@ -74,12 +79,95 @@ - (id)initWithUIImage:(UIImage *)image anchorPoint:(CGPoint)_anchorPoint return self; } -- (void)dealloc +- (id)initWithMapboxMarkerImage { - self.label = nil; - self.textForegroundColor = nil; - self.textBackgroundColor = nil; - [super dealloc]; + return [self initWithMapboxMarkerImage:nil tintColor:nil size:RMMarkerMapboxImageSizeMedium]; +} + +- (id)initWithMapboxMarkerImage:(NSString *)symbolName +{ + return [self initWithMapboxMarkerImage:symbolName tintColor:nil size:RMMarkerMapboxImageSizeMedium]; +} + +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColor:(UIColor *)color +{ + return [self initWithMapboxMarkerImage:symbolName tintColor:color size:RMMarkerMapboxImageSizeMedium]; +} + +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColor:(UIColor *)color size:(RMMarkerMapboxImageSize)size +{ + NSString *sizeString = nil; + + switch (size) + { + case RMMarkerMapboxImageSizeSmall: + sizeString = @"small"; + break; + + case RMMarkerMapboxImageSizeMedium: + default: + sizeString = @"medium"; + break; + + case RMMarkerMapboxImageSizeLarge: + sizeString = @"large"; + break; + } + + NSString *colorHex = nil; + + if (color) + { + CGFloat white, red, green, blue, alpha; + + if ([color getRed:&red green:&green blue:&blue alpha:&alpha]) + { + colorHex = [NSString stringWithFormat:@"%02lx%02lx%02lx", (unsigned long)(red * 255), (unsigned long)(green * 255), (unsigned long)(blue * 255)]; + } + else if ([color getWhite:&white alpha:&alpha]) + { + colorHex = [NSString stringWithFormat:@"%02lx%02lx%02lx", (unsigned long)(white * 255), (unsigned long)(white * 255), (unsigned long)(white * 255)]; + } + } + + return [self initWithMapboxMarkerImage:symbolName tintColorHex:colorHex sizeString:sizeString]; +} + +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColorHex:(NSString *)colorHex +{ + return [self initWithMapboxMarkerImage:symbolName tintColorHex:colorHex sizeString:@"medium"]; +} + +- (id)initWithMapboxMarkerImage:(NSString *)symbolName tintColorHex:(NSString *)colorHex sizeString:(NSString *)sizeString +{ + NSAssert([[[RMConfiguration sharedInstance] accessToken] length], @"an access token is required to use Mapbox markers"); + + BOOL useRetina = ([[UIScreen mainScreen] scale] > 1.0); + + NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://api.tiles.mapbox.com/v4/marker/pin-%@%@%@%@.png%@", + (sizeString ? [sizeString substringToIndex:1] : @"m"), + (symbolName ? [@"-" stringByAppendingString:symbolName] : @""), + (colorHex ? [@"+" stringByAppendingString:[colorHex stringByReplacingOccurrencesOfString:@"#" withString:@""]] : @"+ff0000"), + (useRetina ? @"@2x" : @""), + [@"?access_token=" stringByAppendingString:[[RMConfiguration sharedInstance] accessToken]]]]; + + UIImage *image = nil; + + NSString *cachePath = [NSString stringWithFormat:@"%@/%@", kCachesPath, [imageURL lastPathComponent]]; + + if ((image = [UIImage imageWithData:[NSData dataWithContentsOfFile:cachePath] scale:(useRetina ? 2.0 : 1.0)]) && image) + return [self initWithUIImage:image]; + + [[NSFileManager defaultManager] createFileAtPath:cachePath contents:[NSData brandedDataWithContentsOfURL:imageURL] attributes:nil]; + + return [self initWithUIImage:[UIImage imageWithData:[NSData dataWithContentsOfFile:cachePath] scale:(useRetina ? 2.0 : 1.0)]]; +} + ++ (void)clearCachedMapboxMarkers +{ + for (NSString *filePath in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:kCachesPath error:nil]) + if ([[filePath lastPathComponent] hasPrefix:@"pin-"] && [[filePath lastPathComponent] hasSuffix:@".png"]) + [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@", kCachesPath, filePath] error:nil]; } #pragma mark - @@ -104,30 +192,25 @@ - (void)setLabel:(UIView *)aView return; if (label != nil) - { [[label layer] removeFromSuperlayer]; - [label release]; label = nil; - } if (aView != nil) { - label = [aView retain]; + label = aView; [self addSublayer:[label layer]]; } } - (void)setTextBackgroundColor:(UIColor *)newTextBackgroundColor { - [textBackgroundColor autorelease]; - textBackgroundColor = [newTextBackgroundColor retain]; + textBackgroundColor = newTextBackgroundColor; self.label.backgroundColor = textBackgroundColor; } - (void)setTextForegroundColor:(UIColor *)newTextForegroundColor { - [textForegroundColor autorelease]; - textForegroundColor = [newTextForegroundColor retain]; + textForegroundColor = newTextForegroundColor; if ([self.label respondsToSelector:@selector(setTextColor:)]) ((UILabel *)self.label).textColor = textForegroundColor; @@ -165,11 +248,10 @@ - (void)changeLabelUsingText:(NSString *)text position:(CGPoint)position font:(U [aLabel setBackgroundColor:backgroundColor]; [aLabel setTextColor:textColor]; [aLabel setFont:font]; - [aLabel setTextAlignment:UITextAlignmentCenter]; + [aLabel setTextAlignment:NSTextAlignmentCenter]; [aLabel setText:text]; [self setLabel:aLabel]; - [aLabel release]; } - (void)toggleLabel @@ -203,4 +285,42 @@ - (void)hideLabel } } +- (void)setDragState:(RMMapLayerDragState)dragState animated:(BOOL)animated +{ + if (dragState == RMMapLayerDragStateStarting) + { + [CATransaction begin]; + [CATransaction setAnimationDuration:(animated ? 0.3 : 0)]; + + self.opacity -= 0.1; + self.transform = CATransform3DScale(self.transform, 1.3, 1.3, 1.0); + + [CATransaction setCompletionBlock:^(void) + { + [super setDragState:RMMapLayerDragStateDragging animated:animated]; + }]; + + [CATransaction commit]; + } + else if (dragState == RMMapLayerDragStateCanceling || dragState == RMMapLayerDragStateEnding) + { + [CATransaction begin]; + [CATransaction setAnimationDuration:(animated ? 0.3 : 0)]; + + self.opacity += 0.1; + self.transform = CATransform3DScale(self.transform, 1.0/1.3, 1.0/1.3, 1.0); + + [CATransaction setCompletionBlock:^(void) + { + [super setDragState:RMMapLayerDragStateNone animated:animated]; + }]; + + [CATransaction commit]; + } + else + { + [super setDragState:dragState animated:animated]; + } +} + @end diff --git a/MapView/Map/RMMemoryCache.h b/MapView/Map/RMMemoryCache.h index 34851ec95..0b242f49e 100644 --- a/MapView/Map/RMMemoryCache.h +++ b/MapView/Map/RMMemoryCache.h @@ -29,11 +29,24 @@ #import "RMTile.h" #import "RMTileCache.h" +/** An RMMemoryCache object represents memory-based caching of map tile images. Since memory is constrained in the iOS environment, this cache is relatively small, but useful for increasing performance. */ @interface RMMemoryCache : NSObject +/** @name Initializing Memory Caches */ + +/** Initializes and returns a newly allocated memory cache object with the specified tile count capacity. +* @param aCapacity The maximum number of tiles to be held in the cache. +* @return An initialized memory cache object or `nil` if the object couldn't be created. */ - (id)initWithCapacity:(NSUInteger)aCapacity; -/// Remove the least-recently used image from cache, if cache is at or over capacity. Removes only 1 image. +/** @name Cache Capacity */ + +/** The capacity, in number of tiles, that the memory cache can hold. */ +@property (nonatomic, readonly, assign) NSUInteger capacity; + +/** @name Making Space in the Cache */ + +/** Remove the least-recently used image from the cache if the cache is at or over capacity. This removes a single image from the cache. */ - (void)makeSpaceInCache; @end diff --git a/MapView/Map/RMMemoryCache.m b/MapView/Map/RMMemoryCache.m index 7162ea87d..2817c8876 100644 --- a/MapView/Map/RMMemoryCache.m +++ b/MapView/Map/RMMemoryCache.m @@ -40,8 +40,6 @@ - (id)initWithCapacity:(NSUInteger)aCapacity if (!(self = [super init])) return nil; - RMLog(@"initializing memory cache %@ with capacity %d", self, aCapacity); - _memoryCache = [[NSMutableDictionary alloc] initWithCapacity:aCapacity]; _memoryCacheQueue = dispatch_queue_create("routeme.memoryCacheQueue", DISPATCH_QUEUE_CONCURRENT); @@ -62,10 +60,12 @@ - (void)dealloc { dispatch_barrier_sync(_memoryCacheQueue, ^{ [_memoryCache removeAllObjects]; - [_memoryCache release]; _memoryCache = nil; + _memoryCache = nil; }); - - [super dealloc]; + +#if ! OS_OBJECT_USE_OBJC + dispatch_release(_memoryCacheQueue); +#endif } - (void)didReceiveMemoryWarning @@ -93,7 +93,7 @@ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey dispatch_sync(_memoryCacheQueue, ^{ - cachedObject = [[_memoryCache objectForKey:tileHash] retain]; + cachedObject = [_memoryCache objectForKey:tileHash]; if (cachedObject) { @@ -107,7 +107,7 @@ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey [_memoryCache removeObjectForKey:tileHash]; }); - [cachedObject release]; cachedObject = nil; + cachedObject = nil; } } @@ -115,11 +115,14 @@ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey // RMLog(@"Memory cache hit tile %d %d %d (%@)", tile.x, tile.y, tile.zoom, [RMTileCache tileHash:tile]); - [cachedObject autorelease]; - return [cachedObject cachedObject]; } +- (NSUInteger)capacity +{ + return _memoryCacheCapacity; +} + /// Remove the least-recently used image from cache, if cache is at or over capacity. Removes only 1 image. - (void)makeSpaceInCache { @@ -177,4 +180,20 @@ - (void)removeAllCachedImages }); } +- (void)removeAllCachedImagesForCacheKey:(NSString *)cacheKey +{ + dispatch_barrier_async(_memoryCacheQueue, ^{ + + NSMutableArray *keysToRemove = [NSMutableArray array]; + + [_memoryCache enumerateKeysAndObjectsUsingBlock:^(id key, RMCacheObject *cachedObject, BOOL *stop) { + if ([[cachedObject cacheKey] isEqualToString:cacheKey]) + [keysToRemove addObject:key]; + }]; + + [_memoryCache removeObjectsForKeys:keysToRemove]; + + }); +} + @end diff --git a/MapView/Map/RMNotifications.h b/MapView/Map/RMNotifications.h index c70b3b7ec..b5a585e27 100644 --- a/MapView/Map/RMNotifications.h +++ b/MapView/Map/RMNotifications.h @@ -1,7 +1,7 @@ // // RMNofications.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMOpenCycleMapSource.h b/MapView/Map/RMOpenCycleMapSource.h index c65abc125..9cea8537a 100644 --- a/MapView/Map/RMOpenCycleMapSource.h +++ b/MapView/Map/RMOpenCycleMapSource.h @@ -1,7 +1,7 @@ // // OpenCycleMapSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMOpenCycleMapSource.m b/MapView/Map/RMOpenCycleMapSource.m index fd407f511..fc47b4a3d 100644 --- a/MapView/Map/RMOpenCycleMapSource.m +++ b/MapView/Map/RMOpenCycleMapSource.m @@ -1,7 +1,7 @@ // // OpenCycleMapSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMOpenSeaMapLayer.h b/MapView/Map/RMOpenSeaMapLayer.h index ecd52d38b..ba81d68b6 100644 --- a/MapView/Map/RMOpenSeaMapLayer.h +++ b/MapView/Map/RMOpenSeaMapLayer.h @@ -1,7 +1,7 @@ // // RMOpenSeaMapLayer.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMOpenSeaMapLayer.m b/MapView/Map/RMOpenSeaMapLayer.m index 1e0440cb6..d840e5963 100644 --- a/MapView/Map/RMOpenSeaMapLayer.m +++ b/MapView/Map/RMOpenSeaMapLayer.m @@ -1,7 +1,7 @@ // // RMOpenSeaMapLayer.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -37,6 +37,8 @@ - (id)init self.minZoom = 1; self.maxZoom = 18; + self.opaque = NO; + return self; } diff --git a/MapView/Map/RMOpenSeaMapSource.h b/MapView/Map/RMOpenSeaMapSource.h index e20facdfc..55e845847 100644 --- a/MapView/Map/RMOpenSeaMapSource.h +++ b/MapView/Map/RMOpenSeaMapSource.h @@ -1,7 +1,7 @@ // // RMOpenSeaMapSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMOpenSeaMapSource.m b/MapView/Map/RMOpenSeaMapSource.m index 4788fb9de..6dc068824 100644 --- a/MapView/Map/RMOpenSeaMapSource.m +++ b/MapView/Map/RMOpenSeaMapSource.m @@ -1,7 +1,7 @@ // // RMOpenSeaMapSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMOpenStreetMapSource.h b/MapView/Map/RMOpenStreetMapSource.h index 6682853f1..745044ceb 100644 --- a/MapView/Map/RMOpenStreetMapSource.h +++ b/MapView/Map/RMOpenStreetMapSource.h @@ -1,7 +1,7 @@ // // OpenStreetMapsSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMOpenStreetMapSource.m b/MapView/Map/RMOpenStreetMapSource.m index 3a286207e..efafb85cf 100644 --- a/MapView/Map/RMOpenStreetMapSource.m +++ b/MapView/Map/RMOpenStreetMapSource.m @@ -1,7 +1,7 @@ // // OpenStreetMapsSource.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMPath.h b/MapView/Map/RMPath.h deleted file mode 100644 index ac302627a..000000000 --- a/MapView/Map/RMPath.h +++ /dev/null @@ -1,116 +0,0 @@ -// -// RMPath.h -// -// 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. - -#import - -#import "RMFoundation.h" -#import "RMMapLayer.h" - -@class RMMapView; - -@interface RMPath : RMMapLayer -{ - BOOL isFirstPoint; - - // The color of the line, or the outline if a polygon - UIColor *lineColor; - // The color of polygon's fill. - UIColor *fillColor; - - CGMutablePathRef path; - CGRect pathBoundingBox; - BOOL ignorePathUpdates; - CGRect previousBounds; - - // Width of the line, in pixels - float lineWidth; - - /*! Drawing mode of the path; Choices are - kCGPathFill, - kCGPathEOFill, - kCGPathStroke, - kCGPathFillStroke, - kCGPathEOFillStroke */ - CGPathDrawingMode drawingMode; - - // Line cap and join styles - CGLineCap lineCap; - CGLineJoin lineJoin; - - // Line dash style - CGFloat *_lineDashLengths; - CGFloat *_scaledLineDashLengths; - size_t _lineDashCount; - CGFloat lineDashPhase; - - // Line shadow - CGFloat shadowBlur; - CGSize shadowOffset; - BOOL enableShadow; - - BOOL scaleLineWidth; - BOOL scaleLineDash; // if YES line dashes will be scaled to keep a constant size if the layer is zoomed - - float renderedScale; - RMMapView *mapView; -} - -// DEPRECATED. Use RMShape instead. -- (id)initWithView:(RMMapView *)aMapView __attribute__ ((deprecated));; - -@property (nonatomic, assign) CGPathDrawingMode drawingMode; -@property (nonatomic, assign) CGLineCap lineCap; -@property (nonatomic, assign) CGLineJoin lineJoin; -@property (nonatomic, assign) NSArray *lineDashLengths; -@property (nonatomic, assign) CGFloat lineDashPhase; -@property (nonatomic, assign) BOOL scaleLineDash; -@property (nonatomic, assign) float lineWidth; -@property (nonatomic, assign) BOOL scaleLineWidth; -@property (nonatomic, assign) CGFloat shadowBlur; -@property (nonatomic, assign) CGSize shadowOffset; -@property (nonatomic, assign) BOOL enableShadow; -@property (nonatomic, retain) UIColor *lineColor; -@property (nonatomic, retain) UIColor *fillColor; -@property (nonatomic, readonly) CGRect pathBoundingBox; - -- (void)moveToProjectedPoint:(RMProjectedPoint)projectedPoint; -- (void)moveToScreenPoint:(CGPoint)point; -- (void)moveToCoordinate:(CLLocationCoordinate2D)coordinate; - -- (void)addLineToProjectedPoint:(RMProjectedPoint)projectedPoint; -- (void)addLineToScreenPoint:(CGPoint)point; -- (void)addLineToCoordinate:(CLLocationCoordinate2D)coordinate; - -// Change the path without recalculating the geometry (performance!) -- (void)performBatchOperations:(void (^)(RMPath *aPath))block; - -// This closes the path, connecting the last point to the first. -// After this action, no further points can be added to the path. -// There is no requirement that a path be closed. -- (void)closePath; - -@end diff --git a/MapView/Map/RMPath.m b/MapView/Map/RMPath.m deleted file mode 100644 index 92d352d67..000000000 --- a/MapView/Map/RMPath.m +++ /dev/null @@ -1,433 +0,0 @@ -// -// RMPath.m -// -// 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. - -#import "RMPath.h" -#import "RMPixel.h" -#import "RMProjection.h" -#import "RMMapView.h" -#import "RMAnnotation.h" - -@implementation RMPath - -@synthesize scaleLineWidth; -@synthesize lineDashPhase; -@synthesize scaleLineDash; -@synthesize shadowBlur; -@synthesize shadowOffset; -@synthesize enableShadow; -@synthesize pathBoundingBox; - -#define kDefaultLineWidth 2.0 - -- (id)initWithView:(RMMapView *)aMapView -{ - if (!(self = [super init])) - return nil; - - mapView = aMapView; - - path = CGPathCreateMutable(); - pathBoundingBox = CGRectZero; - ignorePathUpdates = NO; - previousBounds = CGRectZero; - - lineWidth = kDefaultLineWidth; - drawingMode = kCGPathFillStroke; - lineCap = kCGLineCapButt; - lineJoin = kCGLineJoinMiter; - lineColor = [UIColor blackColor]; - fillColor = [UIColor redColor]; - - _lineDashCount = 0; - _lineDashLengths = NULL; - _scaledLineDashLengths = NULL; - lineDashPhase = 0.0; - - self.shadowBlur = 0.0; - self.shadowOffset = CGSizeMake(0, 0); - self.enableShadow = NO; - - self.masksToBounds = YES; - - scaleLineWidth = NO; - scaleLineDash = NO; - isFirstPoint = YES; - - if ([self respondsToSelector:@selector(setContentsScale:)]) - [(id)self setValue:[[UIScreen mainScreen] valueForKey:@"scale"] forKey:@"contentsScale"]; - - return self; -} - -- (void)dealloc -{ - mapView = nil; - CGPathRelease(path); path = NULL; - [self setLineDashLengths:nil]; - [lineColor release]; lineColor = nil; - [fillColor release]; fillColor = nil; - [super dealloc]; -} - -//- (id )actionForKey:(NSString *)key -//{ -// return nil; -//} - -#pragma mark - - -- (void)recalculateGeometry -{ - if (ignorePathUpdates) - return; - - CGPoint myPosition = self.annotation.position; - - float scale = [mapView metersPerPixel]; - float scaledLineWidth; - CGRect pixelBounds, screenBounds; - float offset; - const float outset = 100.0f; // provides a buffer off screen edges for when path is scaled or moved - - // The bounds are actually in mercators... - /// \bug if "bounds are actually in mercators", shouldn't be using a CGRect - scaledLineWidth = lineWidth; - - if (!scaleLineWidth) - { - renderedScale = [mapView metersPerPixel]; - scaledLineWidth *= renderedScale; - } - - CGRect boundsInMercators = CGPathGetBoundingBox(path); - boundsInMercators = CGRectInset(boundsInMercators, -scaledLineWidth, -scaledLineWidth); - pixelBounds = CGRectInset(boundsInMercators, -scaledLineWidth, -scaledLineWidth); - pixelBounds = RMScaleCGRectAboutPoint(pixelBounds, 1.0f / scale, CGPointZero); - - // Clip bound rect to screen bounds. - // If bounds are not clipped, they won't display when you zoom in too much. - screenBounds = [mapView frame]; - - // Clip top - offset = myPosition.y + pixelBounds.origin.y - screenBounds.origin.y + outset; - if (offset < 0.0f) - { - pixelBounds.origin.y -= offset; - pixelBounds.size.height += offset; - } - - // Clip left - offset = myPosition.x + pixelBounds.origin.x - screenBounds.origin.x + outset; - if (offset < 0.0f) - { - pixelBounds.origin.x -= offset; - pixelBounds.size.width += offset; - } - - // Clip bottom - offset = myPosition.y + pixelBounds.origin.y + pixelBounds.size.height - screenBounds.origin.y - screenBounds.size.height - outset; - if (offset > 0.0f) - { - pixelBounds.size.height -= offset; - } - - // Clip right - offset = myPosition.x + pixelBounds.origin.x + pixelBounds.size.width - screenBounds.origin.x - screenBounds.size.width - outset; - if (offset > 0.0f) - { - pixelBounds.size.width -= offset; - } - - [super setPosition:myPosition]; - self.bounds = pixelBounds; - previousBounds = pixelBounds; - -// RMLog(@"x:%f y:%f screen bounds: %f %f %f %f", myPosition.x, myPosition.y, screenBounds.origin.x, screenBounds.origin.y, screenBounds.size.width, screenBounds.size.height); -// RMLog(@"new bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height); - - pathBoundingBox = CGRectMake(myPosition.x + self.bounds.origin.x, myPosition.y + self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height); - self.anchorPoint = CGPointMake(-pixelBounds.origin.x / pixelBounds.size.width, -pixelBounds.origin.y / pixelBounds.size.height); - - [self setNeedsDisplay]; -} - -- (void)drawInContext:(CGContextRef)theContext -{ - renderedScale = [mapView metersPerPixel]; - CGFloat *dashLengths = _lineDashLengths; - - float scale = 1.0f / [mapView metersPerPixel]; - - float scaledLineWidth = lineWidth; - if (!scaleLineWidth) - scaledLineWidth *= renderedScale; - - // NSLog(@"line width = %f, content scale = %f", scaledLineWidth, renderedScale); - - if (!scaleLineDash && _lineDashLengths) - { - dashLengths = _scaledLineDashLengths; - - for (size_t dashIndex=0; dashIndex<_lineDashCount; dashIndex++) - dashLengths[dashIndex] = _lineDashLengths[dashIndex] * renderedScale; - } - - CGContextScaleCTM(theContext, scale, scale); - - CGContextBeginPath(theContext); - CGContextAddPath(theContext, path); - - CGContextSetLineWidth(theContext, scaledLineWidth); - CGContextSetLineCap(theContext, lineCap); - CGContextSetLineJoin(theContext, lineJoin); - CGContextSetStrokeColorWithColor(theContext, [lineColor CGColor]); - CGContextSetFillColorWithColor(theContext, [fillColor CGColor]); - - if (_lineDashLengths) - CGContextSetLineDash(theContext, lineDashPhase, dashLengths, _lineDashCount); - - if (self.enableShadow) - CGContextSetShadow(theContext, self.shadowOffset, self.shadowBlur); - - // according to Apple's documentation, DrawPath closes the path if it's a filled style, so a call to ClosePath isn't necessary - CGContextDrawPath(theContext, drawingMode); -} - -#pragma mark - - -- (void)addPointToProjectedPoint:(RMProjectedPoint)point withDrawing:(BOOL)isDrawing -{ - // RMLog(@"addLineToXY %f %f", point.x, point.y); - - if (isFirstPoint) - { - isFirstPoint = FALSE; - projectedLocation = point; - - self.position = [mapView projectedPointToPixel:projectedLocation]; - // RMLog(@"screen position set to %f %f", self.position.x, self.position.y); - CGPathMoveToPoint(path, NULL, 0.0f, 0.0f); - } - else - { - point.x = point.x - projectedLocation.x; - point.y = point.y - projectedLocation.y; - - if (isDrawing) - CGPathAddLineToPoint(path, NULL, point.x, -point.y); - else - CGPathMoveToPoint(path, NULL, point.x, -point.y); - - [self recalculateGeometry]; - } - - [self setNeedsDisplay]; -} - -- (void)moveToProjectedPoint:(RMProjectedPoint)projectedPoint -{ - [self addPointToProjectedPoint:projectedPoint withDrawing:NO]; -} - -- (void)moveToScreenPoint:(CGPoint)point -{ - RMProjectedPoint mercator = [mapView pixelToProjectedPoint:point]; - [self moveToProjectedPoint:mercator]; -} - -- (void)moveToCoordinate:(CLLocationCoordinate2D)coordinate -{ - RMProjectedPoint mercator = [[mapView projection] coordinateToProjectedPoint:coordinate]; - [self moveToProjectedPoint:mercator]; -} - -- (void)addLineToProjectedPoint:(RMProjectedPoint)projectedPoint -{ - [self addPointToProjectedPoint:projectedPoint withDrawing:YES]; -} - -- (void)addLineToScreenPoint:(CGPoint)point -{ - RMProjectedPoint mercator = [mapView pixelToProjectedPoint:point]; - [self addLineToProjectedPoint:mercator]; -} - -- (void)addLineToCoordinate:(CLLocationCoordinate2D)coordinate -{ - RMProjectedPoint mercator = [[mapView projection] coordinateToProjectedPoint:coordinate]; - [self addLineToProjectedPoint:mercator]; -} - -- (void)performBatchOperations:(void (^)(RMPath *aPath))block -{ - ignorePathUpdates = YES; - block(self); - ignorePathUpdates = NO; - - [self recalculateGeometry]; -} - -#pragma mark - Accessors - -- (void)closePath -{ - CGPathCloseSubpath(path); -} - -- (float)lineWidth -{ - return lineWidth; -} - -- (void)setLineWidth:(float)newLineWidth -{ - lineWidth = newLineWidth; - [self recalculateGeometry]; -} - -- (CGPathDrawingMode)drawingMode -{ - return drawingMode; -} - -- (void)setDrawingMode:(CGPathDrawingMode)newDrawingMode -{ - drawingMode = newDrawingMode; - [self setNeedsDisplay]; -} - -- (CGLineCap)lineCap -{ - return lineCap; -} - -- (void)setLineCap:(CGLineCap)newLineCap -{ - lineCap = newLineCap; - [self setNeedsDisplay]; -} - -- (CGLineJoin)lineJoin -{ - return lineJoin; -} - -- (void)setLineJoin:(CGLineJoin)newLineJoin -{ - lineJoin = newLineJoin; - [self setNeedsDisplay]; -} - -- (UIColor *)lineColor -{ - return lineColor; -} - -- (void)setLineColor:(UIColor *)aLineColor -{ - if (lineColor != aLineColor) - { - [lineColor release]; - lineColor = [aLineColor retain]; - [self setNeedsDisplay]; - } -} - -- (UIColor *)fillColor -{ - return fillColor; -} - -- (void)setFillColor:(UIColor *)aFillColor -{ - if (fillColor != aFillColor) - { - [fillColor release]; - fillColor = [aFillColor retain]; - [self setNeedsDisplay]; - } -} - -- (NSArray *)lineDashLengths -{ - NSMutableArray *lengths = [NSMutableArray arrayWithCapacity:_lineDashCount]; - - for (size_t dashIndex=0; dashIndex<_lineDashCount; dashIndex++) - [lengths addObject:(id)[NSNumber numberWithFloat:_lineDashLengths[dashIndex]]]; - - return lengths; -} - -- (void)setLineDashLengths:(NSArray *)lengths -{ - if (_lineDashLengths) - { - free(_lineDashLengths); - _lineDashLengths = NULL; - } - - if (_scaledLineDashLengths) - { - free(_scaledLineDashLengths); - _scaledLineDashLengths = NULL; - } - - _lineDashCount = [lengths count]; - - if (!_lineDashCount) - return; - - _lineDashLengths = calloc(_lineDashCount, sizeof(CGFloat)); - if (!scaleLineDash) - _scaledLineDashLengths = calloc(_lineDashCount, sizeof(CGFloat)); - - NSEnumerator *lengthEnumerator = [lengths objectEnumerator]; - id lenObj; - size_t dashIndex = 0; - - while ((lenObj = [lengthEnumerator nextObject])) - { - if ([lenObj isKindOfClass:[NSNumber class]]) - { - _lineDashLengths[dashIndex] = [lenObj floatValue]; - } - else - { - _lineDashLengths[dashIndex] = 0.0; - dashIndex++; - } - } -} - -- (void)setPosition:(CGPoint)newPosition animated:(BOOL)animated -{ - if (CGPointEqualToPoint(newPosition, super.position) && CGRectEqualToRect(self.bounds, previousBounds)) return; - - [self recalculateGeometry]; -} - -@end diff --git a/MapView/Map/RMPixel.c b/MapView/Map/RMPixel.c index 659b4fb45..762d473ac 100644 --- a/MapView/Map/RMPixel.c +++ b/MapView/Map/RMPixel.c @@ -1,7 +1,7 @@ // // RMPixel.c // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMPixel.h b/MapView/Map/RMPixel.h index bbaf94fdd..0d6285060 100644 --- a/MapView/Map/RMPixel.h +++ b/MapView/Map/RMPixel.h @@ -1,7 +1,7 @@ // // RMPixel.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMPointAnnotation.h b/MapView/Map/RMPointAnnotation.h new file mode 100644 index 000000000..7993db9f3 --- /dev/null +++ b/MapView/Map/RMPointAnnotation.h @@ -0,0 +1,39 @@ +// +// RMPointAnnotation.h +// MapView +// +// 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. + +#import "RMAnnotation.h" + +/** An RMPointAnnotation is used to represent a single point on a map. The annotation will automatically have a layer created when needed that displays an RMMarker with either a default point icon or the supplied image. +* +* If you wish to customize the layer appearance in more detail, you should instead create an RMAnnotation and configure its layer directly. Providing a layer manually for instances of RMPointAnnotation will not have any effect. */ +@interface RMPointAnnotation : RMAnnotation + +/** An image for the annotation's point. */ +@property (nonatomic, strong) UIImage *image; + +@end diff --git a/MapView/UnitTesting/RMFoundationTests.m b/MapView/Map/RMPointAnnotation.m similarity index 60% rename from MapView/UnitTesting/RMFoundationTests.m rename to MapView/Map/RMPointAnnotation.m index ee550f60d..c92d8891c 100644 --- a/MapView/UnitTesting/RMFoundationTests.m +++ b/MapView/Map/RMPointAnnotation.m @@ -1,8 +1,8 @@ // -// RMFoundationTests.m +// RMPointAnnotation.m // MapView -// -// Copyright (c) 2008-2011, Route-Me Contributors +// +// Copyright (c) 2008-2012, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -26,22 +26,43 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -#import "RMFoundationTests.h" - -@implementation RMFoundationTests - -- (void)testProjectedRectIntersectsProjectedRect { - RMProjectedRect r0022 = RMMakeProjectedRect(0.0, 0.0, 2.0, 2.0); - RMProjectedRect r0123 = RMMakeProjectedRect(0.0, 1.0, 2.0, 2.0); - RMProjectedRect r0325 = RMMakeProjectedRect(0.0, 3.0, 2.0, 2.0); - RMProjectedRect r1032 = RMMakeProjectedRect(1.0, 0.0, 2.0, 2.0); - - STAssertTrue(RMProjectedRectInterectsProjectedRect(r0123, r1032), nil); - STAssertTrue(RMProjectedRectInterectsProjectedRect(r1032, r0123), nil); - STAssertFalse(RMProjectedRectInterectsProjectedRect(r0022, r0325), nil); - STAssertFalse(RMProjectedRectInterectsProjectedRect(r0325, r0022), nil); - STAssertTrue(RMProjectedRectInterectsProjectedRect(r0022, r0123), nil); - STAssertTrue(RMProjectedRectInterectsProjectedRect(r0123, r0022), nil); +#import "RMPointAnnotation.h" + +#import "RMMarker.h" +#import "RMMapView.h" + +@implementation RMPointAnnotation + +- (void)setLayer:(RMMapLayer *)newLayer +{ + if ( ! newLayer) + [super setLayer:nil]; + else + RMLog(@"Setting a custom layer on an %@ is a no-op", [self class]); +} + +- (RMMapLayer *)layer +{ + if ( ! [super layer]) + { + RMMarker *marker = [[RMMarker alloc] initWithMapboxMarkerImage:nil tintColor:(RMPostVersion7 ? self.mapView.tintColor : nil)]; + + marker.canShowCallout = YES; + + super.layer = marker; + } + + return [super layer]; +} + +- (void)setImage:(UIImage *)image +{ + [(RMMarker *)[self layer] replaceUIImage:image]; +} + +- (UIImage *)image +{ + return [UIImage imageWithCGImage:(CGImageRef)[self layer].contents]; } @end diff --git a/MapView/Map/RMPolygonAnnotation.h b/MapView/Map/RMPolygonAnnotation.h new file mode 100644 index 000000000..6981caac7 --- /dev/null +++ b/MapView/Map/RMPolygonAnnotation.h @@ -0,0 +1,50 @@ +// +// RMPolygonAnnotation.h +// MapView +// +// 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. + +#import "RMShapeAnnotation.h" + +/** An RMPolygonAnnotation is a concrete subclass of RMShapeAnnotation that is used to represent a shape consisting of one or more points that define a closed polygon. The points are connected end-to-end in the order they are provided. The first and last points are connected to each other to create the closed shape. The annotation will automatically have a layer created when needed that displays an RMShape. +* +* When creating a polygon, you can mask out portions of the polygon by specifying one or more interior polygons. Areas that are masked by an interior polygon are not considered part of the polygon’s occupied area. +* +* If you wish to customize the layer appearance in more detail, you should instead create an RMAnnotation and configure its layer directly. Providing a layer manually for instances of RMPolygonAnnotation will not have any effect. */ +@interface RMPolygonAnnotation : RMShapeAnnotation + +/** Initialize a polygon annotation. +* @param aMapView The map view on which to place the annotation. +* @param points An array of CLLocation points defining the polygon. The data in this array is copied to the new object. +* @param interiorPolygons An array of RMPolygonAnnotation objects that define one or more cutout regions for the receiver’s polygon. +* @return An initialized polygon annotation object, or `nil` if an annotation was unable to be initialized. */ +- (id)initWithMapView:(RMMapView *)aMapView points:(NSArray *)points interiorPolygons:(NSArray *)interiorPolygons; + +/** The array of polygons nested inside the receiver. (read-only) +* +* When a polygon is rendered on screen, the area occupied by any interior polygons is masked out and not considered part of the polygon. */ +@property (nonatomic, readonly, strong) NSArray *interiorPolygons; + +@end diff --git a/MapView/Map/RMPolygonAnnotation.m b/MapView/Map/RMPolygonAnnotation.m new file mode 100644 index 000000000..48c9cebbd --- /dev/null +++ b/MapView/Map/RMPolygonAnnotation.m @@ -0,0 +1,98 @@ +// +// RMPolygonAnnotation.m +// MapView +// +// 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. + +#import "RMPolygonAnnotation.h" + +#import "RMShape.h" + +@implementation RMPolygonAnnotation + +@synthesize interiorPolygons=_interiorPolygons; + +- (id)initWithMapView:(RMMapView *)aMapView points:(NSArray *)points +{ + return [self initWithMapView:aMapView points:points interiorPolygons:nil]; +} + +- (id)initWithMapView:(RMMapView *)aMapView points:(NSArray *)points interiorPolygons:(NSArray *)interiorPolygons +{ + if (!(self = [super initWithMapView:aMapView points:points])) + return nil; + + _interiorPolygons = interiorPolygons; + + return self; +} + +- (void)setLayer:(RMMapLayer *)newLayer +{ + if ( ! newLayer) + [super setLayer:nil]; + else + RMLog(@"Setting a custom layer on an %@ is a no-op", [self class]); +} + +- (RMMapLayer *)layer +{ + if ( ! [super layer]) + { + RMShape *shape = [[RMShape alloc] initWithView:self.mapView]; + + [shape performBatchOperations:^(RMShape *aShape) + { + [aShape moveToCoordinate:self.coordinate]; + + for (CLLocation *point in self.points) + [aShape addLineToCoordinate:point.coordinate]; + + [aShape closePath]; + + if (self.interiorPolygons) + { + for (RMPolygonAnnotation *interiorPolygon in self.interiorPolygons) + { + [aShape moveToCoordinate:interiorPolygon.coordinate]; + + for (CLLocation *point in interiorPolygon.points) + [aShape addLineToCoordinate:point.coordinate]; + + [aShape addLineToCoordinate:interiorPolygon.coordinate]; + } + + aShape.fillColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.2]; + aShape.fillRule = kCAFillRuleEvenOdd; + } + }]; + + super.layer = shape; + } + + return [super layer]; +} + +@end diff --git a/MapView/Map/RMPolylineAnnotation.h b/MapView/Map/RMPolylineAnnotation.h new file mode 100644 index 000000000..95a7fbf52 --- /dev/null +++ b/MapView/Map/RMPolylineAnnotation.h @@ -0,0 +1,36 @@ +// +// RMPolylineAnnotation.h +// MapView +// +// 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. + +#import "RMShapeAnnotation.h" + +/** An RMPolylineAnnotation is a concrete subclass of RMShapeAnnotation that is used to represent a shape consisting of one or more points that define connecting line segments. The points are connected end-to-end in the order they are provided. The first and last points are not connected to each other. The annotation will automatically have a layer created when needed that displays an RMShape. +* +* If you wish to customize the layer appearance in more detail, you should instead create an RMAnnotation and configure its layer directly. Providing a layer manually for instances of RMPolylineAnnotation will not have any effect. */ +@interface RMPolylineAnnotation : RMShapeAnnotation + +@end diff --git a/MapView/Map/RMPolylineAnnotation.m b/MapView/Map/RMPolylineAnnotation.m new file mode 100644 index 000000000..40c7c1587 --- /dev/null +++ b/MapView/Map/RMPolylineAnnotation.m @@ -0,0 +1,63 @@ +// +// RMPolylineAnnotation.m +// MapView +// +// 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. + +#import "RMPolylineAnnotation.h" + +#import "RMShape.h" + +@implementation RMPolylineAnnotation + +- (void)setLayer:(RMMapLayer *)newLayer +{ + if ( ! newLayer) + [super setLayer:nil]; + else + RMLog(@"Setting a custom layer on an %@ is a no-op", [self class]); +} + +- (RMMapLayer *)layer +{ + if ( ! [super layer]) + { + RMShape *shape = [[RMShape alloc] initWithView:self.mapView]; + + [shape performBatchOperations:^(RMShape *aShape) + { + [aShape moveToCoordinate:self.coordinate]; + + for (CLLocation *point in self.points) + [aShape addLineToCoordinate:point.coordinate]; + }]; + + super.layer = shape; + } + + return [super layer]; +} + +@end diff --git a/MapView/Map/RMProjection.h b/MapView/Map/RMProjection.h index 730405739..fa4eb0ae8 100644 --- a/MapView/Map/RMProjection.h +++ b/MapView/Map/RMProjection.h @@ -1,7 +1,7 @@ // // RMProjection.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -43,8 +43,8 @@ // applies #wrapPointHorizontally to aPoint, and then clamps northing (Y coordinate) to projection's planetBounds - (RMProjectedPoint)constrainPointToBounds:(RMProjectedPoint)aPoint; -+ (RMProjection *)googleProjection; -+ (RMProjection *)EPSGLatLong; ++ (instancetype)googleProjection; ++ (instancetype)EPSGLatLong; - (id)initWithString:(NSString *)proj4String inBounds:(RMProjectedRect)projectedBounds; diff --git a/MapView/Map/RMProjection.m b/MapView/Map/RMProjection.m index d3287690e..68cbc9d6c 100644 --- a/MapView/Map/RMProjection.m +++ b/MapView/Map/RMProjection.m @@ -1,7 +1,7 @@ // // RMProjection.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -50,7 +50,7 @@ @implementation RMProjection static RMProjection *_googleProjection = nil; static RMProjection *_latitudeLongitudeProjection = nil; -+ (RMProjection *)googleProjection ++ (instancetype)googleProjection { if (_googleProjection) { @@ -66,7 +66,7 @@ + (RMProjection *)googleProjection } } -+ (RMProjection *)EPSGLatLong ++ (instancetype)EPSGLatLong { if (_latitudeLongitudeProjection) { @@ -94,7 +94,6 @@ - (id)initWithString:(NSString *)proj4String inBounds:(RMProjectedRect)projected if (_internalProjection == NULL) { RMLog(@"Unhandled error creating projection. String is %@", proj4String); - [self release]; return nil; } @@ -121,8 +120,6 @@ - (void)dealloc { if (_internalProjection) pj_free(_internalProjection); - - [super dealloc]; } - (RMProjectedPoint)wrapPointHorizontally:(RMProjectedPoint)aPoint diff --git a/MapView/Map/RMQuadTree.h b/MapView/Map/RMQuadTree.h index 4bf63f088..899212ecf 100644 --- a/MapView/Map/RMQuadTree.h +++ b/MapView/Map/RMQuadTree.h @@ -2,7 +2,7 @@ // RMQuadTree.h // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -35,13 +35,11 @@ typedef enum : short { nodeTypeNode } RMQuadTreeNodeType; -#define kRMClusterAnnotationTypeName @"RMClusterAnnotation" - #pragma mark - RMQuadTree nodes @interface RMQuadTreeNode : NSObject -@property (nonatomic, readonly) NSArray *annotations; +@property (nonatomic, weak, readonly) NSArray *annotations; @property (nonatomic, readonly) RMQuadTreeNodeType nodeType; @property (nonatomic, readonly) RMProjectedRect boundingBox; @@ -50,18 +48,18 @@ typedef enum : short { @property (nonatomic, readonly) RMProjectedRect southWestBoundingBox; @property (nonatomic, readonly) RMProjectedRect southEastBoundingBox; -@property (nonatomic, readonly) RMQuadTreeNode *parentNode; +@property (nonatomic, weak, readonly) RMQuadTreeNode *parentNode; @property (nonatomic, readonly) RMQuadTreeNode *northWest; @property (nonatomic, readonly) RMQuadTreeNode *northEast; @property (nonatomic, readonly) RMQuadTreeNode *southWest; @property (nonatomic, readonly) RMQuadTreeNode *southEast; -@property (nonatomic, readonly) RMAnnotation *clusterAnnotation; -@property (nonatomic, readonly) NSArray *clusteredAnnotations; +@property (nonatomic, weak, readonly) RMAnnotation *clusterAnnotation; +@property (nonatomic, weak, readonly) NSArray *clusteredAnnotations; // Operations on this node and all subnodes -@property (nonatomic, readonly) NSArray *enclosedAnnotations; -@property (nonatomic, readonly) NSArray *unclusteredAnnotations; +@property (nonatomic, weak, readonly) NSArray *enclosedAnnotations; +@property (nonatomic, weak, readonly) NSArray *unclusteredAnnotations; @end diff --git a/MapView/Map/RMQuadTree.m b/MapView/Map/RMQuadTree.m index da9bdea6d..1aa3a1585 100644 --- a/MapView/Map/RMQuadTree.m +++ b/MapView/Map/RMQuadTree.m @@ -2,7 +2,7 @@ // RMQuadTree.m // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -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; @@ -62,9 +68,10 @@ @implementation RMQuadTreeNode { RMProjectedRect _boundingBox, _northWestBoundingBox, _northEastBoundingBox, _southWestBoundingBox, _southEastBoundingBox; NSMutableArray *_annotations; - RMQuadTreeNode *_parentNode, *_northWest, *_northEast, *_southWest, *_southEast; + __weak RMQuadTreeNode *_parentNode; + RMQuadTreeNode *_northWest, *_northEast, *_southWest, *_southEast; RMQuadTreeNodeType _nodeType; - RMMapView *_mapView; + __weak RMMapView *_mapView; RMAnnotation *_cachedClusterAnnotation; NSArray *_cachedClusterEnclosedAnnotations; @@ -87,7 +94,7 @@ - (id)initWithMapView:(RMMapView *)aMapView forParent:(RMQuadTreeNode *)aParentN // RMLog(@"New quadtree node at {(%.0f,%.0f),(%.0f,%.0f)}", aBoundingBox.origin.easting, aBoundingBox.origin.northing, aBoundingBox.size.width, aBoundingBox.size.height); _mapView = aMapView; - _parentNode = [aParentNode retain]; + _parentNode = aParentNode; _northWest = _northEast = _southWest = _southEast = nil; _annotations = [NSMutableArray new]; _boundingBox = aBoundingBox; @@ -112,8 +119,8 @@ - (void)dealloc @synchronized (_cachedClusterAnnotation) { - [_cachedClusterEnclosedAnnotations release]; _cachedClusterEnclosedAnnotations = nil; - [_cachedClusterAnnotation release]; _cachedClusterAnnotation = nil; + _cachedClusterEnclosedAnnotations = nil; + _cachedClusterAnnotation = nil; } @synchronized (_annotations) @@ -123,18 +130,6 @@ - (void)dealloc annotation.quadTreeNode = nil; } } - - [_annotations release]; _annotations = nil; - [_cachedEnclosedAnnotations release]; _cachedEnclosedAnnotations = nil; - [_cachedUnclusteredAnnotations release]; _cachedUnclusteredAnnotations = nil; - - [_northWest release]; _northWest = nil; - [_northEast release]; _northEast = nil; - [_southWest release]; _southWest = nil; - [_southEast release]; _southEast = nil; - [_parentNode release]; _parentNode = nil; - - [super dealloc]; } - (NSArray *)annotations @@ -202,8 +197,8 @@ - (void)precreateQuadTreeInBounds:(RMProjectedRect)quadTreeBounds withDepth:(NSU @synchronized (_cachedClusterAnnotation) { - [_cachedClusterEnclosedAnnotations release]; _cachedClusterEnclosedAnnotations = nil; - [_cachedClusterAnnotation release]; _cachedClusterAnnotation = nil; + _cachedClusterEnclosedAnnotations = nil; + _cachedClusterAnnotation = nil; } if (RMProjectedRectIntersectsProjectedRect(quadTreeBounds, _northWestBoundingBox)) @@ -318,8 +313,6 @@ - (void)annotationDidChangeBoundingBox:(RMAnnotation *)annotation if (RMProjectedRectContainsProjectedRect(_boundingBox, annotation.projectedBoundingBox)) return; - [annotation retain]; - [self removeAnnotation:annotation]; RMQuadTreeNode *nextParentNode = self; @@ -332,8 +325,6 @@ - (void)annotationDidChangeBoundingBox:(RMAnnotation *)annotation break; } } - - [annotation release]; } - (NSArray *)enclosedAnnotations @@ -453,8 +444,8 @@ - (void)addAnnotationsInBoundingBox:(RMProjectedRect)aBoundingBox { @synchronized (_cachedClusterAnnotation) { - [_cachedClusterEnclosedAnnotations release]; _cachedClusterEnclosedAnnotations = nil; - [_cachedClusterAnnotation release]; _cachedClusterAnnotation = nil; + _cachedClusterEnclosedAnnotations = nil; + _cachedClusterAnnotation = nil; } enclosedAnnotations = [NSArray arrayWithArray:annotationsToCheck]; @@ -470,8 +461,8 @@ - (void)addAnnotationsInBoundingBox:(RMProjectedRect)aBoundingBox { if (_cachedClusterAnnotation && [enclosedAnnotations count] != [_cachedClusterEnclosedAnnotations count]) { - [_cachedClusterEnclosedAnnotations release]; _cachedClusterEnclosedAnnotations = nil; - [_cachedClusterAnnotation release]; _cachedClusterAnnotation = nil; + _cachedClusterEnclosedAnnotations = nil; + _cachedClusterAnnotation = nil; } } @@ -529,8 +520,8 @@ - (void)addAnnotationsInBoundingBox:(RMProjectedRect)aBoundingBox _cachedClusterAnnotation = [[RMAnnotation alloc] initWithMapView:_mapView coordinate:clusterMarkerCoordinate - andTitle:[NSString stringWithFormat:@"%d", enclosedAnnotationsCount]]; - _cachedClusterAnnotation.annotationType = kRMClusterAnnotationTypeName; + andTitle:[NSString stringWithFormat:@"%lu", (unsigned long)enclosedAnnotationsCount]]; + _cachedClusterAnnotation.isClusterAnnotation = YES; _cachedClusterAnnotation.userInfo = self; _cachedClusterEnclosedAnnotations = [[NSArray alloc] initWithArray:enclosedAnnotations]; @@ -591,12 +582,12 @@ - (void)removeUpwardsAllCachedClusterAnnotations @synchronized (_cachedClusterAnnotation) { - [_cachedClusterEnclosedAnnotations release]; _cachedClusterEnclosedAnnotations = nil; - [_cachedClusterAnnotation release]; _cachedClusterAnnotation = nil; + _cachedClusterEnclosedAnnotations = nil; + _cachedClusterAnnotation = nil; } - [_cachedEnclosedAnnotations release]; _cachedEnclosedAnnotations = nil; - [_cachedUnclusteredAnnotations release]; _cachedUnclusteredAnnotations = nil; + _cachedEnclosedAnnotations = nil; + _cachedUnclusteredAnnotations = nil; } @end @@ -606,7 +597,7 @@ - (void)removeUpwardsAllCachedClusterAnnotations @implementation RMQuadTree { RMQuadTreeNode *_rootNode; - RMMapView *_mapView; + __weak RMMapView *_mapView; } - (id)initWithMapView:(RMMapView *)aMapView @@ -620,18 +611,12 @@ - (id)initWithMapView:(RMMapView *)aMapView return self; } -- (void)dealloc -{ - _mapView = nil; - [_rootNode release]; _rootNode = nil; - [super dealloc]; -} - - (void)addAnnotation:(RMAnnotation *)annotation { @synchronized (self) { - [_rootNode addAnnotation:annotation]; + if ( ! [_rootNode.annotations containsObject:annotation]) + [_rootNode addAnnotation:annotation]; } } @@ -643,9 +628,8 @@ - (void)addAnnotations:(NSArray *)annotations @synchronized (self) { for (RMAnnotation *annotation in annotations) - { - [_rootNode addAnnotation:annotation]; - } + if ( ! [_rootNode.annotations containsObject:annotation]) + [_rootNode addAnnotation:annotation]; } } @@ -661,7 +645,6 @@ - (void)removeAllObjects { @synchronized (self) { - [_rootNode release]; _rootNode = [[RMQuadTreeNode alloc] initWithMapView:_mapView forParent:nil inBoundingBox:[[RMProjection googleProjection] planetBounds]]; } } diff --git a/MapView/Map/RMShape.h b/MapView/Map/RMShape.h index 8d411482e..a525768bb 100644 --- a/MapView/Map/RMShape.h +++ b/MapView/Map/RMShape.h @@ -1,7 +1,7 @@ // // RMShape.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ @class RMMapView; +/** An RMShape object is used to represent a line, polygon, or other shape composed of two or more points connected by lines. An RMShape object changes visible size in response to map zooms in order to consistently represent coverage of the same geographic area. */ @interface RMShape : RMMapLayer { CGRect pathBoundingBox; @@ -40,46 +41,107 @@ float lineWidth; // Line dash style - NSArray *lineDashLengths; + __weak NSArray *lineDashLengths; CGFloat lineDashPhase; BOOL scaleLineWidth; BOOL scaleLineDash; // if YES line dashes will be scaled to keep a constant size if the layer is zoomed } +/** @name Creating Shape Objects */ + +/** Initializes and returns a newly allocated shape object for the specified map view. +* @param aMapView The map view the shape should be drawn on. */ - (id)initWithView:(RMMapView *)aMapView; -@property (nonatomic, retain) NSString *fillRule; -@property (nonatomic, retain) NSString *lineCap; -@property (nonatomic, retain) NSString *lineJoin; -@property (nonatomic, retain) UIColor *lineColor; -@property (nonatomic, retain) UIColor *fillColor; +/** @name Accessing the Drawing Properties */ + +@property (nonatomic, strong) NSString *fillRule; +@property (nonatomic, strong) NSString *lineCap; +@property (nonatomic, strong) NSString *lineJoin; + +/** The line color of the shape. Defaults to black. */ +@property (nonatomic, strong) UIColor *lineColor; + +/** The fill color of the shape. Defaults to clear. */ +@property (nonatomic, strong) UIColor *fillColor; -@property (nonatomic, assign) NSArray *lineDashLengths; +/** The fill pattern image of the shape. If set, the fillColor is set to `nil`. */ +@property (nonatomic, strong) UIImage *fillPatternImage; + +@property (nonatomic, weak) NSArray *lineDashLengths; @property (nonatomic, assign) CGFloat lineDashPhase; @property (nonatomic, assign) BOOL scaleLineDash; + +/** The line width of the shape. Defaults to 2.0. */ @property (nonatomic, assign) float lineWidth; + @property (nonatomic, assign) BOOL scaleLineWidth; @property (nonatomic, assign) CGFloat shadowBlur; @property (nonatomic, assign) CGSize shadowOffset; @property (nonatomic, assign) BOOL enableShadow; +/** The bounding box of the shape in the current viewport. */ @property (nonatomic, readonly) CGRect pathBoundingBox; +/** An additional pixel area around the shape that is applied to touch hit testing events. Defaults to none. */ +@property (nonatomic, assign) CGFloat additionalTouchPadding; + +/** @name Drawing Shapes */ + +/** Move the drawing pen to a projected point. +* @param projectedPoint The projected point to move to. */ - (void)moveToProjectedPoint:(RMProjectedPoint)projectedPoint; + +/** Move the drawing pen to a screen point. +* @param point The screen point to move to. */ - (void)moveToScreenPoint:(CGPoint)point; + +/** Move the drawing pen to a coordinate. +* @param coordinate The coordinate to move to. */ - (void)moveToCoordinate:(CLLocationCoordinate2D)coordinate; +/** Draw a line from the current pen location to a projected point. +* @param projectedPoint The projected point to draw to. */ - (void)addLineToProjectedPoint:(RMProjectedPoint)projectedPoint; + +/** Draw a line from the current pen location to a screen point. +* @param point The screen point to draw to. */ - (void)addLineToScreenPoint:(CGPoint)point; -- (void)addLineToCoordinate:(CLLocationCoordinate2D)coordinate; -// Change the path without recalculating the geometry (performance!) -- (void)performBatchOperations:(void (^)(RMShape *aPath))block; +/** Draw a line from the current pen location to a coordinate. +* @param coordinate The coordinate to draw to. */ +- (void)addLineToCoordinate:(CLLocationCoordinate2D)coordinate; -// This closes the path, connecting the last point to the first. -// After this action, no further points can be added to the path. -// There is no requirement that a path be closed. +/** Draw a curve from the current pen location to a coordinate. +* @param coordinate The coordinate to draw to. +* @param controlCoordinate1 The first control coordinate. +* @param controlCoordinate2 The second control coordinate. */ +- (void)addCurveToCoordinate:(CLLocationCoordinate2D)coordinate controlCoordinate1:(CLLocationCoordinate2D)controlCoordinate1 controlCoordinate2:(CLLocationCoordinate2D)controlCoordinate2; + +/** Draw a quad curve from the current pen location to a coordinate. +* @param coordinate The coordinate to draw to. +* @param controlCoordinate The control coordinate. */ +- (void)addQuadCurveToCoordinate:(CLLocationCoordinate2D)coordinate controlCoordinate:(CLLocationCoordinate2D)controlCoordinate; + +/** Draw a curve from the current pen location to a projected point. +* @param projectedPoint The projected point to draw to. +* @param controlProjectedPoint1 The first control projected point. +* @param controlProjectedPoint2 The second control projected point. */ +- (void)addCurveToProjectedPoint:(RMProjectedPoint)projectedPoint controlProjectedPoint1:(RMProjectedPoint)controlProjectedPoint1 controlProjectedPoint2:(RMProjectedPoint)controlProjectedPoint2; + +/** Draw a quad curve from the current pen location to a projected point. +* @param projectedPoint The projected point to draw to. +* @param controlProjectedPoint The control projected point. */ +- (void)addQuadCurveToProjectedPoint:(RMProjectedPoint)projectedPoint controlProjectedPoint:(RMProjectedPoint)controlProjectedPoint; + +/** Alter the path without rerecalculating the geometry. Recommended for many operations in order to increase performance. +* @param block A block containing the operations to perform. */ +- (void)performBatchOperations:(void (^)(RMShape *aShape))block; + +/** Closes the path, connecting the last point to the first. After this action, no further points can be added to the path. +* +* There is no requirement that a path be closed. */ - (void)closePath; @end diff --git a/MapView/Map/RMShape.m b/MapView/Map/RMShape.m index 951838625..ae0e9f0f0 100644 --- a/MapView/Map/RMShape.m +++ b/MapView/Map/RMShape.m @@ -1,7 +1,7 @@ /// // RMShape.m // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -42,7 +42,9 @@ @implementation RMShape CAShapeLayer *shapeLayer; UIBezierPath *bezierPath; - RMMapView *mapView; + NSMutableArray *points; + + __weak RMMapView *mapView; } @synthesize scaleLineWidth; @@ -62,11 +64,11 @@ - (id)initWithView:(RMMapView *)aMapView mapView = aMapView; - bezierPath = [[UIBezierPath alloc] init]; + bezierPath = [UIBezierPath new]; lineWidth = kDefaultLineWidth; ignorePathUpdates = NO; - shapeLayer = [[CAShapeLayer alloc] init]; + shapeLayer = [CAShapeLayer new]; shapeLayer.rasterizationScale = [[UIScreen mainScreen] scale]; shapeLayer.lineWidth = lineWidth; shapeLayer.lineCap = kCALineCapButt; @@ -83,25 +85,19 @@ - (id)initWithView:(RMMapView *)aMapView previousBounds = CGRectZero; lastScale = 0.0; - self.masksToBounds = YES; + self.masksToBounds = NO; scaleLineWidth = NO; scaleLineDash = NO; isFirstPoint = YES; + points = [NSMutableArray array]; + [(id)self setValue:[[UIScreen mainScreen] valueForKey:@"scale"] forKey:@"contentsScale"]; return self; } -- (void)dealloc -{ - mapView = nil; - [bezierPath release]; bezierPath = nil; - [shapeLayer release]; shapeLayer = nil; - [super dealloc]; -} - - (id )actionForKey:(NSString *)key { return nil; @@ -127,6 +123,9 @@ - (void)recalculateGeometryAnimated:(BOOL)animated shapeLayer.lineWidth = scaledLineWidth; + if (self.fillPatternImage) + shapeLayer.fillColor = [[UIColor colorWithPatternImage:self.fillPatternImage] CGColor]; + if (lineDashLengths) { if (scaleLineDash) @@ -173,8 +172,6 @@ - (void)recalculateGeometryAnimated:(BOOL)animated // calculate the bounds of the scaled path CGRect boundsInMercators = scaledPath.bounds; nonClippedBounds = CGRectInset(boundsInMercators, -scaledLineWidth - (2 * shapeLayer.shadowRadius), -scaledLineWidth - (2 * shapeLayer.shadowRadius)); - - [scaledPath release]; } // if the path is not scaled, nonClippedBounds stay the same as in the previous invokation @@ -182,7 +179,7 @@ - (void)recalculateGeometryAnimated:(BOOL)animated // 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; @@ -273,12 +270,21 @@ - (void)recalculateGeometryAnimated:(BOOL)animated } self.anchorPoint = clippedAnchorPoint; + + if (self.annotation && [points count]) + { + self.annotation.coordinate = ((CLLocation *)[points objectAtIndex:0]).coordinate; + [self.annotation setBoundingBoxFromLocations:points]; + } } #pragma mark - -- (void)addPointToProjectedPoint:(RMProjectedPoint)point withDrawing:(BOOL)isDrawing + +- (void)addCurveToProjectedPoint:(RMProjectedPoint)point controlPoint1:(RMProjectedPoint)controlPoint1 controlPoint2:(RMProjectedPoint)controlPoint2 withDrawing:(BOOL)isDrawing { + [points addObject:[[CLLocation alloc] initWithLatitude:[mapView projectedPointToCoordinate:point].latitude longitude:[mapView projectedPointToCoordinate:point].longitude]]; + if (isFirstPoint) { isFirstPoint = FALSE; @@ -294,9 +300,35 @@ - (void)addPointToProjectedPoint:(RMProjectedPoint)point withDrawing:(BOOL)isDra point.y = point.y - projectedLocation.y; if (isDrawing) - [bezierPath addLineToPoint:CGPointMake(point.x, -point.y)]; + { + if (controlPoint1.x == (double)INFINITY && controlPoint2.x == (double)INFINITY) + { + [bezierPath addLineToPoint:CGPointMake(point.x, -point.y)]; + } + else if (controlPoint2.x == (double)INFINITY) + { + controlPoint1.x = controlPoint1.x - projectedLocation.x; + controlPoint1.y = controlPoint1.y - projectedLocation.y; + + [bezierPath addQuadCurveToPoint:CGPointMake(point.x, -point.y) + controlPoint:CGPointMake(controlPoint1.x, -controlPoint1.y)]; + } + else + { + controlPoint1.x = controlPoint1.x - projectedLocation.x; + controlPoint1.y = controlPoint1.y - projectedLocation.y; + controlPoint2.x = controlPoint2.x - projectedLocation.x; + controlPoint2.y = controlPoint2.y - projectedLocation.y; + + [bezierPath addCurveToPoint:CGPointMake(point.x, -point.y) + controlPoint1:CGPointMake(controlPoint1.x, -controlPoint1.y) + controlPoint2:CGPointMake(controlPoint2.x, -controlPoint2.y)]; + } + } else + { [bezierPath moveToPoint:CGPointMake(point.x, -point.y)]; + } lastScale = 0.0; [self recalculateGeometryAnimated:NO]; @@ -307,7 +339,10 @@ - (void)addPointToProjectedPoint:(RMProjectedPoint)point withDrawing:(BOOL)isDra - (void)moveToProjectedPoint:(RMProjectedPoint)projectedPoint { - [self addPointToProjectedPoint:projectedPoint withDrawing:NO]; + [self addCurveToProjectedPoint:projectedPoint + controlPoint1:RMProjectedPointMake((double)INFINITY, (double)INFINITY) + controlPoint2:RMProjectedPointMake((double)INFINITY, (double)INFINITY) + withDrawing:NO]; } - (void)moveToScreenPoint:(CGPoint)point @@ -324,7 +359,10 @@ - (void)moveToCoordinate:(CLLocationCoordinate2D)coordinate - (void)addLineToProjectedPoint:(RMProjectedPoint)projectedPoint { - [self addPointToProjectedPoint:projectedPoint withDrawing:YES]; + [self addCurveToProjectedPoint:projectedPoint + controlPoint1:RMProjectedPointMake((double)INFINITY, (double)INFINITY) + controlPoint2:RMProjectedPointMake((double)INFINITY, (double)INFINITY) + withDrawing:YES]; } - (void)addLineToScreenPoint:(CGPoint)point @@ -339,7 +377,45 @@ - (void)addLineToCoordinate:(CLLocationCoordinate2D)coordinate [self addLineToProjectedPoint:mercator]; } -- (void)performBatchOperations:(void (^)(RMShape *aPath))block +- (void)addCurveToCoordinate:(CLLocationCoordinate2D)coordinate controlCoordinate1:(CLLocationCoordinate2D)controlCoordinate1 controlCoordinate2:(CLLocationCoordinate2D)controlCoordinate2 +{ + RMProjectedPoint projectedPoint = [[mapView projection] coordinateToProjectedPoint:coordinate]; + + RMProjectedPoint controlProjectedPoint1 = [[mapView projection] coordinateToProjectedPoint:controlCoordinate1]; + RMProjectedPoint controlProjectedPoint2 = [[mapView projection] coordinateToProjectedPoint:controlCoordinate2]; + + [self addCurveToProjectedPoint:projectedPoint + controlProjectedPoint1:controlProjectedPoint1 + controlProjectedPoint2:controlProjectedPoint2]; +} + +- (void)addQuadCurveToCoordinate:(CLLocationCoordinate2D)coordinate controlCoordinate:(CLLocationCoordinate2D)controlCoordinate +{ + RMProjectedPoint projectedPoint = [[mapView projection] coordinateToProjectedPoint:coordinate]; + + RMProjectedPoint controlProjectedPoint = [[mapView projection] coordinateToProjectedPoint:controlCoordinate]; + + [self addQuadCurveToProjectedPoint:projectedPoint + controlProjectedPoint:controlProjectedPoint]; +} + +- (void)addCurveToProjectedPoint:(RMProjectedPoint)projectedPoint controlProjectedPoint1:(RMProjectedPoint)controlProjectedPoint1 controlProjectedPoint2:(RMProjectedPoint)controlProjectedPoint2 +{ + [self addCurveToProjectedPoint:projectedPoint + controlPoint1:controlProjectedPoint1 + controlPoint2:controlProjectedPoint2 + withDrawing:YES]; +} + +- (void)addQuadCurveToProjectedPoint:(RMProjectedPoint)projectedPoint controlProjectedPoint:(RMProjectedPoint)controlProjectedPoint +{ + [self addCurveToProjectedPoint:projectedPoint + controlPoint1:controlProjectedPoint + controlPoint2:RMProjectedPointMake((double)INFINITY, (double)INFINITY) + withDrawing:YES]; +} + +- (void)performBatchOperations:(void (^)(RMShape *aShape))block { ignorePathUpdates = YES; block(self); @@ -351,9 +427,47 @@ - (void)performBatchOperations:(void (^)(RMShape *aPath))block #pragma mark - Accessors +- (BOOL)containsPoint:(CGPoint)thePoint +{ + BOOL containsPoint = NO; + + if ([self.fillColor isEqual:[UIColor clearColor]]) + { + // if shape is not filled with a color, do a simple "point on path" test + // + if (self.additionalTouchPadding) + { + CGPathRef tapTargetPath = CGPathCreateCopyByStrokingPath(shapeLayer.path, nil, fmaxf(self.additionalTouchPadding, shapeLayer.lineWidth), 0, 0, 0); + + if (tapTargetPath) + { + containsPoint = [[UIBezierPath bezierPathWithCGPath:tapTargetPath] containsPoint:thePoint]; + + CGPathRelease(tapTargetPath); + } + } + else + { + UIGraphicsBeginImageContext(self.bounds.size); + CGContextAddPath(UIGraphicsGetCurrentContext(), shapeLayer.path); + containsPoint = CGContextPathContainsPoint(UIGraphicsGetCurrentContext(), thePoint, kCGPathStroke); + UIGraphicsEndImageContext(); + } + } + else + { + // else do a "path contains point" test + // + containsPoint = CGPathContainsPoint(shapeLayer.path, nil, thePoint, [shapeLayer.fillRule isEqualToString:kCAFillRuleEvenOdd]); + } + + return containsPoint; +} + - (void)closePath { - [bezierPath closePath]; + if ([points count]) + [self addLineToCoordinate:((CLLocation *)[points objectAtIndex:0]).coordinate]; } - (float)lineWidth @@ -419,6 +533,18 @@ - (void)setFillColor:(UIColor *)aFillColor } } +- (void)setFillPatternImage:(UIImage *)fillPatternImage +{ + if (fillPatternImage) + self.fillColor = nil; + + if (_fillPatternImage != fillPatternImage) + { + _fillPatternImage = fillPatternImage; + [self recalculateGeometryAnimated:NO]; + } +} + - (CGFloat)shadowBlur { return shapeLayer.shadowRadius; @@ -481,4 +607,13 @@ - (void)setPosition:(CGPoint)newPosition animated:(BOOL)animated [self recalculateGeometryAnimated:animated]; } +- (void)setAnnotation:(RMAnnotation *)newAnnotation +{ + if (newAnnotation) + { + super.annotation = newAnnotation; + [self recalculateGeometryAnimated:NO]; + } +} + @end diff --git a/MapView/Map/RMShapeAnnotation.h b/MapView/Map/RMShapeAnnotation.h new file mode 100644 index 000000000..e02913c33 --- /dev/null +++ b/MapView/Map/RMShapeAnnotation.h @@ -0,0 +1,54 @@ +// +// RMShapeAnnotation.h +// MapView +// +// 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. + +#import "RMAnnotation.h" + +/** An RMShapeAnnotation is an abstract subclass of RMAnnotation that is used to represent a shape consisting of one or more points. You should not create instances of this class directly. Instead, you should create instances of the RMPolylineAnnotation or RMPolygonAnnotation classes. However, you can use the properties of this class to access information about the specific points associated with the line or polygon. +* +* Providing a layer manually for instances of RMShapeAnnotation subclasses will not have any effect. */ +@interface RMShapeAnnotation : RMAnnotation + +/** Initialize a shape annotation. +* @param aMapView The map view on which to place the annotation. +* @param points An array of CLLocation points defining the shape. The data in this array is copied to the new object. +* @return An initialized shape annotation object, or `nil` if an annotation was unable to be initialized. */ +- (id)initWithMapView:(RMMapView *)aMapView points:(NSArray *)points; + +/** The array of points associated with the shape. (read-only) */ +@property (nonatomic, readonly, strong) NSArray *points; + +/** A line color for the annotation's shape. */ +@property (nonatomic, strong) UIColor *lineColor; + +/** A line width for the annotation's shape. */ +@property (nonatomic, assign) CGFloat lineWidth; + +/** A fill color for the annotation's shape. */ +@property (nonatomic, strong) UIColor *fillColor; + +@end diff --git a/MapView/Map/RMShapeAnnotation.m b/MapView/Map/RMShapeAnnotation.m new file mode 100644 index 000000000..8fd664a44 --- /dev/null +++ b/MapView/Map/RMShapeAnnotation.m @@ -0,0 +1,84 @@ +// +// RMShapeAnnotation.m +// MapView +// +// 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. + +#import "RMShapeAnnotation.h" + +#import "RMShape.h" + +@implementation RMShapeAnnotation + +@synthesize points=_points; + +- (id)initWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle +{ + return [self initWithMapView:aMapView points:nil]; +} + +- (id)initWithMapView:(RMMapView *)aMapView points:(NSArray *)points +{ + if (!(self = [super initWithMapView:aMapView coordinate:((CLLocation *)[points objectAtIndex:0]).coordinate andTitle:nil])) + return nil; + + _points = [points copy]; + + [self setBoundingBoxFromLocations:points]; + + return self; +} + +- (void)setLineColor:(UIColor *)lineColor +{ + [(RMShape *)[self layer] setLineColor:lineColor]; +} + +- (UIColor *)lineColor +{ + return ((RMShape *)[self layer]).lineColor; +} + +- (void)setLineWidth:(CGFloat)lineWidth +{ + [(RMShape *)[self layer] setLineWidth:lineWidth]; +} + +- (CGFloat)lineWidth +{ + return ((RMShape *)[self layer]).lineWidth; +} + +- (void)setFillColor:(UIColor *)lineColor +{ + [(RMShape *)[self layer] setFillColor:lineColor]; +} + +- (UIColor *)fillColor +{ + return ((RMShape *)[self layer]).fillColor; +} + +@end diff --git a/MapView/Map/RMStaticMapView.h b/MapView/Map/RMStaticMapView.h new file mode 100644 index 000000000..8ee6da01e --- /dev/null +++ b/MapView/Map/RMStaticMapView.h @@ -0,0 +1,77 @@ +// +// RMStaticMapView.h +// +// 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. + +#import + +#import "RMMapView.h" + +/** An RMStaticMapView object provides an embeddable, static map image view. You use this class to display map information in your application that does not need to change or provide user interaction. You can center the map on a given coordinate and zoom level, specify the size of the area you want to display, and optionally provide a completion handler that can be performed upon map load. The map can also automatically have markers added to it if they were provided as simplestyle data when the map was created. +* +* @warning Please note that you are responsible for getting permission to use the map data, and for ensuring your use adheres to the relevant terms of use. You are also responsible for displaying attribution details for the data elsewhere in your application, if applicable. */ +@interface RMStaticMapView : RMMapView + +/** @name Initializing a Static Map View */ + +/** Initialize a static map view with a given frame and mapID. +* +* The map ID is expected to provide initial center coordinate and zoom level information, and may optionally also include simplestyle marker data, which will automatically be added to the map view. +* @param frame The frame with which to initialize the map view. +* @param mapID The Mapbox map ID string, typically in the format `.map-`. +* @return An initialized map view, or `nil` if the map view was unable to be initialized. */ +- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID; + +/** Initialize a static map view with a given frame and mapID, performing a block upon completion of the map load. +* +* The map ID is expected to provide initial center coordinate and zoom level information, and may optionally also include simplestyle marker data, which will automatically be added to the map view. The block will be performed upon completion of the load of both the map and of any simplestyle markers included with the map ID. +* @param frame The frame with which to initialize the map view. +* @param mapID The Mapbox map ID string, typically in the format `.map-`. +* @param handler A block to be performed upon map and marker load completion. An image of the map, including markers, is passed as an argument to the block in the event that you wish to use it elsewhere. The handler will be called on the main dispatch queue. +* @return An initialized map view, or `nil` if the map view was unable to be initialized. */ +- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID completionHandler:(void (^)(UIImage *))handler; + +/** Initialize a static map view with a given frame, mapID, center coordinate, and zoom level. +* +* The map ID may optionally also include simplestyle marker data, which will automatically be added to the map view. +* @param frame The frame with which to initialize the map view. +* @param mapID The Mapbox map ID string, typically in the format `.map-`. +* @param centerCoordinate The map center coordinate. +* @param zoomLevel The map zoom level. +* @return An initialized map view, or `nil` if the map view was unable to be initialized. */ +- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID centerCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(CGFloat)zoomLevel; + +/** Designated initializer. Initialize a static map view with a given frame, mapID, center coordinate, and zoom level, performing a block upon completion of the map load. +* +* The map ID may optionally also include simplestyle marker data, which will automatically be added to the map view. The block will be performed upon completion of the load of both the map and of any simplestyle markers included with the map ID. +* @param frame The frame with which to initialize the map view. +* @param mapID The Mapbox map ID string, typically in the format `.map-`. +* @param centerCoordinate The map center coordinate. +* @param zoomLevel The map zoom level. +* @param handler A block to be performed upon map load completion. An image of the map, including markers, is passed as an argument to the block in the event that you wish to use it elsewhere. The handler will be called on the main dispatch queue. +* @return An initialized map view, or `nil` if the map view was unable to be initialized. */ +- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID centerCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(CGFloat)zoomLevel completionHandler:(void (^)(UIImage *))handler; + +@end diff --git a/MapView/Map/RMStaticMapView.m b/MapView/Map/RMStaticMapView.m new file mode 100644 index 000000000..c9f459202 --- /dev/null +++ b/MapView/Map/RMStaticMapView.m @@ -0,0 +1,139 @@ +// +// RMStaticMapView.m +// +// 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. + +#import "RMStaticMapView.h" + +#import "RMAnnotation.h" +#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:kMapboxDefaultCenter zoomLevel:kMapboxDefaultZoom completionHandler:nil]; +} + +- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID completionHandler:(void (^)(UIImage *))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 +{ + return [self initWithFrame:frame mapID:mapID centerCoordinate:centerCoordinate zoomLevel:zoomLevel completionHandler:nil]; +} + +- (id)initWithFrame:(CGRect)frame mapID:(NSString *)mapID centerCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(CGFloat)zoomLevel completionHandler:(void (^)(UIImage *))handler +{ + 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 +{ + RMMapboxSource *tileSource = [[RMMapboxSource alloc] initWithMapID:(mapID ? mapID : kMapboxPlaceholderMapID) enablingDataOnMapView:self]; + + self.tileSource = tileSource; + + if ( ! CLLocationCoordinate2DIsValid(centerCoordinate)) + centerCoordinate = [tileSource centerCoordinate]; + + [self setCenterCoordinate:centerCoordinate animated:NO]; + + if (zoomLevel < 0) + zoomLevel = [tileSource centerZoom]; + + [self setZoom:zoomLevel]; + + self.backgroundColor = [UIColor colorWithPatternImage:[RMMapView resourceImageNamed:@"LoadingTile.png"]]; + + self.hideAttribution = YES; + + self.showsUserLocation = NO; + + self.userInteractionEnabled = NO; + + if (handler) + { + _weakSelf = self; + + dispatch_async(tileSource.dataQueue, ^(void) + { + dispatch_sync(dispatch_get_main_queue(), ^(void) + { + UIImage *image = [_weakSelf takeSnapshot]; + + handler(image); + }); + }); + } +} + +- (void)addAnnotation:(RMAnnotation *)annotation +{ + annotation.layer = [[RMMarker alloc] initWithMapboxMarkerImage:[annotation.userInfo objectForKey:@"marker-symbol"] + tintColorHex:[annotation.userInfo objectForKey:@"marker-color"] + sizeString:[annotation.userInfo objectForKey:@"marker-size"]]; + + [super addAnnotation:annotation]; +} + +@end diff --git a/MapView/Map/RMTile.c b/MapView/Map/RMTile.c index 4aa3603e7..3633a4e98 100644 --- a/MapView/Map/RMTile.c +++ b/MapView/Map/RMTile.c @@ -1,7 +1,7 @@ // // RMTile.c // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMTile.h b/MapView/Map/RMTile.h index 96df8756b..bbbe8c06b 100644 --- a/MapView/Map/RMTile.h +++ b/MapView/Map/RMTile.h @@ -1,7 +1,7 @@ // // RMTile.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/MapView/Map/RMTileCache.h b/MapView/Map/RMTileCache.h index ee487c1c9..2095fa78c 100644 --- a/MapView/Map/RMTileCache.h +++ b/MapView/Map/RMTileCache.h @@ -39,33 +39,157 @@ typedef enum : short { #pragma mark - +/** The RMTileCache protocol describes behaviors that tile caches should implement. */ @protocol RMTileCache -// Returns the cached image if it exists. nil otherwise. +/** @name Querying the Cache */ + +/** Returns an image from the cache if it exists. +* @param tile A desired RMTile. +* @param cacheKey The key representing a certain cache. +* @return An image of the tile that can be used to draw a portion of the map. */ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)cacheKey; +/** Returns an image from the cache if it exists. +* @param tile A desired RMTile. +* @param cacheKey The key representing a certain cache. +* @param shouldBypassMemoryCache Whether to only consult disk-based caches. +* @return An image of the tile that can be used to draw a portion of the map. */ +- (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)cacheKey bypassingMemoryCache:(BOOL)shouldBypassMemoryCache; + - (void)didReceiveMemoryWarning; @optional +/** @name Adding to the Cache */ + +/** Adds a tile image to the specified cache. +* @param image A tile image to be cached. +* @param tile The RMTile describing the map location of the image. +* @param cacheKey The key representing a certain cache. */ - (void)addImage:(UIImage *)image forTile:(RMTile)tile withCacheKey:(NSString *)cacheKey; -// removes all tile images from the memory and disk subcaches +/** Adds tile image data to the specified cache, bypassing the memory cache and only writing to disk. This is useful for instances where many tiles are downloaded directly to disk for later use offline. +* @param data The tile image data to be cached. +* @param tile The RMTile describing the map location of the image. +* @param cacheKey The key representing a certain cache. */ +- (void)addDiskCachedImageData:(NSData *)data forTile:(RMTile)tile withCacheKey:(NSString *)cacheKey; + +/** @name Clearing the Cache */ + +/** Removes all tile images from a cache. */ - (void)removeAllCachedImages; +- (void)removeAllCachedImagesForCacheKey:(NSString *)cacheKey; + +@end + +#pragma mark - + +/** The RMTileCacheBackgroundDelegate protocol is for receiving notifications about background tile cache download operations. +* +* These callbacks are not guaranteed to be received on the main thread, so if you intend to do work in the user interface, you should properly enqueue such jobs on the main thread. */ +@protocol RMTileCacheBackgroundDelegate + +@optional + +/** Sent when the background caching operation begins. +* @param tileCache The tile cache. +* @param tileCount The total number of tiles required for coverage of the desired geographic area. +* @param tileSource The tile source providing the tiles. */ +- (void)tileCache:(RMTileCache *)tileCache didBeginBackgroundCacheWithCount:(NSUInteger)tileCount forTileSource:(id )tileSource; + +/** Sent upon caching of each tile in a background cache operation. +* @param tileCache The tile cache. +* @param tile A structure representing the tile in question. +* @param tileIndex The index of the tile in question, beginning with `1` and ending with totalTileCount. +* @param totalTileCount The total number of of tiles required for coverage of the desired geographic area. */ +- (void)tileCache:(RMTileCache *)tileCache didBackgroundCacheTile:(RMTile)tile withIndex:(NSUInteger)tileIndex ofTotalTileCount:(NSUInteger)totalTileCount; + +/** Sent upon error when trying to cache a tile in a background cache operation. +* @param tileCache The tile cache. +* @param error The error received. +* @param tile A structure representing the tile in question. */ +- (void)tileCache:(RMTileCache *)tileCache didReceiveError:(NSError *)error whenCachingTile:(RMTile)tile; + +/** Sent when all tiles have completed downloading and caching. +* @param tileCache The tile cache. */ +- (void)tileCacheDidFinishBackgroundCache:(RMTileCache *)tileCache; + +/** Sent when the cache download operation has completed cancellation and the cache object is safe to dispose of. +* @param tileCache The tile cache. */ +- (void)tileCacheDidCancelBackgroundCache:(RMTileCache *)tileCache; @end #pragma mark - +/** An RMTileCache object manages memory-based and disk-based caches for map tiles that have been retrieved from the network. +* +* An RMMapView has one RMTileCache across all tile sources, which is further divided according to each tile source's uniqueTilecacheKey property in order to keep tiles separate in the cache. +* +* An RMTileCache is a key component of offline map use. All tile requests pass through the tile cache and are served from cache if available, avoiding network operation. If tiles exist in cache already, a tile source that is instantiated when offline will still be able to serve tile imagery to the map renderer for areas that have been previously cached. This can occur either from normal map use, since all tiles are cached after being retrieved, or from proactive caching ahead of time using the beginBackgroundCacheForTileSource:southWest:northEast:minZoom:maxZoom: method. +* +* @see [RMDatabaseCache initUsingCacheDir:] */ @interface RMTileCache : NSObject +/** @name Initializing a Cache Manager */ + +/** Initializes and returns a newly allocated cache object with specified expiry period. +* +* If the `init` method is used to initialize a cache instead, a period of `0` is used. In that case, time-based expiration of tiles is not performed, but rather the cached tile count is used instead. +* +* @param period A period of time after which tiles should be expunged from the cache. +* @return An initialized cache object or `nil` if the object couldn't be created. */ - (id)initWithExpiryPeriod:(NSTimeInterval)period; +/** @name Identifying Cache Objects */ + +/** Return an identifying hash number for the specified tile. +* +* @param tile A tile image to hash. +* @return A unique number for the specified tile. */ + (NSNumber *)tileHash:(RMTile)tile; -// Add another cache to the chain +/** @name Adding Caches to the Cache Manager */ + +/** Adds a given cache to the cache management system. +* +* @param cache A memory-based or disk-based cache. */ - (void)addCache:(id )cache; +- (void)insertCache:(id )cache atIndex:(NSUInteger)index; + +/** The list of caches managed by a cache manager. This could include memory-based, disk-based, or other types of caches. */ +@property (nonatomic, readonly, strong) NSArray *tileCaches; - (void)didReceiveMemoryWarning; +/** @name Background Downloading */ + +/** A delegate to notify of background tile cache download operations. */ +@property (nonatomic, weak) id backgroundCacheDelegate; + +/** Whether or not the tile cache is currently background caching. */ +@property (nonatomic, readonly, assign) BOOL isBackgroundCaching; + +/** Tells the tile cache to begin background caching. Progress during the caching operation can be observed by implementing the RMTileCacheBackgroundDelegate protocol. +* @param tileSource The tile source from which to retrieve tiles. +* @param southWest The southwest corner of the geographic area to cache. +* @param northEast The northeast corner of the geographic area to cache. +* @param minZoom The minimum zoom level to cache. +* @param maxZoom The maximum zoom level to cache. */ +- (void)beginBackgroundCacheForTileSource:(id )tileSource southWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast minZoom:(NSUInteger)minZoom maxZoom:(NSUInteger)maxZoom; + +/** Cancel any background caching. +* +* This method returns immediately so as to not block the calling thread. If you wish to be notified of the actual cancellation completion, implement the tileCacheDidCancelBackgroundCache: delegate method. */ +- (void)cancelBackgroundCache; + +/** A count of the number of tiles that would be downloaded in a background tile cache download operation. +* @param southWest The southwest corner of the geographic area to cache. +* @param northEast The northeast corner of the geographic area to cache. +* @param minZoom The minimum zoom level to cache. +* @param maxZoom The maximum zoom level to cache. +* @return The number of tiles representing the coverage area. */ +- (NSUInteger)tileCountForSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast minZoom:(NSUInteger)minZoom maxZoom:(NSUInteger)maxZoom; + @end diff --git a/MapView/Map/RMTileCache.m b/MapView/Map/RMTileCache.m index f5e2340c2..7ba9f2486 100644 --- a/MapView/Map/RMTileCache.m +++ b/MapView/Map/RMTileCache.m @@ -34,6 +34,10 @@ #import "RMConfiguration.h" #import "RMTileSource.h" +#import "RMAbstractWebMapSource.h" + +#import "RMTileCacheDownloadOperation.h" + @interface RMTileCache (Configuration) - (id )memoryCacheWithConfig:(NSDictionary *)cfg; @@ -52,20 +56,29 @@ @implementation RMTileCache NSTimeInterval _expiryPeriod; dispatch_queue_t _tileCacheQueue; + + id _activeTileSource; + NSOperationQueue *_backgroundFetchQueue; } +@synthesize backgroundCacheDelegate=_backgroundCacheDelegate; + - (id)initWithExpiryPeriod:(NSTimeInterval)period { if (!(self = [super init])) return nil; - _tileCaches = [[NSMutableArray alloc] init]; + _tileCaches = [NSMutableArray new]; _tileCacheQueue = dispatch_queue_create("routeme.tileCacheQueue", DISPATCH_QUEUE_CONCURRENT); _memoryCache = nil; _expiryPeriod = period; + + _backgroundCacheDelegate = nil; + _activeTileSource = nil; + _backgroundFetchQueue = nil; - id cacheCfg = [[RMConfiguration configuration] cacheConfiguration]; + id cacheCfg = [[RMConfiguration sharedInstance] cacheConfiguration]; if (!cacheCfg) cacheCfg = [NSArray arrayWithObjects: [NSDictionary dictionaryWithObject: @"memory-cache" forKey: @"type"], @@ -82,7 +95,7 @@ - (id)initWithExpiryPeriod:(NSTimeInterval)period if ([@"memory-cache" isEqualToString:type]) { - _memoryCache = [[self memoryCacheWithConfig:cfg] retain]; + _memoryCache = [self memoryCacheWithConfig:cfg]; continue; } @@ -113,12 +126,17 @@ - (id)init - (void)dealloc { + if (self.isBackgroundCaching) + [self cancelBackgroundCache]; + dispatch_barrier_sync(_tileCacheQueue, ^{ - [_memoryCache release]; _memoryCache = nil; - [_tileCaches release]; _tileCaches = nil; + _memoryCache = nil; + _tileCaches = nil; }); - - [super dealloc]; + +#if ! OS_OBJECT_USE_OBJC + dispatch_release(_tileCacheQueue); +#endif } - (void)addCache:(id )cache @@ -128,15 +146,37 @@ - (void)addCache:(id )cache }); } +- (void)insertCache:(id )cache atIndex:(NSUInteger)index +{ + dispatch_barrier_async(_tileCacheQueue, ^{ + if (index >= [_tileCaches count]) + [_tileCaches addObject:cache]; + else + [_tileCaches insertObject:cache atIndex:index]; + }); +} + +- (NSArray *)tileCaches +{ + return [NSArray arrayWithArray:_tileCaches]; +} + + (NSNumber *)tileHash:(RMTile)tile { return [NSNumber numberWithUnsignedLongLong:RMTileKey(tile)]; } -// Returns the cached image if it exists. nil otherwise. - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey { - __block UIImage *image = [_memoryCache cachedImage:tile withCacheKey:aCacheKey]; + return [self cachedImage:tile withCacheKey:aCacheKey bypassingMemoryCache:NO]; +} + +- (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey bypassingMemoryCache:(BOOL)shouldBypassMemoryCache +{ + __block UIImage *image = nil; + + if (!shouldBypassMemoryCache) + image = [_memoryCache cachedImage:tile withCacheKey:aCacheKey]; if (image) return image; @@ -145,9 +185,9 @@ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey for (id cache in _tileCaches) { - image = [[cache cachedImage:tile withCacheKey:aCacheKey] retain]; + image = [cache cachedImage:tile withCacheKey:aCacheKey]; - if (image != nil) + if (image != nil && !shouldBypassMemoryCache) { [_memoryCache addImage:image forTile:tile withCacheKey:aCacheKey]; break; @@ -156,7 +196,7 @@ - (UIImage *)cachedImage:(RMTile)tile withCacheKey:(NSString *)aCacheKey }); - return [image autorelease]; + return image; } - (void)addImage:(UIImage *)image forTile:(RMTile)tile withCacheKey:(NSString *)aCacheKey @@ -177,6 +217,22 @@ - (void)addImage:(UIImage *)image forTile:(RMTile)tile withCacheKey:(NSString *) }); } +- (void)addDiskCachedImageData:(NSData *)data forTile:(RMTile)tile withCacheKey:(NSString *)aCacheKey +{ + if (!data || !aCacheKey) + return; + + dispatch_sync(_tileCacheQueue, ^{ + + for (id cache in _tileCaches) + { + if ([cache respondsToSelector:@selector(addDiskCachedImageData:forTile:withCacheKey:)]) + [cache addDiskCachedImageData:data forTile:tile withCacheKey:aCacheKey]; + } + + }); +} + - (void)didReceiveMemoryWarning { LogMethod(); @@ -207,6 +263,189 @@ - (void)removeAllCachedImages }); } +- (void)removeAllCachedImagesForCacheKey:(NSString *)cacheKey +{ + [_memoryCache removeAllCachedImagesForCacheKey:cacheKey]; + + dispatch_sync(_tileCacheQueue, ^{ + + for (id cache in _tileCaches) + { + [cache removeAllCachedImagesForCacheKey:cacheKey]; + } + }); +} + +- (BOOL)isBackgroundCaching +{ + return (_activeTileSource || _backgroundFetchQueue); +} + +- (BOOL)markCachingComplete +{ + BOOL incomplete = (_activeTileSource || _backgroundFetchQueue); + + _activeTileSource = nil; + _backgroundFetchQueue = nil; + + return incomplete; +} + +- (NSUInteger)tileCountForSouthWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast minZoom:(NSUInteger)minZoom maxZoom:(NSUInteger)maxZoom +{ + NSUInteger minCacheZoom = minZoom; + NSUInteger maxCacheZoom = maxZoom; + + CLLocationDegrees minCacheLat = southWest.latitude; + CLLocationDegrees maxCacheLat = northEast.latitude; + CLLocationDegrees minCacheLon = southWest.longitude; + CLLocationDegrees maxCacheLon = northEast.longitude; + + NSAssert(minCacheZoom <= maxCacheZoom, @"Minimum zoom should be less than or equal to maximum zoom"); + NSAssert(maxCacheLat > minCacheLat, @"Northernmost bounds should exceed southernmost bounds"); + NSAssert(maxCacheLon > minCacheLon, @"Easternmost bounds should exceed westernmost bounds"); + + NSUInteger n, xMin, yMax, xMax, yMin; + + NSUInteger totalTiles = 0; + + for (NSUInteger zoom = minCacheZoom; zoom <= maxCacheZoom; zoom++) + { + n = pow(2.0, zoom); + xMin = floor(((minCacheLon + 180.0) / 360.0) * n); + yMax = floor((1.0 - (logf(tanf(minCacheLat * M_PI / 180.0) + 1.0 / cosf(minCacheLat * M_PI / 180.0)) / M_PI)) / 2.0 * n); + xMax = floor(((maxCacheLon + 180.0) / 360.0) * n); + yMin = floor((1.0 - (logf(tanf(maxCacheLat * M_PI / 180.0) + 1.0 / cosf(maxCacheLat * M_PI / 180.0)) / M_PI)) / 2.0 * n); + + totalTiles += (xMax + 1 - xMin) * (yMax + 1 - yMin); + } + + return totalTiles; +} + +- (void)beginBackgroundCacheForTileSource:(id )tileSource southWest:(CLLocationCoordinate2D)southWest northEast:(CLLocationCoordinate2D)northEast minZoom:(NSUInteger)minZoom maxZoom:(NSUInteger)maxZoom +{ + if (self.isBackgroundCaching) + return; + + NSAssert([tileSource isKindOfClass:[RMAbstractWebMapSource class]], @"only web-based tile sources are supported for downloading"); + + _activeTileSource = tileSource; + + _backgroundFetchQueue = [NSOperationQueue new]; + [_backgroundFetchQueue setMaxConcurrentOperationCount:6]; + if ([_backgroundFetchQueue respondsToSelector:@selector(setQualityOfService:)]) + { + [_backgroundFetchQueue setQualityOfService:NSQualityOfServiceUtility]; + } + + NSUInteger totalTiles = [self tileCountForSouthWest:southWest northEast:northEast minZoom:minZoom maxZoom:maxZoom]; + + NSUInteger minCacheZoom = minZoom; + NSUInteger maxCacheZoom = maxZoom; + + CLLocationDegrees minCacheLat = southWest.latitude; + CLLocationDegrees maxCacheLat = northEast.latitude; + CLLocationDegrees minCacheLon = southWest.longitude; + CLLocationDegrees maxCacheLon = northEast.longitude; + + if ([_backgroundCacheDelegate respondsToSelector:@selector(tileCache:didBeginBackgroundCacheWithCount:forTileSource:)]) + { + [_backgroundCacheDelegate tileCache:self + didBeginBackgroundCacheWithCount:totalTiles + forTileSource:_activeTileSource]; + } + + NSUInteger n, xMin, yMax, xMax, yMin; + + __block NSUInteger progTile = 0; + + for (NSUInteger zoom = minCacheZoom; zoom <= maxCacheZoom; zoom++) + { + n = pow(2.0, zoom); + xMin = floor(((minCacheLon + 180.0) / 360.0) * n); + yMax = floor((1.0 - (logf(tanf(minCacheLat * M_PI / 180.0) + 1.0 / cosf(minCacheLat * M_PI / 180.0)) / M_PI)) / 2.0 * n); + xMax = floor(((maxCacheLon + 180.0) / 360.0) * n); + yMin = floor((1.0 - (logf(tanf(maxCacheLat * M_PI / 180.0) + 1.0 / cosf(maxCacheLat * M_PI / 180.0)) / M_PI)) / 2.0 * n); + + for (NSUInteger x = xMin; x <= xMax; x++) + { + for (NSUInteger y = yMin; y <= yMax; y++) + { + RMTileCacheDownloadOperation *operation = [[RMTileCacheDownloadOperation alloc] initWithTile:RMTileMake((uint32_t)x, (uint32_t)y, zoom) + forTileSource:_activeTileSource + usingCache:self]; + + __weak RMTileCacheDownloadOperation *internalOperation = operation; + __weak RMTileCache *weakSelf = self; + + [operation setCompletionBlock:^(void) + { + if ( ! [internalOperation isCancelled]) + { + progTile++; + + if ([_backgroundCacheDelegate respondsToSelector:@selector(tileCache:didBackgroundCacheTile:withIndex:ofTotalTileCount:)]) + { + [_backgroundCacheDelegate tileCache:weakSelf + didBackgroundCacheTile:RMTileMake((uint32_t)x, (uint32_t)y, zoom) + withIndex:progTile + ofTotalTileCount:totalTiles]; + } + + if (progTile == totalTiles) + { + dispatch_async(dispatch_get_main_queue(), ^(void) + { + [weakSelf markCachingComplete]; + + if ([_backgroundCacheDelegate respondsToSelector:@selector(tileCacheDidFinishBackgroundCache:)]) + { + [_backgroundCacheDelegate tileCacheDidFinishBackgroundCache:weakSelf]; + } + }); + } + } + else + { + if ([_backgroundCacheDelegate respondsToSelector:@selector(tileCache:didReceiveError:whenCachingTile:)]) + { + [_backgroundCacheDelegate tileCache:weakSelf + didReceiveError:internalOperation.error + whenCachingTile:RMTileMake((uint32_t)x, (uint32_t)y, zoom)]; + } + } + }]; + + [_backgroundFetchQueue addOperation:operation]; + } + } + } +} + +- (void)cancelBackgroundCache +{ + __weak NSOperationQueue *weakBackgroundFetchQueue = _backgroundFetchQueue; + __weak RMTileCache *weakSelf = self; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) + { + dispatch_sync(dispatch_get_main_queue(), ^(void) + { + [weakBackgroundFetchQueue cancelAllOperations]; + [weakBackgroundFetchQueue waitUntilAllOperationsAreFinished]; + + if ([weakSelf markCachingComplete]) + { + if ([_backgroundCacheDelegate respondsToSelector:@selector(tileCacheDidCancelBackgroundCache:)]) + { + [_backgroundCacheDelegate tileCacheDidCancelBackgroundCache:weakSelf]; + } + } + }); + }); +} + @end #pragma mark - @@ -286,9 +525,7 @@ - (NSDictionary *)predicateValues } } - RMLog(@"Memory cache configuration: {capacity : %d}", capacity); - - return [[[RMMemoryCache alloc] initWithCapacity:capacity] autorelease]; + return [[RMMemoryCache alloc] initWithCapacity:capacity]; } - (id )databaseCacheWithConfig:(NSDictionary *)cfg @@ -356,7 +593,7 @@ - (NSDictionary *)predicateValues } else { - RMLog(@"illegal value for capacity: %d", value); + RMLog(@"illegal value for capacity: %ld", (long)value); } } @@ -386,9 +623,7 @@ - (NSDictionary *)predicateValues if (expiryPeriodNumber != nil) _expiryPeriod = [expiryPeriodNumber doubleValue]; - RMLog(@"Database cache configuration: {capacity : %d, strategy : %@, minimalPurge : %d, expiryPeriod: %.0f, useCacheDir : %@}", capacity, strategyStr, minimalPurge, _expiryPeriod, useCacheDir ? @"YES" : @"NO"); - - RMDatabaseCache *dbCache = [[[RMDatabaseCache alloc] initUsingCacheDir:useCacheDir] autorelease]; + RMDatabaseCache *dbCache = [[RMDatabaseCache alloc] initUsingCacheDir:useCacheDir]; [dbCache setCapacity:capacity]; [dbCache setPurgeStrategy:strategy]; [dbCache setMinimalPurge:minimalPurge]; diff --git a/MapView/Map/NSUserDefaults+RouteMe.h b/MapView/Map/RMTileCacheDownloadOperation.h similarity index 60% rename from MapView/Map/NSUserDefaults+RouteMe.h rename to MapView/Map/RMTileCacheDownloadOperation.h index c9606bf21..8588b06fb 100644 --- a/MapView/Map/NSUserDefaults+RouteMe.h +++ b/MapView/Map/RMTileCacheDownloadOperation.h @@ -1,7 +1,7 @@ // -// NSUserDefaults+RouteMe.h -// -// Copyright (c) 2008-2011, Route-Me Contributors +// RMTileCacheDownloadOperation.h +// +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -24,28 +24,17 @@ // 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. -// - -// -// If you link your Route-Me to your project as a static libary, -// add to your project's build param Other Linker Flags (OTHER_LDFLAGS) '-all_load' (without quotes). -// #import -#import "RMFoundation.h" - -@interface NSUserDefaults (RouteMe) -/// Returns the projected point associated with the specified key. -- (RMProjectedPoint)projectedPointForKey:(NSString *)key; +#import "RMTile.h" +#import "RMTileSource.h" +#import "RMTileCache.h" -/// Sets the value of the specified default key to the specified projected point. -- (void)setProjectedPoint:(RMProjectedPoint)projectedPoint forKey:(NSString *)key; +@interface RMTileCacheDownloadOperation : NSOperation -/// Returns the projected rectangle associated with the specified key. -- (RMProjectedRect)projectedRectForKey:(NSString *)key; +- (id)initWithTile:(RMTile)tile forTileSource:(id )source usingCache:(RMTileCache *)cache; -/// Sets the value of the specified default key to the specified projected rectangle. -- (void)setProjectedRect:(RMProjectedRect)projectedRect forKey:(NSString *)key; +@property (nonatomic, strong) NSError *error; @end diff --git a/MapView/Map/RMTileCacheDownloadOperation.m b/MapView/Map/RMTileCacheDownloadOperation.m new file mode 100644 index 000000000..870213672 --- /dev/null +++ b/MapView/Map/RMTileCacheDownloadOperation.m @@ -0,0 +1,96 @@ +// +// RMTileCacheDownloadOperation.m +// +// Copyright (c) 2008-2013, 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. + +#import "RMTileCacheDownloadOperation.h" +#import "RMAbstractWebMapSource.h" +#import "RMConfiguration.h" + +@implementation RMTileCacheDownloadOperation +{ + RMTile _tile; + __weak id _source; + __weak RMTileCache *_cache; +} + +- (id)initWithTile:(RMTile)tile forTileSource:(id )source usingCache:(RMTileCache *)cache +{ + if (!(self = [super init])) + return nil; + + NSAssert([source isKindOfClass:[RMAbstractWebMapSource class]], @"only web-based tile sources are supported for downloading"); + + _tile = tile; + _source = source; + _cache = cache; + + return self; +} + +- (void)main +{ + if ( ! _source || ! _cache) + [self cancel]; + + if ([self isCancelled]) + return; + + if ( ! [_cache cachedImage:_tile withCacheKey:[_source uniqueTilecacheKey] bypassingMemoryCache:YES]) + { + if ([self isCancelled]) + return; + + NSURL *tileURL = [(RMAbstractWebMapSource *)_source URLForTile:_tile]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:tileURL]; + request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + NSError *error = nil; + NSData *data = [NSURLConnection sendBrandedSynchronousRequest:request + returningResponse:nil + error:&error]; + + if ( ! data || error != nil) + { + if (error != nil) + { + self.error = error; + } + else + { + self.error = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorUnknown + userInfo:nil]; + } + + [self cancel]; + } + else + { + [_cache addDiskCachedImageData:data forTile:_tile withCacheKey:[_source uniqueTilecacheKey]]; + } + } +} + +@end diff --git a/MapView/Map/RMTileImage.m b/MapView/Map/RMTileImage.m index bb409fc79..c05be86ce 100644 --- a/MapView/Map/RMTileImage.m +++ b/MapView/Map/RMTileImage.m @@ -42,7 +42,7 @@ + (UIImage *)errorTile if (_didLoadErrorTile) return nil; - _errorTile = [[UIImage imageNamed:@"error.png"] retain]; + _errorTile = [UIImage imageNamed:@"error.png"]; _didLoadErrorTile = YES; return _errorTile; @@ -51,8 +51,7 @@ + (UIImage *)errorTile + (void)setErrorTile:(UIImage *)newErrorTile { if (_errorTile == newErrorTile) return; - [_errorTile autorelease]; - _errorTile = [newErrorTile retain]; + _errorTile = newErrorTile; _didLoadErrorTile = YES; } @@ -64,7 +63,7 @@ + (UIImage *)missingTile if (_didLoadMissingTile) return nil; - _missingTile = [[UIImage imageNamed:@"missing.png"] retain]; + _missingTile = [UIImage imageNamed:@"missing.png"]; _didLoadMissingTile = YES; return _missingTile; @@ -73,8 +72,7 @@ + (UIImage *)missingTile + (void)setMissingTile:(UIImage *)newMissingTile { if (_missingTile == newMissingTile) return; - [_missingTile autorelease]; - _missingTile = [newMissingTile retain]; + _missingTile = newMissingTile; _didLoadMissingTile = YES; } diff --git a/MapView/Map/RMTileMillSource.h b/MapView/Map/RMTileMillSource.h new file mode 100644 index 000000000..6482cf078 --- /dev/null +++ b/MapView/Map/RMTileMillSource.h @@ -0,0 +1,52 @@ +// +// RMTileMillSource.h +// +// 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. + +#import "RMGenericMapSource.h" + +/** An RMTileMillSource is used to display map tiles from a live, running instance of [TileMill](https://mapbox.com/tilemill). All instances of TileMill automatically include an HTTP server, allowing network access outside of the application. This tile source allows for an easier development cycle between map editing and testing in an iOS application. */ +@interface RMTileMillSource : RMGenericMapSource + +/** @name Creating Tile Sources */ + +/** Initialize and return a newly allocated TileMill tile source based on a given map name. This assumes that TileMill is running on the local development computer (e.g., `localhost`), which will not work from an iOS device but will work in the iOS Simulator. +* @param mapName The name of the map in TileMill, substituting dashes for spaces. +* @param tileCacheKey A unique cache string to use for this tile source's tiles in the tile cache. +* @param minZoom The minimum zoom level supported by the map. +* @param maxZoom The maximum zoom level supported by the map. +* @return An initialized TileMill tile source. */ +- (id)initWithMapName:(NSString *)mapName tileCacheKey:(NSString *)tileCacheKey minZoom:(float)minZoom maxZoom:(float)maxZoom; + +/** Initialize and return a newly allocated TileMill tile source based on a given host and map name. This is ideal for testing on an actual iOS device if the network name or address of the computer running TileMill is passed as the `host` parameter. +* @param host The hostname or IP address of the computer running TileMill. +* @param mapName The name of the map in TileMill, substituting dashes for spaces. +* @param tileCacheKey A unique cache string to use for this tile source's tiles in the tile cache. +* @param minZoom The minimum zoom level supported by the map. +* @param maxZoom The maximum zoom level supported by the map. +* @return An initialized TileMill tile source. */ +- (id)initWithHost:(NSString *)host mapName:(NSString *)mapName tileCacheKey:(NSString *)tileCacheKey minZoom:(float)minZoom maxZoom:(float)maxZoom; + +@end diff --git a/MapView/Map/RMTileMillSource.m b/MapView/Map/RMTileMillSource.m new file mode 100644 index 000000000..7e9d65387 --- /dev/null +++ b/MapView/Map/RMTileMillSource.m @@ -0,0 +1,49 @@ +// +// RMTileMillSource.m +// +// 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. + +#import "RMTileMillSource.h" + +@implementation RMTileMillSource + +- (id)initWithMapName:(NSString *)mapName tileCacheKey:(NSString *)tileCacheKey minZoom:(float)minZoom maxZoom:(float)maxZoom +{ + return [self initWithHost:@"localhost" mapName:mapName tileCacheKey:tileCacheKey minZoom:minZoom maxZoom:maxZoom]; +} + +- (id)initWithHost:(NSString *)host mapName:(NSString *)mapName tileCacheKey:(NSString *)tileCacheKey minZoom:(float)minZoom maxZoom:(float)maxZoom +{ + return [super initWithHost:[NSString stringWithFormat:@"%@:20008/tile/%@", host, mapName] tileCacheKey:tileCacheKey minZoom:minZoom maxZoom:maxZoom]; +} + +- (NSURL *)URLForTile:(RMTile)tile +{ + NSURL *tileURL = [super URLForTile:tile]; + + return [NSURL URLWithString:[[tileURL absoluteString] stringByAppendingFormat:@"?updated=%i", (int)[[NSDate date] timeIntervalSince1970]]]; +} + +@end diff --git a/MapView/Map/RMTileSource.h b/MapView/Map/RMTileSource.h index 7faa6ddb6..dd2d49144 100644 --- a/MapView/Map/RMTileSource.h +++ b/MapView/Map/RMTileSource.h @@ -1,7 +1,7 @@ // // RMTileSource.h // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -40,28 +40,70 @@ #pragma mark - +/** The RMTileSource protocol describes the general interface for map tile sources. Whether retrieved from network sources or provided locally, tile sources must provide some specific minimum properties. */ @protocol RMTileSource -// min and max zoom can be set externally since you might want to constrain the zoom level range +/** @name Configuring the Supported Zoom Levels */ + +/** The minimum zoom level supported by the tile source. */ @property (nonatomic, assign) float minZoom; + +/** The maximum zoom level supported by the tile source. */ @property (nonatomic, assign) float maxZoom; +/** A Boolean value indicating whether the tiles from this source should be cached. */ +@property (nonatomic, assign, getter=isCacheable) BOOL cacheable; + +/** A Boolean value indicating whether the tiles from this source are opaque. Setting this correctly is important when using RMCompositeSource so that alpha transparency can be preserved when compositing tile images. */ +@property (nonatomic, assign, getter=isOpaque) BOOL opaque; + @property (nonatomic, readonly) RMFractalTileProjection *mercatorToTileProjection; @property (nonatomic, readonly) RMProjection *projection; +/** @name Querying the Bounds */ + +/** The bounding box that the tile source provides coverage for. */ @property (nonatomic, readonly) RMSphericalTrapezium latitudeLongitudeBoundingBox; +/** @name Configuring Caching */ + +/** A unique string representing the tile source in the cache in order to distinguish it from other tile sources. */ @property (nonatomic, readonly) NSString *uniqueTilecacheKey; + +/** @name Configuring Tile Size */ + +/** The number of pixels along the side of a tile image for this source. */ @property (nonatomic, readonly) NSUInteger tileSideLength; +/** @name Configuring Descriptive Properties */ + +/** A short version of the tile source's name. */ @property (nonatomic, readonly) NSString *shortName; + +/** An extended version of the tile source's description. */ @property (nonatomic, readonly) NSString *longDescription; + +/** A short version of the tile source's attribution string. */ @property (nonatomic, readonly) NSString *shortAttribution; + +/** An extended version of the tile source's attribution string. */ @property (nonatomic, readonly) NSString *longAttribution; #pragma mark - +/** @name Supplying Tile Images */ + +/** Provide an image for a given tile location using a given cache. +* @param tile The map tile in question. +* @param tileCache A tile cache to check first when providing the image. +* @return An image to display. */ - (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache; + +/** Check if the tile source can provide the requested tile. + * @param tile The map tile in question. + * @return A Boolean value indicating whether the tile source can provide the requested tile. */ +- (BOOL)tileSourceHasTile:(RMTile)tile; + - (void)cancelAllDownloads; - (void)didReceiveMemoryWarning; diff --git a/MapView/Map/RMTileSourcesContainer.h b/MapView/Map/RMTileSourcesContainer.h index 847f98875..e0e11accf 100644 --- a/MapView/Map/RMTileSourcesContainer.h +++ b/MapView/Map/RMTileSourcesContainer.h @@ -2,7 +2,7 @@ // RMTileSourcesContainer.h // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -33,8 +33,6 @@ @interface RMTileSourcesContainer : NSObject -@property (nonatomic, readonly) NSArray *tileSources; - // These are the minimum and maximum zoom levels across all tile sources. @property (nonatomic, assign) float minZoom; @property (nonatomic, assign) float maxZoom; @@ -42,13 +40,19 @@ // These properties are (and have to be) equal across all tile sources @property (nonatomic, readonly) NSUInteger tileSideLength; -@property (nonatomic, readonly) RMFractalTileProjection *mercatorToTileProjection; -@property (nonatomic, readonly) RMProjection *projection; +@property (nonatomic, weak, readonly) RMFractalTileProjection *mercatorToTileProjection; +@property (nonatomic, weak, readonly) RMProjection *projection; @property (nonatomic, readonly) RMSphericalTrapezium latitudeLongitudeBoundingBox; #pragma mark - +@property (nonatomic, weak, readonly) NSArray *tileSources; + +- (id )tileSourceForUniqueTilecacheKey:(NSString *)uniqueTilecacheKey; + +#pragma mark - + - (BOOL)setTileSource:(id )tileSource; - (BOOL)setTileSources:(NSArray *)tileSources; diff --git a/MapView/Map/RMTileSourcesContainer.m b/MapView/Map/RMTileSourcesContainer.m index 594f81787..e2cf2648f 100644 --- a/MapView/Map/RMTileSourcesContainer.m +++ b/MapView/Map/RMTileSourcesContainer.m @@ -2,7 +2,7 @@ // RMTileSourcesContainer.m // MapView // -// Copyright (c) 2008-2012, Route-Me Contributors +// Copyright (c) 2008-2013, Route-Me Contributors // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -28,6 +28,8 @@ #import "RMTileSourcesContainer.h" +#import "RMCompositeSource.h" + @implementation RMTileSourcesContainer { NSMutableArray *_tileSources; @@ -39,7 +41,7 @@ @implementation RMTileSourcesContainer RMSphericalTrapezium _latitudeLongitudeBoundingBox; float _minZoom, _maxZoom; - int _tileSideLength; + NSUInteger _tileSideLength; } - (id)init @@ -65,13 +67,33 @@ - (id)init return self; } -- (void)dealloc +#pragma mark - + +- (void)setBoundingBoxFromTilesources { - [_tileSources release]; _tileSources = nil; - [_tileSourcesLock release]; _tileSourcesLock = nil; - [_projection release]; _projection = nil; - [_mercatorToTileProjection release]; _mercatorToTileProjection = nil; - [super dealloc]; + [_tileSourcesLock lock]; + + _latitudeLongitudeBoundingBox = ((RMSphericalTrapezium) { + .northEast = {.latitude = 90.0, .longitude = 180.0}, + .southWest = {.latitude = -90.0, .longitude = -180.0} + }); + + for (id tileSource in _tileSources) + { + RMSphericalTrapezium newLatitudeLongitudeBoundingBox = [tileSource latitudeLongitudeBoundingBox]; + + _latitudeLongitudeBoundingBox = ((RMSphericalTrapezium) { + .northEast = { + .latitude = MIN(_latitudeLongitudeBoundingBox.northEast.latitude, newLatitudeLongitudeBoundingBox.northEast.latitude), + .longitude = MIN(_latitudeLongitudeBoundingBox.northEast.longitude, newLatitudeLongitudeBoundingBox.northEast.longitude)}, + .southWest = { + .latitude = MAX(_latitudeLongitudeBoundingBox.southWest.latitude, newLatitudeLongitudeBoundingBox.southWest.latitude), + .longitude = MAX(_latitudeLongitudeBoundingBox.southWest.longitude, newLatitudeLongitudeBoundingBox.southWest.longitude) + } + }); + } + + [_tileSourcesLock unlock]; } #pragma mark - @@ -84,7 +106,39 @@ - (NSArray *)tileSources tileSources = [_tileSources copy]; [_tileSourcesLock unlock]; - return [tileSources autorelease]; + return tileSources; +} + +- (id )tileSourceForUniqueTilecacheKey:(NSString *)uniqueTilecacheKey +{ + if (!uniqueTilecacheKey) + return nil; + + id result = nil; + + [_tileSourcesLock lock]; + + NSMutableArray *tileSources = [NSMutableArray arrayWithArray:_tileSources]; + + while ([tileSources count]) + { + id currentTileSource = [tileSources objectAtIndex:0]; + [tileSources removeObjectAtIndex:0]; + + if ([currentTileSource isKindOfClass:[RMCompositeSource class]]) + { + [tileSources addObjectsFromArray:[(RMCompositeSource *)currentTileSource tileSources]]; + } + else if ([[currentTileSource uniqueTilecacheKey] isEqualToString:uniqueTilecacheKey]) + { + result = currentTileSource; + break; + } + } + + [_tileSourcesLock unlock]; + + return result; } - (BOOL)setTileSource:(id )tileSource @@ -134,7 +188,7 @@ - (BOOL)addTileSource:(id)tileSource atIndex:(NSUInteger)index if ( ! _projection) { - _projection = [newProjection retain]; + _projection = newProjection; } else if (_projection != newProjection) { @@ -144,7 +198,7 @@ - (BOOL)addTileSource:(id)tileSource atIndex:(NSUInteger)index } if ( ! _mercatorToTileProjection) - _mercatorToTileProjection = [newFractalTileProjection retain]; + _mercatorToTileProjection = newFractalTileProjection; // minZoom and maxZoom are the min and max values of all tile sources, so that individual tilesources // could have a smaller zoom level range @@ -164,6 +218,26 @@ - (BOOL)addTileSource:(id)tileSource atIndex:(NSUInteger)index RMSphericalTrapezium newLatitudeLongitudeBoundingBox = [tileSource latitudeLongitudeBoundingBox]; + double minX1 = _latitudeLongitudeBoundingBox.southWest.longitude; + double minX2 = newLatitudeLongitudeBoundingBox.southWest.longitude; + double maxX1 = _latitudeLongitudeBoundingBox.northEast.longitude; + double maxX2 = newLatitudeLongitudeBoundingBox.northEast.longitude; + + double minY1 = _latitudeLongitudeBoundingBox.southWest.latitude; + double minY2 = newLatitudeLongitudeBoundingBox.southWest.latitude; + double maxY1 = _latitudeLongitudeBoundingBox.northEast.latitude; + double maxY2 = newLatitudeLongitudeBoundingBox.northEast.latitude; + + BOOL intersects = (((minX1 <= minX2 && minX2 <= maxX1) || (minX2 <= minX1 && minX1 <= maxX2)) && + ((minY1 <= minY2 && minY2 <= maxY1) || (minY2 <= minY1 && minY1 <= maxY2))); + + if ( ! intersects) + { + NSLog(@"The bounding box from tilesource '%@' doesn't intersect with the tilesource containers' bounding box", [tileSource shortName]); + [_tileSourcesLock unlock]; + return NO; + } + _latitudeLongitudeBoundingBox = ((RMSphericalTrapezium) { .northEast = { .latitude = MIN(_latitudeLongitudeBoundingBox.northEast.latitude, newLatitudeLongitudeBoundingBox.northEast.latitude), @@ -192,14 +266,14 @@ - (void)removeTileSource:(id )tileSource [_tileSourcesLock lock]; - RMLog(@"Removed the tilesource '%@' from the container", [tileSource shortName]); - [_tileSources removeObject:tileSource]; + RMLog(@"Removed the tilesource '%@' from the container", [tileSource shortName]); + if ([_tileSources count] == 0) - { [self removeAllTileSources]; // cleanup - } + else + [self setBoundingBoxFromTilesources]; [_tileSourcesLock unlock]; } @@ -220,6 +294,11 @@ - (void)removeTileSourceAtIndex:(NSUInteger)index RMLog(@"Removed the tilesource '%@' from the container", [tileSource shortName]); + if ([_tileSources count] == 0) + [self removeAllTileSources]; // cleanup + else + [self setBoundingBoxFromTilesources]; + [_tileSourcesLock unlock]; } @@ -236,7 +315,7 @@ - (void)moveTileSourceAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex return; } - id tileSource = [[_tileSources objectAtIndex:fromIndex] retain]; + id tileSource = [_tileSources objectAtIndex:fromIndex]; [_tileSources removeObjectAtIndex:fromIndex]; if (toIndex >= [_tileSources count]) @@ -244,8 +323,6 @@ - (void)moveTileSourceAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex else [_tileSources insertObject:tileSource atIndex:toIndex]; - [tileSource autorelease]; - [_tileSourcesLock unlock]; } @@ -256,20 +333,17 @@ - (void)removeAllTileSources [self cancelAllDownloads]; [_tileSources removeAllObjects]; - if ([_tileSources count] == 0) - { - [_projection release]; _projection = nil; - [_mercatorToTileProjection release]; _mercatorToTileProjection = nil; + _projection = nil; + _mercatorToTileProjection = nil; - _latitudeLongitudeBoundingBox = ((RMSphericalTrapezium) { - .northEast = {.latitude = 90.0, .longitude = 180.0}, - .southWest = {.latitude = -90.0, .longitude = -180.0} - }); + _latitudeLongitudeBoundingBox = ((RMSphericalTrapezium) { + .northEast = {.latitude = 90.0, .longitude = 180.0}, + .southWest = {.latitude = -90.0, .longitude = -180.0} + }); - _minZoom = kRMTileSourcesContainerMaxZoom; - _maxZoom = kRMTileSourcesContainerMinZoom; - _tileSideLength = 0; - } + _minZoom = kRMTileSourcesContainerMaxZoom; + _maxZoom = kRMTileSourcesContainerMinZoom; + _tileSideLength = 0; [_tileSourcesLock unlock]; } diff --git a/MapView/Map/RMUserLocation.h b/MapView/Map/RMUserLocation.h index ad1653c55..cb09f3a93 100644 --- a/MapView/Map/RMUserLocation.h +++ b/MapView/Map/RMUserLocation.h @@ -2,16 +2,48 @@ // RMUserLocation.h // MapView // -// Created by Justin Miller on 5/8/12. -// Copyright (c) 2012 MapBox / Development Seed. All rights reserved. +// Copyright (c) 2008-2013, 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. #import "RMAnnotation.h" +/** The RMUserLocation class defines a specific type of annotation that identifies the user’s current location. You do not create instances of this class directly. Instead, you retrieve an existing RMUserLocation object from the userLocation property of the map view displayed in your application. */ @interface RMUserLocation : RMAnnotation +/** @name Determining the User’s Position */ + +/** A Boolean value indicating whether the user’s location is currently being updated. (read-only) */ @property (nonatomic, readonly, getter=isUpdating) BOOL updating; + +/** The current location of the device. (read-only) +* +* This property contains `nil` if the map view is not currently showing the user location or if the user’s location has not yet been determined. */ @property (nonatomic, readonly) CLLocation *location; + +/** The heading of the user location. (read-only) +* +* This property is `nil` if the user location tracking mode is not `RMUserTrackingModeFollowWithHeading`. */ @property (nonatomic, readonly) CLHeading *heading; @end diff --git a/MapView/Map/RMUserLocation.m b/MapView/Map/RMUserLocation.m index 37dded5f0..daa825e1f 100644 --- a/MapView/Map/RMUserLocation.m +++ b/MapView/Map/RMUserLocation.m @@ -2,43 +2,83 @@ // RMUserLocation.m // MapView // -// Created by Justin Miller on 5/8/12. -// Copyright (c) 2012 MapBox / Development Seed. All rights reserved. +// Copyright (c) 2008-2013, 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. #import "RMUserLocation.h" #import "RMMarker.h" #import "RMMapView.h" +#define kRMUserLocationAnnotationTypeName @"RMUserLocationAnnotation" + +@interface RMUserLocation () + +@property (nonatomic, assign) BOOL hasCustomLayer; + +@end + +#pragma mark - + @implementation RMUserLocation -@synthesize updating; -@synthesize location; -@synthesize heading; +@synthesize updating = _updating; +@synthesize location = _location; +@synthesize heading = _heading; +@synthesize hasCustomLayer = _hasCustomLayer; - (id)initWithMapView:(RMMapView *)aMapView coordinate:(CLLocationCoordinate2D)aCoordinate andTitle:(NSString *)aTitle { if ( ! (self = [super initWithMapView:aMapView coordinate:aCoordinate andTitle:aTitle])) return nil; - NSAssert([[NSBundle mainBundle] pathForResource:@"TrackingDot" ofType:@"png"], @"Unable to find necessary user location graphical assets (copy from MapView/Map/Resources)"); - - layer = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:@"TrackingDot.png"]]; - - annotationType = [kRMUserLocationAnnotationTypeName retain]; + self.annotationType = kRMUserLocationAnnotationTypeName; - clusteringEnabled = NO; + self.clusteringEnabled = NO; return self; } -- (void)dealloc +- (RMMapLayer *)layer { - [layer release]; layer = nil; - [annotationType release]; annotationType = nil; - [location release]; location = nil; - [heading release]; heading = nil; - [super dealloc]; + if ( ! super.layer) + { + if ([self.mapView.delegate respondsToSelector:@selector(mapView:layerForAnnotation:)]) + super.layer = [self.mapView.delegate mapView:self.mapView layerForAnnotation:self]; + + if (super.layer) + self.hasCustomLayer = YES; + + if ( ! super.layer) + { + if (RMPreVersion7) + super.layer = [[RMMarker alloc] initWithUIImage:[RMMapView resourceImageNamed:@"TrackingDot.png"]]; + else + [self updateTintColor]; + } + } + + return super.layer; } - (BOOL)isUpdating @@ -46,25 +86,84 @@ - (BOOL)isUpdating return (self.mapView.userTrackingMode != RMUserTrackingModeNone); } +- (void)updateTintColor +{ + if ( ! self.hasCustomLayer && CLLocationCoordinate2DIsValid(self.coordinate)) + { + // white dot background with shadow + // + CGFloat whiteWidth = 24.0; + + CGRect rect = CGRectMake(0, 0, whiteWidth * 1.5, whiteWidth * 1.5); + + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSetShadow(context, CGSizeMake(0, 0), whiteWidth / 4.0); + + CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]); + CGContextFillEllipseInRect(context, CGRectMake((rect.size.width - whiteWidth) / 2.0, (rect.size.height - whiteWidth) / 2.0, whiteWidth, whiteWidth)); + + UIImage *whiteBackground = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + + super.layer = [[RMMarker alloc] initWithUIImage:whiteBackground]; + + // pulsing, tinted dot sublayer + // + CGFloat tintedWidth = whiteWidth * 0.7; + + rect = CGRectMake(0, 0, tintedWidth, tintedWidth); + + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + context = UIGraphicsGetCurrentContext(); + + CGContextSetFillColorWithColor(context, [self.mapView.tintColor CGColor]); + CGContextFillEllipseInRect(context, CGRectMake((rect.size.width - tintedWidth) / 2.0, (rect.size.height - tintedWidth) / 2.0, tintedWidth, tintedWidth)); + + UIImage *tintedForeground = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + + CALayer *dotLayer = [CALayer layer]; + dotLayer.bounds = CGRectMake(0, 0, tintedForeground.size.width, tintedForeground.size.height); + dotLayer.contents = (id)[tintedForeground CGImage]; + dotLayer.position = CGPointMake(super.layer.bounds.size.width / 2.0, super.layer.bounds.size.height / 2.0); + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; + animation.repeatCount = MAXFLOAT; + animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; + animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.8, 0.8, 1.0)]; + animation.removedOnCompletion = NO; + animation.autoreverses = YES; + animation.duration = 1.5; + animation.beginTime = CACurrentMediaTime() + 1.0; + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; + + [dotLayer addAnimation:animation forKey:@"animateTransform"]; + + [super.layer addSublayer:dotLayer]; + } +} + - (void)setLocation:(CLLocation *)newLocation { - if ([newLocation distanceFromLocation:location] && newLocation.coordinate.latitude != 0 && newLocation.coordinate.longitude != 0) + if ([newLocation distanceFromLocation:_location] && newLocation.coordinate.latitude != 0 && newLocation.coordinate.longitude != 0) { [self willChangeValueForKey:@"location"]; - [location release]; - location = [newLocation retain]; - self.coordinate = location.coordinate; + _location = newLocation; + self.coordinate = _location.coordinate; [self didChangeValueForKey:@"location"]; } } - (void)setHeading:(CLHeading *)newHeading { - if (newHeading.trueHeading != heading.trueHeading) + if (newHeading.trueHeading != _heading.trueHeading) { [self willChangeValueForKey:@"heading"]; - [heading release]; - heading = [newHeading retain]; + _heading = newHeading; [self didChangeValueForKey:@"heading"]; } } diff --git a/MapView/Map/RMUserTrackingBarButtonItem.h b/MapView/Map/RMUserTrackingBarButtonItem.h index 66a7f0764..25ffab83c 100644 --- a/MapView/Map/RMUserTrackingBarButtonItem.h +++ b/MapView/Map/RMUserTrackingBarButtonItem.h @@ -2,18 +2,47 @@ // RMUserTrackingBarButtonItem.h // MapView // -// Created by Justin Miller on 5/10/12. -// Copyright (c) 2012 MapBox / Development Seed. All rights reserved. +// Copyright (c) 2008-2013, 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. #import @class RMMapView; +/** An RMUserTrackingBarButtonItem object is a specialized bar button item that allows the user to toggle through the user tracking modes. For example, when the user taps the button, the map view toggles between tracking the user with and without heading. The button also reflects the current user tracking mode if set elsewhere. This bar button item is associated to a single map view. */ @interface RMUserTrackingBarButtonItem : UIBarButtonItem +/** @name Initializing */ + +/** Initializes a newly created bar button item with the specified map view. +* @param mapView The map view used by this bar button item. +* @return The initialized bar button item. */ - (id)initWithMapView:(RMMapView *)mapView; -@property (nonatomic, retain) RMMapView *mapView; +/** @name Accessing Properties */ + +/** The map view associated with this bar button item. */ +@property (nonatomic, strong) IBOutlet RMMapView *mapView; @end diff --git a/MapView/Map/RMUserTrackingBarButtonItem.m b/MapView/Map/RMUserTrackingBarButtonItem.m index 9b0fdccde..c11c22131 100644 --- a/MapView/Map/RMUserTrackingBarButtonItem.m +++ b/MapView/Map/RMUserTrackingBarButtonItem.m @@ -2,29 +2,60 @@ // RMUserTrackingBarButtonItem.m // MapView // -// Created by Justin Miller on 5/10/12. -// Copyright (c) 2012 MapBox / Development Seed. All rights reserved. +// Copyright (c) 2008-2013, 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. #import "RMUserTrackingBarButtonItem.h" #import "RMMapView.h" #import "RMUserLocation.h" -typedef enum { - RMUserTrackingButtonStateActivity = 0, - RMUserTrackingButtonStateLocation = 1, - RMUserTrackingButtonStateHeading = 2 +typedef enum : NSUInteger { + RMUserTrackingButtonStateNone = 0, + RMUserTrackingButtonStateActivity = 1, + RMUserTrackingButtonStateLocation = 2, + RMUserTrackingButtonStateHeading = 3 } RMUserTrackingButtonState; +@interface RMMapView (PrivateMethods) + +@property (nonatomic, weak) RMUserTrackingBarButtonItem *userTrackingBarButtonItem; + +@end + +#pragma mark - + @interface RMUserTrackingBarButtonItem () -@property (nonatomic, retain) UISegmentedControl *segmentedControl; -@property (nonatomic, retain) UIImageView *buttonImageView; -@property (nonatomic, retain) UIActivityIndicatorView *activityView; +@property (nonatomic, strong) UISegmentedControl *segmentedControl; +@property (nonatomic, strong) UIImageView *buttonImageView; +@property (nonatomic, strong) UIActivityIndicatorView *activityView; @property (nonatomic, assign) RMUserTrackingButtonState state; +@property (nonatomic, assign) UIViewTintAdjustmentMode tintAdjustmentMode; -- (void)updateAppearance; +- (void)createBarButtonItem; +- (void)updateState; - (void)changeMode:(id)sender; @end @@ -34,64 +65,80 @@ - (void)changeMode:(id)sender; @implementation RMUserTrackingBarButtonItem @synthesize mapView = _mapView; -@synthesize segmentedControl; -@synthesize buttonImageView; -@synthesize activityView; -@synthesize state; +@synthesize segmentedControl = _segmentedControl; +@synthesize buttonImageView = _buttonImageView; +@synthesize activityView = _activityView; +@synthesize state = _state; - (id)initWithMapView:(RMMapView *)mapView { if ( ! (self = [super initWithCustomView:[[UIControl alloc] initWithFrame:CGRectMake(0, 0, 32, 32)]])) return nil; - segmentedControl = [[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@""]] retain]; - segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar; - [segmentedControl setWidth:32.0 forSegmentAtIndex:0]; - segmentedControl.userInteractionEnabled = NO; - segmentedControl.tintColor = self.tintColor; - segmentedControl.center = self.customView.center; + [self createBarButtonItem]; + [self setMapView:mapView]; - [self.customView addSubview:segmentedControl]; + return self; +} - buttonImageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TrackingLocation.png"]] retain]; - buttonImageView.contentMode = UIViewContentModeCenter; - buttonImageView.frame = CGRectMake(0, 0, 32, 32); - buttonImageView.center = self.customView.center; - buttonImageView.userInteractionEnabled = NO; +- (id)initWithCoder:(NSCoder *)aDecoder +{ + if ( ! (self = [super initWithCoder:aDecoder])) + return nil; - [self.customView addSubview:buttonImageView]; + [self setCustomView:[[UIControl alloc] initWithFrame:CGRectMake(0, 0, 32, 32)]]; - activityView = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] retain]; - activityView.hidesWhenStopped = YES; - activityView.center = self.customView.center; - activityView.userInteractionEnabled = NO; + [self createBarButtonItem]; - [self.customView addSubview:activityView]; + return self; +} - [((UIControl *)self.customView) addTarget:self action:@selector(changeMode:) forControlEvents:UIControlEventTouchUpInside]; +- (void)createBarButtonItem +{ + if (RMPreVersion7) + { + _segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@""]]; + _segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar; + [_segmentedControl setWidth:32.0 forSegmentAtIndex:0]; + _segmentedControl.userInteractionEnabled = NO; + _segmentedControl.tintColor = self.tintColor; + _segmentedControl.center = self.customView.center; + + [self.customView addSubview:_segmentedControl]; + } - _mapView = [mapView retain]; + _buttonImageView = [[UIImageView alloc] initWithImage:nil]; + _buttonImageView.contentMode = UIViewContentModeCenter; + _buttonImageView.frame = CGRectMake(0, 0, 32, 32); + _buttonImageView.center = self.customView.center; + _buttonImageView.userInteractionEnabled = NO; - [_mapView addObserver:self forKeyPath:@"userTrackingMode" options:NSKeyValueObservingOptionNew context:nil]; - [_mapView addObserver:self forKeyPath:@"userLocation.location" options:NSKeyValueObservingOptionNew context:nil]; + [self updateImage]; - state = RMUserTrackingButtonStateLocation; + [self.customView addSubview:_buttonImageView]; - [self updateAppearance]; + _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:(RMPreVersion7 ? UIActivityIndicatorViewStyleWhite : UIActivityIndicatorViewStyleGray)]; + _activityView.hidesWhenStopped = YES; + _activityView.center = self.customView.center; + _activityView.userInteractionEnabled = NO; - return self; + [self.customView addSubview:_activityView]; + + [((UIControl *)self.customView) addTarget:self action:@selector(changeMode:) forControlEvents:UIControlEventTouchUpInside]; + + _state = RMUserTrackingButtonStateNone; + + [self updateSize:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSize:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; } - (void)dealloc { - [segmentedControl release]; segmentedControl = nil; - [buttonImageView release]; buttonImageView = nil; - [activityView release]; activityView = nil; [_mapView removeObserver:self forKeyPath:@"userTrackingMode"]; [_mapView removeObserver:self forKeyPath:@"userLocation.location"]; - [_mapView release]; _mapView = nil; - - [super dealloc]; + + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; } #pragma mark - @@ -102,13 +149,14 @@ - (void)setMapView:(RMMapView *)newMapView { [_mapView removeObserver:self forKeyPath:@"userTrackingMode"]; [_mapView removeObserver:self forKeyPath:@"userLocation.location"]; - [_mapView release]; - _mapView = [newMapView retain]; + _mapView = newMapView; [_mapView addObserver:self forKeyPath:@"userTrackingMode" options:NSKeyValueObservingOptionNew context:nil]; [_mapView addObserver:self forKeyPath:@"userLocation.location" options:NSKeyValueObservingOptionNew context:nil]; - [self updateAppearance]; + _mapView.userTrackingBarButtonItem = self; + + [self updateState]; } } @@ -116,23 +164,119 @@ - (void)setTintColor:(UIColor *)newTintColor { [super setTintColor:newTintColor]; - segmentedControl.tintColor = newTintColor; + if (RMPreVersion7) + _segmentedControl.tintColor = newTintColor; + else + [self updateImage]; } #pragma mark - - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - [self updateAppearance]; + [self updateState]; } #pragma mark - -- (void)updateAppearance +- (void)updateSize:(NSNotification *)notification +{ + NSInteger orientation = (notification ? [[notification.userInfo objectForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue] : [[UIApplication sharedApplication] statusBarOrientation]); + + CGFloat dimension = (UIInterfaceOrientationIsPortrait(orientation) ? (RMPostVersion7 ? 36 : 32) : 24); + + self.customView.bounds = _buttonImageView.bounds = _segmentedControl.bounds = CGRectMake(0, 0, dimension, dimension); + [_segmentedControl setWidth:dimension forSegmentAtIndex:0]; + self.width = dimension; + + _segmentedControl.center = _buttonImageView.center = _activityView.center = CGPointMake(dimension / 2, dimension / 2 - (RMPostVersion7 ? 1 : 0)); + + [self updateImage]; +} + +- (void)updateImage +{ + if (RMPreVersion7) + { + if (_mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading) + _buttonImageView.image = [RMMapView resourceImageNamed:@"TrackingHeading.png"]; + else + _buttonImageView.image = [RMMapView resourceImageNamed:@"TrackingLocation.png"]; + } + else + { + CGRect rect = CGRectMake(0, 0, self.customView.bounds.size.width, self.customView.bounds.size.height); + + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + + CGContextRef context = UIGraphicsGetCurrentContext(); + + UIImage *image; + + if (_mapView.userTrackingMode == RMUserTrackingModeNone || ! _mapView) + image = [RMMapView resourceImageNamed:@"TrackingLocationOffMask.png"]; + else if (_mapView.userTrackingMode == RMUserTrackingModeFollow) + image = [RMMapView resourceImageNamed:@"TrackingLocationMask.png"]; + else if (_mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading) + image = [RMMapView resourceImageNamed:@"TrackingHeadingMask.png"]; + + UIGraphicsPushContext(context); + [image drawAtPoint:CGPointMake((rect.size.width - image.size.width) / 2, ((rect.size.height - image.size.height) / 2) + 2)]; + UIGraphicsPopContext(); + + CGContextSetBlendMode(context, kCGBlendModeSourceIn); + CGContextSetFillColorWithColor(context, self.tintColor.CGColor); + CGContextFillRect(context, rect); + + _buttonImageView.image = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + + CABasicAnimation *backgroundColorAnimation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; + CABasicAnimation *cornerRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"]; + + backgroundColorAnimation.duration = cornerRadiusAnimation.duration = 0.25; + + CGColorRef filledColor = [[self.tintColor colorWithAlphaComponent:0.1] CGColor]; + CGColorRef clearColor = [[UIColor clearColor] CGColor]; + + CGFloat onRadius = 4.0; + CGFloat offRadius = 0; + + if (_mapView.userTrackingMode != RMUserTrackingModeNone && self.customView.layer.cornerRadius != onRadius) + { + backgroundColorAnimation.fromValue = (__bridge id)clearColor; + backgroundColorAnimation.toValue = (__bridge id)filledColor; + + cornerRadiusAnimation.fromValue = @(offRadius); + cornerRadiusAnimation.toValue = @(onRadius); + + self.customView.layer.backgroundColor = filledColor; + self.customView.layer.cornerRadius = onRadius; + } + else if (_mapView.userTrackingMode == RMUserTrackingModeNone && self.customView.layer.cornerRadius != offRadius) + { + backgroundColorAnimation.fromValue = (__bridge id)filledColor; + backgroundColorAnimation.toValue = (__bridge id)clearColor; + + cornerRadiusAnimation.fromValue = @(onRadius); + cornerRadiusAnimation.toValue = @(offRadius); + + self.customView.layer.backgroundColor = clearColor; + self.customView.layer.cornerRadius = offRadius; + } + + [self.customView.layer addAnimation:backgroundColorAnimation forKey:@"animateBackgroundColor"]; + [self.customView.layer addAnimation:cornerRadiusAnimation forKey:@"animateCornerRadius"]; + } +} + +- (void)updateState { // "selection" state // - segmentedControl.selectedSegmentIndex = (_mapView.userTrackingMode == RMUserTrackingModeNone ? UISegmentedControlNoSegment : 0); + if (RMPreVersion7) + _segmentedControl.selectedSegmentIndex = (_mapView.userTrackingMode == RMUserTrackingModeNone ? UISegmentedControlNoSegment : 0); // activity/image state // @@ -145,54 +289,85 @@ - (void)updateAppearance options:UIViewAnimationOptionBeginFromCurrentState animations:^(void) { - buttonImageView.transform = CGAffineTransformMakeScale(0.01, 0.01); - activityView.transform = CGAffineTransformMakeScale(0.01, 0.01); + _buttonImageView.transform = CGAffineTransformMakeScale(0.01, 0.01); + _activityView.transform = CGAffineTransformMakeScale(0.01, 0.01); } completion:^(BOOL finished) { - buttonImageView.hidden = YES; + _buttonImageView.hidden = YES; - [activityView startAnimating]; + [_activityView startAnimating]; [UIView animateWithDuration:0.25 animations:^(void) { - buttonImageView.transform = CGAffineTransformIdentity; - activityView.transform = CGAffineTransformIdentity; + _buttonImageView.transform = CGAffineTransformIdentity; + _activityView.transform = CGAffineTransformIdentity; }]; }]; - state = RMUserTrackingButtonStateActivity; + _state = RMUserTrackingButtonStateActivity; } else { - if ((_mapView.userTrackingMode != RMUserTrackingModeFollowWithHeading && state != RMUserTrackingButtonStateLocation) || - (_mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading && state != RMUserTrackingButtonStateHeading)) + if ((_mapView.userTrackingMode == RMUserTrackingModeNone && _state != RMUserTrackingButtonStateNone) || + (_mapView.userTrackingMode == RMUserTrackingModeFollow && _state != RMUserTrackingButtonStateLocation) || + (_mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading && _state != RMUserTrackingButtonStateHeading)) { - // if image state doesn't match mode, update it + // we'll always animate if leaving activity state // + __block BOOL animate = (_state == RMUserTrackingButtonStateActivity); + [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void) { - buttonImageView.transform = CGAffineTransformMakeScale(0.01, 0.01); - activityView.transform = CGAffineTransformMakeScale(0.01, 0.01); + if (_state == RMUserTrackingButtonStateHeading && + _mapView.userTrackingMode != RMUserTrackingModeFollowWithHeading) + { + // coming out of heading mode + // + animate = YES; + } + else if ((_state != RMUserTrackingButtonStateHeading) && + _mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading) + { + // going into heading mode + // + animate = YES; + } + + if (animate) + _buttonImageView.transform = CGAffineTransformMakeScale(0.01, 0.01); + + if (_state == RMUserTrackingButtonStateActivity) + _activityView.transform = CGAffineTransformMakeScale(0.01, 0.01); } completion:^(BOOL finished) { - buttonImageView.image = [UIImage imageNamed:(_mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading ? @"TrackingHeading.png" : @"TrackingLocation.png")]; - buttonImageView.hidden = NO; + [self updateImage]; - [activityView stopAnimating]; + _buttonImageView.hidden = NO; + + if (_state == RMUserTrackingButtonStateActivity) + [_activityView stopAnimating]; [UIView animateWithDuration:0.25 animations:^(void) { - buttonImageView.transform = CGAffineTransformIdentity; - activityView.transform = CGAffineTransformIdentity; + if (animate) + _buttonImageView.transform = CGAffineTransformIdentity; + + if (_state == RMUserTrackingButtonStateActivity) + _activityView.transform = CGAffineTransformIdentity; }]; }]; - state = (_mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading ? RMUserTrackingButtonStateHeading : RMUserTrackingButtonStateLocation); + if (_mapView.userTrackingMode == RMUserTrackingModeNone) + _state = RMUserTrackingButtonStateNone; + else if (_mapView.userTrackingMode == RMUserTrackingModeFollow) + _state = RMUserTrackingButtonStateLocation; + else if (_mapView.userTrackingMode == RMUserTrackingModeFollowWithHeading) + _state = RMUserTrackingButtonStateHeading; } } } @@ -228,7 +403,7 @@ - (void)changeMode:(id)sender } } - [self updateAppearance]; + [self updateState]; } @end diff --git a/MapView/Map/Resources/Compass.png b/MapView/Map/Resources/Compass.png new file mode 100644 index 000000000..fd3afe6f6 Binary files /dev/null and b/MapView/Map/Resources/Compass.png differ diff --git a/MapView/Map/Resources/Compass@2x.png b/MapView/Map/Resources/Compass@2x.png new file mode 100644 index 000000000..58e7e08d2 Binary files /dev/null and b/MapView/Map/Resources/Compass@2x.png differ diff --git a/MapView/Map/Resources/HeadingAngleLarge.png b/MapView/Map/Resources/HeadingAngleLarge.png new file mode 100644 index 000000000..fce6b69ab Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleLarge.png differ diff --git a/MapView/Map/Resources/HeadingAngleLarge@2x.png b/MapView/Map/Resources/HeadingAngleLarge@2x.png new file mode 100644 index 000000000..ec955ecbd Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleLarge@2x.png differ diff --git a/MapView/Map/Resources/HeadingAngleMaskLarge.png b/MapView/Map/Resources/HeadingAngleMaskLarge.png new file mode 100644 index 000000000..430c9b750 Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMaskLarge.png differ diff --git a/MapView/Map/Resources/HeadingAngleMaskLarge@2x.png b/MapView/Map/Resources/HeadingAngleMaskLarge@2x.png new file mode 100644 index 000000000..81c3b0993 Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMaskLarge@2x.png differ diff --git a/MapView/Map/Resources/HeadingAngleMaskMedium.png b/MapView/Map/Resources/HeadingAngleMaskMedium.png new file mode 100644 index 000000000..662d35781 Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMaskMedium.png differ diff --git a/MapView/Map/Resources/HeadingAngleMaskMedium@2x.png b/MapView/Map/Resources/HeadingAngleMaskMedium@2x.png new file mode 100644 index 000000000..0a8ff389d Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMaskMedium@2x.png differ diff --git a/MapView/Map/Resources/HeadingAngleMaskSmall.png b/MapView/Map/Resources/HeadingAngleMaskSmall.png new file mode 100644 index 000000000..2b1ea9f5f Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMaskSmall.png differ diff --git a/MapView/Map/Resources/HeadingAngleMaskSmall@2x.png b/MapView/Map/Resources/HeadingAngleMaskSmall@2x.png new file mode 100644 index 000000000..7fe4eacab Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMaskSmall@2x.png differ diff --git a/MapView/Map/Resources/HeadingAngleMedium.png b/MapView/Map/Resources/HeadingAngleMedium.png new file mode 100644 index 000000000..9c9468a32 Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMedium.png differ diff --git a/MapView/Map/Resources/HeadingAngleMedium@2x.png b/MapView/Map/Resources/HeadingAngleMedium@2x.png new file mode 100644 index 000000000..cc16caf84 Binary files /dev/null and b/MapView/Map/Resources/HeadingAngleMedium@2x.png differ diff --git a/MapView/Map/Resources/LoadingTile.png b/MapView/Map/Resources/LoadingTile.png new file mode 100644 index 000000000..d383b4986 Binary files /dev/null and b/MapView/Map/Resources/LoadingTile.png differ diff --git a/MapView/Map/Resources/LoadingTile6.png b/MapView/Map/Resources/LoadingTile6.png new file mode 100644 index 000000000..841873eda Binary files /dev/null and b/MapView/Map/Resources/LoadingTile6.png differ diff --git a/MapView/Map/Resources/TrackingHeadingMask.png b/MapView/Map/Resources/TrackingHeadingMask.png new file mode 100644 index 000000000..1b406ec49 Binary files /dev/null and b/MapView/Map/Resources/TrackingHeadingMask.png differ diff --git a/MapView/Map/Resources/TrackingHeadingMask@2x.png b/MapView/Map/Resources/TrackingHeadingMask@2x.png new file mode 100644 index 000000000..100501ae5 Binary files /dev/null and b/MapView/Map/Resources/TrackingHeadingMask@2x.png differ diff --git a/MapView/Map/Resources/TrackingHeadingMaskLandscape@2x.png b/MapView/Map/Resources/TrackingHeadingMaskLandscape@2x.png new file mode 100644 index 000000000..c063fd032 Binary files /dev/null and b/MapView/Map/Resources/TrackingHeadingMaskLandscape@2x.png differ diff --git a/MapView/Map/Resources/TrackingLocationMask.png b/MapView/Map/Resources/TrackingLocationMask.png new file mode 100644 index 000000000..ccb5186bd Binary files /dev/null and b/MapView/Map/Resources/TrackingLocationMask.png differ diff --git a/MapView/Map/Resources/TrackingLocationMask@2x.png b/MapView/Map/Resources/TrackingLocationMask@2x.png new file mode 100644 index 000000000..ea036cb59 Binary files /dev/null and b/MapView/Map/Resources/TrackingLocationMask@2x.png differ diff --git a/MapView/Map/Resources/TrackingLocationMaskLandscape@2x.png b/MapView/Map/Resources/TrackingLocationMaskLandscape@2x.png new file mode 100644 index 000000000..ea036cb59 Binary files /dev/null and b/MapView/Map/Resources/TrackingLocationMaskLandscape@2x.png differ diff --git a/MapView/Map/Resources/TrackingLocationOffMask.png b/MapView/Map/Resources/TrackingLocationOffMask.png new file mode 100644 index 000000000..81749e2a7 Binary files /dev/null and b/MapView/Map/Resources/TrackingLocationOffMask.png differ diff --git a/MapView/Map/Resources/TrackingLocationOffMask@2x.png b/MapView/Map/Resources/TrackingLocationOffMask@2x.png new file mode 100644 index 000000000..dc9f6a21f Binary files /dev/null and b/MapView/Map/Resources/TrackingLocationOffMask@2x.png differ diff --git a/MapView/Map/Resources/TrackingLocationOffMaskLandscape@2x.png b/MapView/Map/Resources/TrackingLocationOffMaskLandscape@2x.png new file mode 100644 index 000000000..dc9f6a21f Binary files /dev/null and b/MapView/Map/Resources/TrackingLocationOffMaskLandscape@2x.png differ diff --git a/MapView/Map/Resources/loading.png b/MapView/Map/Resources/loading.png deleted file mode 100644 index 93cafb0f5..000000000 Binary files a/MapView/Map/Resources/loading.png and /dev/null differ diff --git a/MapView/Map/Resources/mapbox-logo.png b/MapView/Map/Resources/mapbox-logo.png new file mode 100644 index 000000000..189630875 Binary files /dev/null and b/MapView/Map/Resources/mapbox-logo.png differ diff --git a/MapView/Map/Resources/mapbox-logo@2x.png b/MapView/Map/Resources/mapbox-logo@2x.png new file mode 100644 index 000000000..15e96b1dd Binary files /dev/null and b/MapView/Map/Resources/mapbox-logo@2x.png differ diff --git a/MapView/Map/Resources/mapbox.png b/MapView/Map/Resources/mapbox.png new file mode 100644 index 000000000..01b5596b6 Binary files /dev/null and b/MapView/Map/Resources/mapbox.png differ diff --git a/MapView/Map/Resources/mapbox@2x.png b/MapView/Map/Resources/mapbox@2x.png new file mode 100644 index 000000000..ff4ef2558 Binary files /dev/null and b/MapView/Map/Resources/mapbox@2x.png differ diff --git a/MapView/Map/Resources/marker-blue-withletter.png b/MapView/Map/Resources/marker-blue-withletter.png deleted file mode 100644 index 32700040f..000000000 Binary files a/MapView/Map/Resources/marker-blue-withletter.png and /dev/null differ diff --git a/MapView/Map/Resources/marker-blue.png b/MapView/Map/Resources/marker-blue.png deleted file mode 100644 index 8a3970fe5..000000000 Binary files a/MapView/Map/Resources/marker-blue.png and /dev/null differ diff --git a/MapView/Map/Resources/marker-red-withletter.png b/MapView/Map/Resources/marker-red-withletter.png deleted file mode 100644 index ce7186c4a..000000000 Binary files a/MapView/Map/Resources/marker-red-withletter.png and /dev/null differ diff --git a/MapView/Map/Resources/marker-red.png b/MapView/Map/Resources/marker-red.png deleted file mode 100644 index 8c7488ab8..000000000 Binary files a/MapView/Map/Resources/marker-red.png and /dev/null differ diff --git a/MapView/Map/SMCalloutView b/MapView/Map/SMCalloutView new file mode 160000 index 000000000..58ce4607e --- /dev/null +++ b/MapView/Map/SMCalloutView @@ -0,0 +1 @@ +Subproject commit 58ce4607e7967e4d22fec6ef6d202433c44dd3a0 diff --git a/MapView/Map/marker-X.png b/MapView/Map/marker-X.png deleted file mode 100644 index e35f589bf..000000000 Binary files a/MapView/Map/marker-X.png and /dev/null differ diff --git a/MapView/MapView.xcodeproj/project.pbxproj b/MapView/MapView.xcodeproj/project.pbxproj index e14d1945e..d0a42e684 100755 --- a/MapView/MapView.xcodeproj/project.pbxproj +++ b/MapView/MapView.xcodeproj/project.pbxproj @@ -8,60 +8,60 @@ /* Begin PBXBuildFile section */ 126693040EB76C0B00E002D5 /* RMConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 126692A00EB75C0A00E002D5 /* RMConfiguration.m */; }; - 1606C9FE13D86BA400547581 /* RMOpenCycleMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1606C9FC13D86BA300547581 /* RMOpenCycleMapSource.h */; }; + 1606C9FE13D86BA400547581 /* RMOpenCycleMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1606C9FC13D86BA300547581 /* RMOpenCycleMapSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1606C9FF13D86BA400547581 /* RMOpenCycleMapSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 1606C9FD13D86BA300547581 /* RMOpenCycleMapSource.m */; }; - 1607499514E120A100D535F5 /* RMGenericMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1607499314E120A100D535F5 /* RMGenericMapSource.h */; }; + 1607499514E120A100D535F5 /* RMGenericMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1607499314E120A100D535F5 /* RMGenericMapSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1607499614E120A100D535F5 /* RMGenericMapSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 1607499414E120A100D535F5 /* RMGenericMapSource.m */; }; - 1609AF8E14068B09008344B7 /* RMMapOverlayView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1609AF8C14068B09008344B7 /* RMMapOverlayView.h */; }; + 1609AF8E14068B09008344B7 /* RMMapOverlayView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1609AF8C14068B09008344B7 /* RMMapOverlayView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1609AF8F14068B09008344B7 /* RMMapOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1609AF8D14068B09008344B7 /* RMMapOverlayView.m */; }; - 160E535713FBDB48004F82F9 /* RMMapTiledLayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 160E535513FBDB47004F82F9 /* RMMapTiledLayerView.h */; }; + 160E535713FBDB48004F82F9 /* RMMapTiledLayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 160E535513FBDB47004F82F9 /* RMMapTiledLayerView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 160E535813FBDB48004F82F9 /* RMMapTiledLayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 160E535613FBDB48004F82F9 /* RMMapTiledLayerView.m */; }; - 160EEDAF13D41DEC007C5501 /* RMAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 160EEDAD13D41DEC007C5501 /* RMAnnotation.h */; }; + 160EEDAF13D41DEC007C5501 /* RMAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 160EEDAD13D41DEC007C5501 /* RMAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 160EEDB013D41DEC007C5501 /* RMAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 160EEDAE13D41DEC007C5501 /* RMAnnotation.m */; }; - 16128CF5148D295300C23C0E /* RMOpenSeaMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16128CF3148D295300C23C0E /* RMOpenSeaMapSource.h */; }; + 16128CF5148D295300C23C0E /* RMOpenSeaMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16128CF3148D295300C23C0E /* RMOpenSeaMapSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; 16128CF6148D295300C23C0E /* RMOpenSeaMapSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 16128CF4148D295300C23C0E /* RMOpenSeaMapSource.m */; }; - 161E563A1594664E00B00BB6 /* RMOpenSeaMapLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 161E56381594664E00B00BB6 /* RMOpenSeaMapLayer.h */; }; + 161E563A1594664E00B00BB6 /* RMOpenSeaMapLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 161E56381594664E00B00BB6 /* RMOpenSeaMapLayer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 161E563B1594664E00B00BB6 /* RMOpenSeaMapLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 161E56391594664E00B00BB6 /* RMOpenSeaMapLayer.m */; }; - 1656665515A1DF7900EF3DC7 /* RMCoordinateGridSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1656665315A1DF7900EF3DC7 /* RMCoordinateGridSource.h */; }; + 1656665515A1DF7900EF3DC7 /* RMCoordinateGridSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1656665315A1DF7900EF3DC7 /* RMCoordinateGridSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1656665615A1DF7900EF3DC7 /* RMCoordinateGridSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 1656665415A1DF7900EF3DC7 /* RMCoordinateGridSource.m */; }; - 16EC85D2133CA6C300219947 /* RMAbstractMercatorTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16EC85CC133CA6C300219947 /* RMAbstractMercatorTileSource.h */; }; + 16E5A63A15E531F200C92A5A /* RMCompositeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16E5A63815E531F200C92A5A /* RMCompositeSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 16E5A63B15E531F200C92A5A /* RMCompositeSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 16E5A63915E531F200C92A5A /* RMCompositeSource.m */; }; + 16EC85D2133CA6C300219947 /* RMAbstractMercatorTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16EC85CC133CA6C300219947 /* RMAbstractMercatorTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16EC85D3133CA6C300219947 /* RMAbstractMercatorTileSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 16EC85CD133CA6C300219947 /* RMAbstractMercatorTileSource.m */; }; - 16EC85D4133CA6C300219947 /* RMAbstractWebMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16EC85CE133CA6C300219947 /* RMAbstractWebMapSource.h */; }; + 16EC85D4133CA6C300219947 /* RMAbstractWebMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16EC85CE133CA6C300219947 /* RMAbstractWebMapSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16EC85D5133CA6C300219947 /* RMAbstractWebMapSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 16EC85CF133CA6C300219947 /* RMAbstractWebMapSource.m */; }; - 16EC85D6133CA6C300219947 /* RMCacheObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 16EC85D0133CA6C300219947 /* RMCacheObject.h */; }; + 16EC85D6133CA6C300219947 /* RMCacheObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 16EC85D0133CA6C300219947 /* RMCacheObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16EC85D7133CA6C300219947 /* RMCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 16EC85D1133CA6C300219947 /* RMCacheObject.m */; }; - 16F3581B15864135003A3AD9 /* RMMapScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = 16F3581915864135003A3AD9 /* RMMapScrollView.h */; }; + 16F3581B15864135003A3AD9 /* RMMapScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = 16F3581915864135003A3AD9 /* RMMapScrollView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 16F3581C15864135003A3AD9 /* RMMapScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 16F3581A15864135003A3AD9 /* RMMapScrollView.m */; }; - 16F98C961590CFF000FF90CE /* RMShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 16F98C941590CFF000FF90CE /* RMShape.h */; }; + 16F98C961590CFF000FF90CE /* RMShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 16F98C941590CFF000FF90CE /* RMShape.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16F98C971590CFF000FF90CE /* RMShape.m in Sources */ = {isa = PBXBuildFile; fileRef = 16F98C951590CFF000FF90CE /* RMShape.m */; }; - 16FAB66413E03D55002F4E1C /* RMQuadTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 16FAB66213E03D55002F4E1C /* RMQuadTree.h */; }; + 16FAB66413E03D55002F4E1C /* RMQuadTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 16FAB66213E03D55002F4E1C /* RMQuadTree.h */; settings = {ATTRIBUTES = (Private, ); }; }; 16FAB66513E03D55002F4E1C /* RMQuadTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 16FAB66313E03D55002F4E1C /* RMQuadTree.m */; }; - 16FBF07615936BF1004ECAD1 /* RMTileSourcesContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 16FBF07415936BF1004ECAD1 /* RMTileSourcesContainer.h */; }; + 16FBF07615936BF1004ECAD1 /* RMTileSourcesContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 16FBF07415936BF1004ECAD1 /* RMTileSourcesContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 16FBF07715936BF1004ECAD1 /* RMTileSourcesContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 16FBF07515936BF1004ECAD1 /* RMTileSourcesContainer.m */; }; - 16FFF2CB14E3DBF700A170EC /* RMMapQuestOpenAerialSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16FFF2C914E3DBF700A170EC /* RMMapQuestOpenAerialSource.h */; }; + 16FFF2CB14E3DBF700A170EC /* RMMapQuestOpenAerialSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 16FFF2C914E3DBF700A170EC /* RMMapQuestOpenAerialSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; 16FFF2CC14E3DBF700A170EC /* RMMapQuestOpenAerialSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 16FFF2CA14E3DBF700A170EC /* RMMapQuestOpenAerialSource.m */; }; - 17F02BB11319BA4B00260C6B /* RouteMe.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F02BB01319BA4B00260C6B /* RouteMe.h */; }; 23A0AAE90EB90A99003A4521 /* RMFoundation.c in Sources */ = {isa = PBXBuildFile; fileRef = 23A0AAE80EB90A99003A4521 /* RMFoundation.c */; }; - 23A0AAEB0EB90AA6003A4521 /* RMFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 23A0AAEA0EB90AA6003A4521 /* RMFoundation.h */; }; - 25757F4F1291C8640083D504 /* RMCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = 25757F4D1291C8640083D504 /* RMCircle.h */; }; + 23A0AAEB0EB90AA6003A4521 /* RMFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 23A0AAEA0EB90AA6003A4521 /* RMFoundation.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 25757F4F1291C8640083D504 /* RMCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = 25757F4D1291C8640083D504 /* RMCircle.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25757F501291C8640083D504 /* RMCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 25757F4E1291C8640083D504 /* RMCircle.m */; }; - 3849889C0F6F758100496293 /* libProj4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 38D818500F6F67B90034598B /* libProj4.a */; }; - 96492C400FA8AD3400EBA6D2 /* RMGlobalConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 96492C3F0FA8AD3400EBA6D2 /* RMGlobalConstants.h */; }; - B1EB26C610B5D8E6009F8658 /* RMNotifications.h in Headers */ = {isa = PBXBuildFile; fileRef = B1EB26C510B5D8E6009F8658 /* RMNotifications.h */; }; - B8474BA40EB40094006A0BC1 /* RMDatabaseCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */; }; + 96492C400FA8AD3400EBA6D2 /* RMGlobalConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 96492C3F0FA8AD3400EBA6D2 /* RMGlobalConstants.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B1EB26C610B5D8E6009F8658 /* RMNotifications.h in Headers */ = {isa = PBXBuildFile; fileRef = B1EB26C510B5D8E6009F8658 /* RMNotifications.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B8474BA40EB40094006A0BC1 /* RMDatabaseCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8474BA50EB40094006A0BC1 /* RMDatabaseCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */; }; B8474BC10EB4019A006A0BC1 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */; }; - B8800FF20EC3A239003E9CDD /* RMMapViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 12F2031E0EBB65E9003D7B6B /* RMMapViewDelegate.h */; }; - B8800FF30EC3A23D003E9CDD /* RMConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1266929F0EB75C0A00E002D5 /* RMConfiguration.h */; }; - B8C974220E8A19B2007D16AD /* RMProjection.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64E30E80E73F001663B6 /* RMProjection.h */; }; - B8C974230E8A19B2007D16AD /* RMTileCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D00E80E73F001663B6 /* RMTileCache.h */; }; - B8C974250E8A19B2007D16AD /* RMOpenStreetMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64ED0E80E73F001663B6 /* RMOpenStreetMapSource.h */; settings = {ATTRIBUTES = (); }; }; - B8C974260E8A19B2007D16AD /* RMTile.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D60E80E73F001663B6 /* RMTile.h */; }; - B8C974270E8A19B2007D16AD /* RMPixel.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64B60E80E73F001663B6 /* RMPixel.h */; }; - B8C9742A0E8A19B2007D16AD /* RMTileImage.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D80E80E73F001663B6 /* RMTileImage.h */; }; - B8C9742B0E8A19B2007D16AD /* RMMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D20E80E73F001663B6 /* RMMemoryCache.h */; }; - B8C9742D0E8A19B2007D16AD /* RMFractalTileProjection.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64E90E80E73F001663B6 /* RMFractalTileProjection.h */; }; - B8C9742F0E8A19B2007D16AD /* RMMapLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = B86F26AC0E87442C007A3773 /* RMMapLayer.h */; }; + B8800FF20EC3A239003E9CDD /* RMMapViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 12F2031E0EBB65E9003D7B6B /* RMMapViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8800FF30EC3A23D003E9CDD /* RMConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1266929F0EB75C0A00E002D5 /* RMConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8C974220E8A19B2007D16AD /* RMProjection.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64E30E80E73F001663B6 /* RMProjection.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B8C974230E8A19B2007D16AD /* RMTileCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D00E80E73F001663B6 /* RMTileCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8C974250E8A19B2007D16AD /* RMOpenStreetMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64ED0E80E73F001663B6 /* RMOpenStreetMapSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8C974260E8A19B2007D16AD /* RMTile.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D60E80E73F001663B6 /* RMTile.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B8C974270E8A19B2007D16AD /* RMPixel.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64B60E80E73F001663B6 /* RMPixel.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B8C9742A0E8A19B2007D16AD /* RMTileImage.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D80E80E73F001663B6 /* RMTileImage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B8C9742B0E8A19B2007D16AD /* RMMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64D20E80E73F001663B6 /* RMMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8C9742D0E8A19B2007D16AD /* RMFractalTileProjection.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64E90E80E73F001663B6 /* RMFractalTileProjection.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B8C9742F0E8A19B2007D16AD /* RMMapLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = B86F26AC0E87442C007A3773 /* RMMapLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8C9743F0E8A19B2007D16AD /* RMTileImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D90E80E73F001663B6 /* RMTileImage.m */; }; B8C974400E8A19B2007D16AD /* RMTile.c in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D70E80E73F001663B6 /* RMTile.c */; }; B8C974410E8A19B2007D16AD /* RMOpenStreetMapSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64EE0E80E73F001663B6 /* RMOpenStreetMapSource.m */; }; @@ -75,52 +75,114 @@ B8C974520E8A19B2007D16AD /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B83E65630E80E81C001663B6 /* CoreLocation.framework */; }; B8C974530E8A19B2007D16AD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; B8C974540E8A19B2007D16AD /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B83E65680E80E830001663B6 /* QuartzCore.framework */; }; - B8C974620E8A19E8007D16AD /* RMTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64EC0E80E73F001663B6 /* RMTileSource.h */; }; - B8C9746B0E8A1A50007D16AD /* RMMapView.h in Headers */ = {isa = PBXBuildFile; fileRef = B8C974690E8A1A50007D16AD /* RMMapView.h */; }; + B8C974620E8A19E8007D16AD /* RMTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E64EC0E80E73F001663B6 /* RMTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8C9746B0E8A1A50007D16AD /* RMMapView.h in Headers */ = {isa = PBXBuildFile; fileRef = B8C974690E8A1A50007D16AD /* RMMapView.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8C9746C0E8A1A50007D16AD /* RMMapView.m in Sources */ = {isa = PBXBuildFile; fileRef = B8C9746A0E8A1A50007D16AD /* RMMapView.m */; }; - B8CEB1C50ED5A3480014C431 /* RMPath.h in Headers */ = {isa = PBXBuildFile; fileRef = B8CEB1C30ED5A3480014C431 /* RMPath.h */; }; - B8CEB1C60ED5A3480014C431 /* RMPath.m in Sources */ = {isa = PBXBuildFile; fileRef = B8CEB1C40ED5A3480014C431 /* RMPath.m */; }; B8F3FC610EA2B382004D8F85 /* RMMapLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = B8F3FC600EA2B382004D8F85 /* RMMapLayer.m */; }; - B8F3FC640EA2E792004D8F85 /* RMMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = B8F3FC620EA2E792004D8F85 /* RMMarker.h */; }; + B8F3FC640EA2E792004D8F85 /* RMMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = B8F3FC620EA2E792004D8F85 /* RMMarker.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8F3FC650EA2E792004D8F85 /* RMMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = B8F3FC630EA2E792004D8F85 /* RMMarker.m */; }; D1437B36122869E400888DAE /* RMDBMapSource.m in Sources */ = {isa = PBXBuildFile; fileRef = D1437B32122869E400888DAE /* RMDBMapSource.m */; }; - D1437B37122869E400888DAE /* RMDBMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D1437B33122869E400888DAE /* RMDBMapSource.h */; }; - DD2B374514CF8041008DE8CB /* FMDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2B373F14CF8041008DE8CB /* FMDatabase.h */; }; - DD2B374614CF8041008DE8CB /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2B374014CF8041008DE8CB /* FMDatabase.m */; }; - DD2B374714CF8041008DE8CB /* FMDatabaseAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2B374114CF8041008DE8CB /* FMDatabaseAdditions.h */; }; - DD2B374814CF8041008DE8CB /* FMDatabaseAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2B374214CF8041008DE8CB /* FMDatabaseAdditions.m */; }; - DD2B374914CF8041008DE8CB /* FMResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2B374314CF8041008DE8CB /* FMResultSet.h */; }; - DD2B374A14CF8041008DE8CB /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2B374414CF8041008DE8CB /* FMResultSet.m */; }; - DD2B374F14CF814F008DE8CB /* FMDatabasePool.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2B374B14CF814F008DE8CB /* FMDatabasePool.h */; }; - DD2B375014CF814F008DE8CB /* FMDatabasePool.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2B374C14CF814F008DE8CB /* FMDatabasePool.m */; }; - DD2B375114CF814F008DE8CB /* FMDatabaseQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2B374D14CF814F008DE8CB /* FMDatabaseQueue.h */; }; - DD2B375214CF814F008DE8CB /* FMDatabaseQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2B374E14CF814F008DE8CB /* FMDatabaseQueue.m */; }; - DD2B375514CF8197008DE8CB /* RMMBTilesSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2B375314CF8197008DE8CB /* RMMBTilesSource.h */; }; + D1437B37122869E400888DAE /* RMDBMapSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D1437B33122869E400888DAE /* RMDBMapSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DD07A23817F3AF9800E420B2 /* HeadingAngleMaskSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = DD07A23217F3AF9800E420B2 /* HeadingAngleMaskSmall.png */; }; + DD07A23917F3AF9800E420B2 /* HeadingAngleMaskMedium.png in Resources */ = {isa = PBXBuildFile; fileRef = DD07A23317F3AF9800E420B2 /* HeadingAngleMaskMedium.png */; }; + DD07A23A17F3AF9800E420B2 /* HeadingAngleMaskLarge.png in Resources */ = {isa = PBXBuildFile; fileRef = DD07A23417F3AF9800E420B2 /* HeadingAngleMaskLarge.png */; }; + DD07A23B17F3AF9800E420B2 /* HeadingAngleMaskSmall@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD07A23517F3AF9800E420B2 /* HeadingAngleMaskSmall@2x.png */; }; + DD07A23C17F3AF9800E420B2 /* HeadingAngleMaskMedium@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD07A23617F3AF9800E420B2 /* HeadingAngleMaskMedium@2x.png */; }; + DD07A23D17F3AF9800E420B2 /* HeadingAngleMaskLarge@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD07A23717F3AF9800E420B2 /* HeadingAngleMaskLarge@2x.png */; }; + DD1985C1165C5F6400DF667F /* RMTileMillSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD1985BF165C5F6400DF667F /* RMTileMillSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DD1985C2165C5F6400DF667F /* RMTileMillSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1985C0165C5F6400DF667F /* RMTileMillSource.m */; }; + DD1E3C6E161F954F004FC649 /* SMCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DD1E3C6C161F954F004FC649 /* SMCalloutView.h */; }; + DD1E3C6F161F954F004FC649 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1E3C6D161F954F004FC649 /* SMCalloutView.m */; }; + DD2B375514CF8197008DE8CB /* RMMBTilesSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2B375314CF8197008DE8CB /* RMMBTilesSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; DD2B375614CF8197008DE8CB /* RMMBTilesSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2B375414CF8197008DE8CB /* RMMBTilesSource.m */; }; - DD8CDB4A14E0507100B73EB9 /* RMMapQuestOSMSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD8CDB4814E0507100B73EB9 /* RMMapQuestOSMSource.h */; }; + DD36766B17D94F980001F27B /* mapbox-logo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD36766A17D94F980001F27B /* mapbox-logo@2x.png */; }; + DD3BEF7915913C55007892D8 /* RMAttributionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DD3BEF7715913C55007892D8 /* RMAttributionViewController.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DD3BEF7A15913C55007892D8 /* RMAttributionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3BEF7815913C55007892D8 /* RMAttributionViewController.m */; }; + DD4195C9162356900049E6BA /* RMBingSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD4195C7162356900049E6BA /* RMBingSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DD4195CA162356900049E6BA /* RMBingSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4195C8162356900049E6BA /* RMBingSource.m */; }; + DD41960116250ED40049E6BA /* RMTileCacheDownloadOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DD4195FF16250ED40049E6BA /* RMTileCacheDownloadOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DD41960216250ED40049E6BA /* RMTileCacheDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DD41960016250ED40049E6BA /* RMTileCacheDownloadOperation.m */; }; + DD4BE198161CE296003EF677 /* Mapbox.h in Headers */ = {isa = PBXBuildFile; fileRef = DD4BE197161CE296003EF677 /* Mapbox.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DD56B94F1961E23F00706C67 /* FMDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = DD56B9441961E23F00706C67 /* FMDatabase.h */; }; + DD56B9501961E23F00706C67 /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = DD56B9451961E23F00706C67 /* FMDatabase.m */; }; + DD56B9511961E23F00706C67 /* FMDatabaseAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DD56B9461961E23F00706C67 /* FMDatabaseAdditions.h */; }; + DD56B9521961E23F00706C67 /* FMDatabaseAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DD56B9471961E23F00706C67 /* FMDatabaseAdditions.m */; }; + DD56B9531961E23F00706C67 /* FMDatabasePool.h in Headers */ = {isa = PBXBuildFile; fileRef = DD56B9481961E23F00706C67 /* FMDatabasePool.h */; }; + DD56B9541961E23F00706C67 /* FMDatabasePool.m in Sources */ = {isa = PBXBuildFile; fileRef = DD56B9491961E23F00706C67 /* FMDatabasePool.m */; }; + DD56B9551961E23F00706C67 /* FMDatabaseQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = DD56B94A1961E23F00706C67 /* FMDatabaseQueue.h */; }; + DD56B9561961E23F00706C67 /* FMDatabaseQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = DD56B94B1961E23F00706C67 /* FMDatabaseQueue.m */; }; + DD56B9571961E23F00706C67 /* FMDB.h in Headers */ = {isa = PBXBuildFile; fileRef = DD56B94C1961E23F00706C67 /* FMDB.h */; }; + DD56B9581961E23F00706C67 /* FMResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = DD56B94D1961E23F00706C67 /* FMResultSet.h */; }; + DD56B9591961E23F00706C67 /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = DD56B94E1961E23F00706C67 /* FMResultSet.m */; }; + DD5F5F9518C7C03C0085DE98 /* SMClassicCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DD5F5F9318C7C03C0085DE98 /* SMClassicCalloutView.h */; }; + DD5F5F9618C7C03C0085DE98 /* SMClassicCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD5F5F9418C7C03C0085DE98 /* SMClassicCalloutView.m */; }; + DD5FA1EB15E2B020004EB6C5 /* RMLoadingTileView.h in Headers */ = {isa = PBXBuildFile; fileRef = DD5FA1E915E2B020004EB6C5 /* RMLoadingTileView.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DD5FA1EC15E2B020004EB6C5 /* RMLoadingTileView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD5FA1EA15E2B020004EB6C5 /* RMLoadingTileView.m */; }; + DD63175F17D1506D008CA79B /* RMGreatCircleAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = DD63175D17D1506D008CA79B /* RMGreatCircleAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DD63176017D1506D008CA79B /* RMGreatCircleAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DD63175E17D1506D008CA79B /* RMGreatCircleAnnotation.m */; }; + DD63176317D15EB5008CA79B /* RMCircleAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = DD63176117D15EB5008CA79B /* RMCircleAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DD63176417D15EB5008CA79B /* RMCircleAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DD63176217D15EB5008CA79B /* RMCircleAnnotation.m */; }; + DD7C7E38164C894F0021CCA5 /* RMStaticMapView.h in Headers */ = {isa = PBXBuildFile; fileRef = DD7C7E36164C894F0021CCA5 /* RMStaticMapView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DD7C7E39164C894F0021CCA5 /* RMStaticMapView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7C7E37164C894F0021CCA5 /* RMStaticMapView.m */; }; + DD8CDB4A14E0507100B73EB9 /* RMMapQuestOSMSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD8CDB4814E0507100B73EB9 /* RMMapQuestOSMSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; DD8CDB4B14E0507100B73EB9 /* RMMapQuestOSMSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8CDB4914E0507100B73EB9 /* RMMapQuestOSMSource.m */; }; - DD8FD7541559E4A40044D96F /* RMUserLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = DD8FD7521559E4A40044D96F /* RMUserLocation.h */; }; + DD8FD7541559E4A40044D96F /* RMUserLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = DD8FD7521559E4A40044D96F /* RMUserLocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; DD8FD7551559E4A40044D96F /* RMUserLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8FD7531559E4A40044D96F /* RMUserLocation.m */; }; - DD98B6FA14D76B930092882F /* RMMapBoxSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DD98B6F814D76B930092882F /* RMMapBoxSource.h */; }; - DD98B6FB14D76B930092882F /* RMMapBoxSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD98B6F914D76B930092882F /* RMMapBoxSource.m */; }; - DDA6B8BD155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h in Headers */ = {isa = PBXBuildFile; fileRef = DDA6B8BB155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h */; }; + DD932BB3165C287000D69D49 /* mapbox.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BA5165C287000D69D49 /* mapbox.png */; }; + DD932BB4165C287000D69D49 /* mapbox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BA6165C287000D69D49 /* mapbox@2x.png */; }; + DD932BB5165C287000D69D49 /* TrackingDot.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BA7165C287000D69D49 /* TrackingDot.png */; }; + DD932BB6165C287000D69D49 /* TrackingDot@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BA8165C287000D69D49 /* TrackingDot@2x.png */; }; + DD932BB7165C287000D69D49 /* HeadingAngleSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BA9165C287000D69D49 /* HeadingAngleSmall.png */; }; + DD932BB8165C287000D69D49 /* HeadingAngleSmall@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BAA165C287000D69D49 /* HeadingAngleSmall@2x.png */; }; + DD932BB9165C287000D69D49 /* LoadingTile.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BAB165C287000D69D49 /* LoadingTile.png */; }; + DD932BBB165C287000D69D49 /* TrackingDotHalo.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BAD165C287000D69D49 /* TrackingDotHalo.png */; }; + DD932BBC165C287000D69D49 /* TrackingDotHalo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BAE165C287000D69D49 /* TrackingDotHalo@2x.png */; }; + DD932BBD165C287000D69D49 /* TrackingHeading.png in Resources */ = {isa = PBXBuildFile; fileRef = DD932BAF165C287000D69D49 /* TrackingHeading.png */; }; + 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 */; settings = {ATTRIBUTES = (Public, ); }; }; + DD98B6FB14D76B930092882F /* RMMapboxSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD98B6F914D76B930092882F /* RMMapboxSource.m */; }; + DDA257011798A95600BBB325 /* TrackingLocationOffMaskLandscape@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256F61798A95600BBB325 /* TrackingLocationOffMaskLandscape@2x.png */; }; + DDA257021798A95600BBB325 /* TrackingLocationOffMask@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256F71798A95600BBB325 /* TrackingLocationOffMask@2x.png */; }; + DDA257031798A95600BBB325 /* TrackingLocationMaskLandscape@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256F81798A95600BBB325 /* TrackingLocationMaskLandscape@2x.png */; }; + DDA257041798A95600BBB325 /* TrackingLocationMask@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256F91798A95600BBB325 /* TrackingLocationMask@2x.png */; }; + DDA257051798A95600BBB325 /* TrackingHeadingMaskLandscape@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256FA1798A95600BBB325 /* TrackingHeadingMaskLandscape@2x.png */; }; + DDA257061798A95600BBB325 /* TrackingHeadingMask@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256FB1798A95600BBB325 /* TrackingHeadingMask@2x.png */; }; + DDA257071798A95600BBB325 /* Compass@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256FC1798A95600BBB325 /* Compass@2x.png */; }; + DDA257081798A95600BBB325 /* Compass.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256FD1798A95600BBB325 /* Compass.png */; }; + DDA257091798A95600BBB325 /* TrackingHeadingMask.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256FE1798A95600BBB325 /* TrackingHeadingMask.png */; }; + DDA2570A1798A95600BBB325 /* TrackingLocationOffMask.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA256FF1798A95600BBB325 /* TrackingLocationOffMask.png */; }; + DDA2570B1798A95600BBB325 /* TrackingLocationMask.png in Resources */ = {isa = PBXBuildFile; fileRef = DDA257001798A95600BBB325 /* TrackingLocationMask.png */; }; + DDA6B8BD155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h in Headers */ = {isa = PBXBuildFile; fileRef = DDA6B8BB155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; DDA6B8BE155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.m in Sources */ = {isa = PBXBuildFile; fileRef = DDA6B8BC155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.m */; }; + DDC4BED5152E3BD700089409 /* RMInteractiveSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DDC4BED3152E3BD700089409 /* RMInteractiveSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDC4BEF2152E3FAE00089409 /* RMInteractiveSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DDC4BED4152E3BD700089409 /* RMInteractiveSource.m */; }; + DDC8D28717E92ED100A4FB32 /* LoadingTile6.png in Resources */ = {isa = PBXBuildFile; fileRef = DDC8D28517E92ED100A4FB32 /* LoadingTile6.png */; }; + DDE357E71651F570001DB842 /* RMPointAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = DDE357E51651F570001DB842 /* RMPointAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDE357E81651F570001DB842 /* RMPointAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE357E61651F570001DB842 /* RMPointAnnotation.m */; }; + DDE357F0165223A3001DB842 /* RMShapeAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = DDE357EE165223A3001DB842 /* RMShapeAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDE357F1165223A3001DB842 /* RMShapeAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE357EF165223A3001DB842 /* RMShapeAnnotation.m */; }; + DDE357F416522661001DB842 /* RMPolylineAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = DDE357F216522661001DB842 /* RMPolylineAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDE357F516522661001DB842 /* RMPolylineAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE357F316522661001DB842 /* RMPolylineAnnotation.m */; }; + DDE357F816522CD8001DB842 /* RMPolygonAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = DDE357F616522CD8001DB842 /* RMPolygonAnnotation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDE357F916522CD8001DB842 /* RMPolygonAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE357F716522CD8001DB842 /* RMPolygonAnnotation.m */; }; + DDE68E5A17D94C0500F1E869 /* mapbox-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = DDE68E5917D94C0500F1E869 /* mapbox-logo.png */; }; + DDEDBBD01A81864800646DBB /* libGRMustache7-iOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDEDBBCF1A81864800646DBB /* libGRMustache7-iOS.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 38D8184F0F6F67B90034598B /* PBXContainerItemProxy */ = { + DD6A838F1644A2810097F31F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = B83E654A0E80E7A8001663B6 /* Proj4.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = D2AAC07E0554694100DB518D; - remoteInfo = Proj4; - }; - B8C974150E8A19B2007D16AD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = B83E654A0E80E7A8001663B6 /* Proj4.xcodeproj */; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = D2AAC07D0554694100DB518D; - remoteInfo = Proj4; + remoteGlobalIDString = DD6A83741644A20C0097F31F; + remoteInfo = Resources; }; /* End PBXContainerItemProxy section */ @@ -144,6 +206,8 @@ 161E56391594664E00B00BB6 /* RMOpenSeaMapLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMOpenSeaMapLayer.m; sourceTree = ""; }; 1656665315A1DF7900EF3DC7 /* RMCoordinateGridSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCoordinateGridSource.h; sourceTree = ""; }; 1656665415A1DF7900EF3DC7 /* RMCoordinateGridSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCoordinateGridSource.m; sourceTree = ""; }; + 16E5A63815E531F200C92A5A /* RMCompositeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCompositeSource.h; sourceTree = ""; }; + 16E5A63915E531F200C92A5A /* RMCompositeSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCompositeSource.m; sourceTree = ""; }; 16EC85CC133CA6C300219947 /* RMAbstractMercatorTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMAbstractMercatorTileSource.h; sourceTree = ""; }; 16EC85CD133CA6C300219947 /* RMAbstractMercatorTileSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMAbstractMercatorTileSource.m; sourceTree = ""; }; 16EC85CE133CA6C300219947 /* RMAbstractWebMapSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMAbstractWebMapSource.h; sourceTree = ""; }; @@ -160,8 +224,7 @@ 16FBF07515936BF1004ECAD1 /* RMTileSourcesContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMTileSourcesContainer.m; sourceTree = ""; }; 16FFF2C914E3DBF700A170EC /* RMMapQuestOpenAerialSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMapQuestOpenAerialSource.h; sourceTree = ""; }; 16FFF2CA14E3DBF700A170EC /* RMMapQuestOpenAerialSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMapQuestOpenAerialSource.m; sourceTree = ""; }; - 17F02BB01319BA4B00260C6B /* RouteMe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RouteMe.h; sourceTree = ""; }; - 17F31EFA1331050A00122B16 /* libMapView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMapView.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 17F31EFA1331050A00122B16 /* libMapbox.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMapbox.a; sourceTree = BUILT_PRODUCTS_DIR; }; 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 23A0AAE80EB90A99003A4521 /* RMFoundation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = RMFoundation.c; sourceTree = ""; }; @@ -169,13 +232,8 @@ 25757F4D1291C8640083D504 /* RMCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCircle.h; sourceTree = ""; }; 25757F4E1291C8640083D504 /* RMCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCircle.m; sourceTree = ""; }; 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 2B2BADD60FA3B45A00EE37AA /* marker-X.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-X.png"; path = "Map/marker-X.png"; sourceTree = ""; }; - 2B8C8A230F8EB855002E8CF3 /* RouteMeTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RouteMeTests.h; path = UnitTesting/RouteMeTests.h; sourceTree = ""; }; - 2B8C8A240F8EB855002E8CF3 /* RouteMeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RouteMeTests.m; path = UnitTesting/RouteMeTests.m; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* MapView_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapView_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* MapView_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapView_Prefix.pch; sourceTree = SOURCE_ROOT; }; 96492C3F0FA8AD3400EBA6D2 /* RMGlobalConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMGlobalConstants.h; sourceTree = ""; }; - 966504690F6869810036562A /* loading.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = loading.png; path = Map/Resources/loading.png; sourceTree = ""; }; B1EB26C510B5D8E6009F8658 /* RMNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMNotifications.h; sourceTree = ""; }; B83E64B60E80E73F001663B6 /* RMPixel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMPixel.h; sourceTree = ""; }; B83E64B70E80E73F001663B6 /* RMPixel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = RMPixel.c; sourceTree = ""; }; @@ -194,59 +252,112 @@ B83E64EC0E80E73F001663B6 /* RMTileSource.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = RMTileSource.h; sourceTree = ""; }; B83E64ED0E80E73F001663B6 /* RMOpenStreetMapSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMOpenStreetMapSource.h; sourceTree = ""; }; B83E64EE0E80E73F001663B6 /* RMOpenStreetMapSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMOpenStreetMapSource.m; sourceTree = ""; }; - B83E654A0E80E7A8001663B6 /* Proj4.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Proj4.xcodeproj; path = ../Proj4/Proj4.xcodeproj; sourceTree = SOURCE_ROOT; }; B83E65590E80E7EB001663B6 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; B83E65630E80E81C001663B6 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; B83E65680E80E830001663B6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMDatabaseCache.h; sourceTree = ""; }; B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMDatabaseCache.m; sourceTree = ""; }; B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - B8474C6D0EB53A41006A0BC1 /* marker-blue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-blue.png"; path = "Map/Resources/marker-blue.png"; sourceTree = ""; }; - B8474C6E0EB53A41006A0BC1 /* marker-red-withletter.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-red-withletter.png"; path = "Map/Resources/marker-red-withletter.png"; sourceTree = ""; }; - B8474C6F0EB53A41006A0BC1 /* marker-red.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-red.png"; path = "Map/Resources/marker-red.png"; sourceTree = ""; }; - B8474C700EB53A41006A0BC1 /* marker-blue-withletter.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-blue-withletter.png"; path = "Map/Resources/marker-blue-withletter.png"; sourceTree = ""; }; B86F26AC0E87442C007A3773 /* RMMapLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMapLayer.h; sourceTree = ""; }; - B86F26E10E877802007A3773 /* DesktopMapView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DesktopMapView-Info.plist"; sourceTree = ""; }; - B8C9740E0E8A198F007D16AD /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = Map/README.txt; sourceTree = ""; }; B8C974690E8A1A50007D16AD /* RMMapView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMapView.h; sourceTree = ""; }; B8C9746A0E8A1A50007D16AD /* RMMapView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMapView.m; sourceTree = ""; }; - B8CEB1C30ED5A3480014C431 /* RMPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMPath.h; sourceTree = ""; }; - B8CEB1C40ED5A3480014C431 /* RMPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMPath.m; sourceTree = ""; }; B8F3FC600EA2B382004D8F85 /* RMMapLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMapLayer.m; sourceTree = ""; }; B8F3FC620EA2E792004D8F85 /* RMMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMarker.h; sourceTree = ""; }; B8F3FC630EA2E792004D8F85 /* RMMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMarker.m; sourceTree = ""; }; D1437B32122869E400888DAE /* RMDBMapSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMDBMapSource.m; sourceTree = ""; }; D1437B33122869E400888DAE /* RMDBMapSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMDBMapSource.h; sourceTree = ""; }; - DD2B373F14CF8041008DE8CB /* FMDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = ""; }; - DD2B374014CF8041008DE8CB /* FMDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabase.m; sourceTree = ""; }; - DD2B374114CF8041008DE8CB /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseAdditions.h; sourceTree = ""; }; - DD2B374214CF8041008DE8CB /* FMDatabaseAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseAdditions.m; sourceTree = ""; }; - DD2B374314CF8041008DE8CB /* FMResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = ""; }; - DD2B374414CF8041008DE8CB /* FMResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = ""; }; - DD2B374B14CF814F008DE8CB /* FMDatabasePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabasePool.h; sourceTree = ""; }; - DD2B374C14CF814F008DE8CB /* FMDatabasePool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabasePool.m; sourceTree = ""; }; - DD2B374D14CF814F008DE8CB /* FMDatabaseQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseQueue.h; sourceTree = ""; }; - DD2B374E14CF814F008DE8CB /* FMDatabaseQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseQueue.m; sourceTree = ""; }; + DD07A23217F3AF9800E420B2 /* HeadingAngleMaskSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleMaskSmall.png; path = Map/Resources/HeadingAngleMaskSmall.png; sourceTree = ""; }; + DD07A23317F3AF9800E420B2 /* HeadingAngleMaskMedium.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleMaskMedium.png; path = Map/Resources/HeadingAngleMaskMedium.png; sourceTree = ""; }; + DD07A23417F3AF9800E420B2 /* HeadingAngleMaskLarge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleMaskLarge.png; path = Map/Resources/HeadingAngleMaskLarge.png; sourceTree = ""; }; + DD07A23517F3AF9800E420B2 /* HeadingAngleMaskSmall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleMaskSmall@2x.png"; path = "Map/Resources/HeadingAngleMaskSmall@2x.png"; sourceTree = ""; }; + DD07A23617F3AF9800E420B2 /* HeadingAngleMaskMedium@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleMaskMedium@2x.png"; path = "Map/Resources/HeadingAngleMaskMedium@2x.png"; sourceTree = ""; }; + DD07A23717F3AF9800E420B2 /* HeadingAngleMaskLarge@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleMaskLarge@2x.png"; path = "Map/Resources/HeadingAngleMaskLarge@2x.png"; sourceTree = ""; }; + DD1985BF165C5F6400DF667F /* RMTileMillSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMTileMillSource.h; sourceTree = ""; }; + DD1985C0165C5F6400DF667F /* RMTileMillSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMTileMillSource.m; sourceTree = ""; }; + DD1E3C6C161F954F004FC649 /* SMCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SMCalloutView.h; path = SMCalloutView/SMCalloutView.h; sourceTree = ""; }; + DD1E3C6D161F954F004FC649 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SMCalloutView.m; path = SMCalloutView/SMCalloutView.m; sourceTree = ""; }; DD2B375314CF8197008DE8CB /* RMMBTilesSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMBTilesSource.h; sourceTree = ""; }; DD2B375414CF8197008DE8CB /* RMMBTilesSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMBTilesSource.m; sourceTree = ""; }; + DD36766A17D94F980001F27B /* mapbox-logo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "mapbox-logo@2x.png"; path = "Map/Resources/mapbox-logo@2x.png"; sourceTree = ""; }; + DD3BEF7715913C55007892D8 /* RMAttributionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMAttributionViewController.h; sourceTree = ""; }; + DD3BEF7815913C55007892D8 /* RMAttributionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMAttributionViewController.m; sourceTree = ""; }; + DD4195C7162356900049E6BA /* RMBingSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMBingSource.h; sourceTree = ""; }; + DD4195C8162356900049E6BA /* RMBingSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMBingSource.m; sourceTree = ""; }; + DD4195FF16250ED40049E6BA /* RMTileCacheDownloadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMTileCacheDownloadOperation.h; sourceTree = ""; }; + DD41960016250ED40049E6BA /* RMTileCacheDownloadOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMTileCacheDownloadOperation.m; sourceTree = ""; }; + DD4BE197161CE296003EF677 /* Mapbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mapbox.h; sourceTree = ""; }; + DD56B9441961E23F00706C67 /* FMDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMDatabase.h; path = fmdb/FMDatabase.h; sourceTree = ""; }; + DD56B9451961E23F00706C67 /* FMDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FMDatabase.m; path = fmdb/FMDatabase.m; sourceTree = ""; }; + DD56B9461961E23F00706C67 /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMDatabaseAdditions.h; path = fmdb/FMDatabaseAdditions.h; sourceTree = ""; }; + DD56B9471961E23F00706C67 /* FMDatabaseAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FMDatabaseAdditions.m; path = fmdb/FMDatabaseAdditions.m; sourceTree = ""; }; + DD56B9481961E23F00706C67 /* FMDatabasePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMDatabasePool.h; path = fmdb/FMDatabasePool.h; sourceTree = ""; }; + DD56B9491961E23F00706C67 /* FMDatabasePool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FMDatabasePool.m; path = fmdb/FMDatabasePool.m; sourceTree = ""; }; + DD56B94A1961E23F00706C67 /* FMDatabaseQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMDatabaseQueue.h; path = fmdb/FMDatabaseQueue.h; sourceTree = ""; }; + DD56B94B1961E23F00706C67 /* FMDatabaseQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FMDatabaseQueue.m; path = fmdb/FMDatabaseQueue.m; sourceTree = ""; }; + DD56B94C1961E23F00706C67 /* FMDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMDB.h; path = fmdb/FMDB.h; sourceTree = ""; }; + DD56B94D1961E23F00706C67 /* FMResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMResultSet.h; path = fmdb/FMResultSet.h; sourceTree = ""; }; + DD56B94E1961E23F00706C67 /* FMResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FMResultSet.m; path = fmdb/FMResultSet.m; sourceTree = ""; }; + DD5F5F9318C7C03C0085DE98 /* SMClassicCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SMClassicCalloutView.h; path = SMCalloutView/SMClassicCalloutView.h; sourceTree = ""; }; + DD5F5F9418C7C03C0085DE98 /* SMClassicCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SMClassicCalloutView.m; path = SMCalloutView/SMClassicCalloutView.m; sourceTree = ""; }; + DD5FA1E915E2B020004EB6C5 /* RMLoadingTileView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMLoadingTileView.h; sourceTree = ""; }; + DD5FA1EA15E2B020004EB6C5 /* RMLoadingTileView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMLoadingTileView.m; sourceTree = ""; }; + DD63175D17D1506D008CA79B /* RMGreatCircleAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMGreatCircleAnnotation.h; sourceTree = ""; }; + DD63175E17D1506D008CA79B /* RMGreatCircleAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMGreatCircleAnnotation.m; sourceTree = ""; }; + DD63176117D15EB5008CA79B /* RMCircleAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMCircleAnnotation.h; sourceTree = ""; }; + DD63176217D15EB5008CA79B /* RMCircleAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMCircleAnnotation.m; sourceTree = ""; }; + DD6A83751644A20C0097F31F /* Mapbox.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Mapbox.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + DD7C7E36164C894F0021CCA5 /* RMStaticMapView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMStaticMapView.h; sourceTree = ""; }; + DD7C7E37164C894F0021CCA5 /* RMStaticMapView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMStaticMapView.m; sourceTree = ""; }; DD8CDB4814E0507100B73EB9 /* RMMapQuestOSMSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMapQuestOSMSource.h; sourceTree = ""; }; DD8CDB4914E0507100B73EB9 /* RMMapQuestOSMSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMapQuestOSMSource.m; sourceTree = ""; }; DD8FD7521559E4A40044D96F /* RMUserLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMUserLocation.h; sourceTree = ""; }; DD8FD7531559E4A40044D96F /* RMUserLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMUserLocation.m; sourceTree = ""; }; - DD8FD7631559EE120044D96F /* HeadingAngleSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleSmall.png; path = Resources/HeadingAngleSmall.png; sourceTree = ""; }; - DD8FD7641559EE120044D96F /* HeadingAngleSmall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleSmall@2x.png"; path = "Resources/HeadingAngleSmall@2x.png"; sourceTree = ""; }; - DD8FD7651559EE120044D96F /* TrackingDot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingDot.png; path = Resources/TrackingDot.png; sourceTree = ""; }; - DD8FD7661559EE120044D96F /* TrackingDot@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingDot@2x.png"; path = "Resources/TrackingDot@2x.png"; sourceTree = ""; }; - DD8FD7691559EE120044D96F /* TrackingDotHalo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingDotHalo@2x.png"; path = "Resources/TrackingDotHalo@2x.png"; sourceTree = ""; }; - DD8FD76C1559EE120044D96F /* TrackingDotHalo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingDotHalo.png; path = Resources/TrackingDotHalo.png; sourceTree = ""; }; - DD98B6F814D76B930092882F /* RMMapBoxSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMapBoxSource.h; sourceTree = ""; }; - DD98B6F914D76B930092882F /* RMMapBoxSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMapBoxSource.m; sourceTree = ""; }; + DD932BA5165C287000D69D49 /* mapbox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = mapbox.png; path = Map/Resources/mapbox.png; sourceTree = ""; }; + DD932BA6165C287000D69D49 /* mapbox@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "mapbox@2x.png"; path = "Map/Resources/mapbox@2x.png"; sourceTree = ""; }; + DD932BA7165C287000D69D49 /* TrackingDot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingDot.png; path = Map/Resources/TrackingDot.png; sourceTree = ""; }; + DD932BA8165C287000D69D49 /* TrackingDot@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingDot@2x.png"; path = "Map/Resources/TrackingDot@2x.png"; sourceTree = ""; }; + DD932BA9165C287000D69D49 /* HeadingAngleSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleSmall.png; path = Map/Resources/HeadingAngleSmall.png; sourceTree = ""; }; + DD932BAA165C287000D69D49 /* HeadingAngleSmall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleSmall@2x.png"; path = "Map/Resources/HeadingAngleSmall@2x.png"; sourceTree = ""; }; + DD932BAB165C287000D69D49 /* LoadingTile.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LoadingTile.png; path = Map/Resources/LoadingTile.png; sourceTree = ""; }; + DD932BAD165C287000D69D49 /* TrackingDotHalo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingDotHalo.png; path = Map/Resources/TrackingDotHalo.png; sourceTree = ""; }; + DD932BAE165C287000D69D49 /* TrackingDotHalo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingDotHalo@2x.png"; path = "Map/Resources/TrackingDotHalo@2x.png"; sourceTree = ""; }; + DD932BAF165C287000D69D49 /* TrackingHeading.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingHeading.png; path = Map/Resources/TrackingHeading.png; sourceTree = ""; }; + DD932BB0165C287000D69D49 /* TrackingHeading@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingHeading@2x.png"; path = "Map/Resources/TrackingHeading@2x.png"; sourceTree = ""; }; + DD932BB1165C287000D69D49 /* TrackingLocation.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingLocation.png; path = Map/Resources/TrackingLocation.png; sourceTree = ""; }; + DD932BB2165C287000D69D49 /* TrackingLocation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocation@2x.png"; path = "Map/Resources/TrackingLocation@2x.png"; sourceTree = ""; }; + DD94D46616C2E064003D5739 /* HeadingAngleLarge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleLarge.png; path = Map/Resources/HeadingAngleLarge.png; sourceTree = ""; }; + DD94D46716C2E064003D5739 /* HeadingAngleLarge@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleLarge@2x.png"; path = "Map/Resources/HeadingAngleLarge@2x.png"; sourceTree = ""; }; + DD94D46816C2E064003D5739 /* HeadingAngleMedium.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleMedium.png; path = Map/Resources/HeadingAngleMedium.png; sourceTree = ""; }; + DD94D46916C2E064003D5739 /* HeadingAngleMedium@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleMedium@2x.png"; path = "Map/Resources/HeadingAngleMedium@2x.png"; sourceTree = ""; }; + DD97C11516489678007C4652 /* libProj4.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libProj4.a; path = ../Proj4/libProj4.a; sourceTree = ""; }; + DD98B6F814D76B930092882F /* RMMapboxSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMMapboxSource.h; sourceTree = ""; }; + DD98B6F914D76B930092882F /* RMMapboxSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMMapboxSource.m; sourceTree = ""; }; + DDA256F61798A95600BBB325 /* TrackingLocationOffMaskLandscape@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocationOffMaskLandscape@2x.png"; path = "Map/Resources/TrackingLocationOffMaskLandscape@2x.png"; sourceTree = ""; }; + DDA256F71798A95600BBB325 /* TrackingLocationOffMask@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocationOffMask@2x.png"; path = "Map/Resources/TrackingLocationOffMask@2x.png"; sourceTree = ""; }; + DDA256F81798A95600BBB325 /* TrackingLocationMaskLandscape@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocationMaskLandscape@2x.png"; path = "Map/Resources/TrackingLocationMaskLandscape@2x.png"; sourceTree = ""; }; + DDA256F91798A95600BBB325 /* TrackingLocationMask@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocationMask@2x.png"; path = "Map/Resources/TrackingLocationMask@2x.png"; sourceTree = ""; }; + DDA256FA1798A95600BBB325 /* TrackingHeadingMaskLandscape@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingHeadingMaskLandscape@2x.png"; path = "Map/Resources/TrackingHeadingMaskLandscape@2x.png"; sourceTree = ""; }; + DDA256FB1798A95600BBB325 /* TrackingHeadingMask@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingHeadingMask@2x.png"; path = "Map/Resources/TrackingHeadingMask@2x.png"; sourceTree = ""; }; + DDA256FC1798A95600BBB325 /* Compass@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Compass@2x.png"; path = "Map/Resources/Compass@2x.png"; sourceTree = ""; }; + DDA256FD1798A95600BBB325 /* Compass.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Compass.png; path = Map/Resources/Compass.png; sourceTree = ""; }; + DDA256FE1798A95600BBB325 /* TrackingHeadingMask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingHeadingMask.png; path = Map/Resources/TrackingHeadingMask.png; sourceTree = ""; }; + DDA256FF1798A95600BBB325 /* TrackingLocationOffMask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingLocationOffMask.png; path = Map/Resources/TrackingLocationOffMask.png; sourceTree = ""; }; + DDA257001798A95600BBB325 /* TrackingLocationMask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingLocationMask.png; path = Map/Resources/TrackingLocationMask.png; sourceTree = ""; }; DDA6B8BB155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMUserTrackingBarButtonItem.h; sourceTree = ""; }; DDA6B8BC155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMUserTrackingBarButtonItem.m; sourceTree = ""; }; - DDA6B8C0155CAB9A003DB5D8 /* TrackingLocation.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingLocation.png; path = Resources/TrackingLocation.png; sourceTree = ""; }; - DDA6B8C1155CAB9A003DB5D8 /* TrackingLocation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocation@2x.png"; path = "Resources/TrackingLocation@2x.png"; sourceTree = ""; }; - DDA6B8C2155CAB9A003DB5D8 /* TrackingHeading.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingHeading.png; path = Resources/TrackingHeading.png; sourceTree = ""; }; - DDA6B8C3155CAB9A003DB5D8 /* TrackingHeading@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingHeading@2x.png"; path = "Resources/TrackingHeading@2x.png"; sourceTree = ""; }; + DDC4BED3152E3BD700089409 /* RMInteractiveSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMInteractiveSource.h; sourceTree = ""; }; + DDC4BED4152E3BD700089409 /* RMInteractiveSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMInteractiveSource.m; sourceTree = ""; }; + DDC8D28517E92ED100A4FB32 /* LoadingTile6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LoadingTile6.png; path = Map/Resources/LoadingTile6.png; sourceTree = ""; }; + DDE357E51651F570001DB842 /* RMPointAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMPointAnnotation.h; sourceTree = ""; }; + DDE357E61651F570001DB842 /* RMPointAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMPointAnnotation.m; sourceTree = ""; }; + DDE357EE165223A3001DB842 /* RMShapeAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMShapeAnnotation.h; sourceTree = ""; }; + DDE357EF165223A3001DB842 /* RMShapeAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMShapeAnnotation.m; sourceTree = ""; }; + DDE357F216522661001DB842 /* RMPolylineAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMPolylineAnnotation.h; sourceTree = ""; }; + DDE357F316522661001DB842 /* RMPolylineAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMPolylineAnnotation.m; sourceTree = ""; }; + DDE357F616522CD8001DB842 /* RMPolygonAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMPolygonAnnotation.h; sourceTree = ""; }; + DDE357F716522CD8001DB842 /* RMPolygonAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMPolygonAnnotation.m; sourceTree = ""; }; + DDE68E5917D94C0500F1E869 /* mapbox-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "mapbox-logo.png"; path = "Map/Resources/mapbox-logo.png"; sourceTree = ""; }; + DDEDBBCF1A81864800646DBB /* libGRMustache7-iOS.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libGRMustache7-iOS.a"; path = "GRMustache/lib/libGRMustache7-iOS.a"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -260,7 +371,8 @@ B8C974530E8A19B2007D16AD /* UIKit.framework in Frameworks */, B8C974540E8A19B2007D16AD /* QuartzCore.framework in Frameworks */, B8474BC10EB4019A006A0BC1 /* libsqlite3.dylib in Frameworks */, - 3849889C0F6F758100496293 /* libProj4.a in Frameworks */, + DDEDBBD01A81864800646DBB /* libGRMustache7-iOS.a in Frameworks */, + DD97C11616489678007C4652 /* libProj4.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -276,17 +388,19 @@ name = Configuration; sourceTree = ""; }; - 16EC85CB133CA69A00219947 /* Map sources */ = { + 16EC85CB133CA69A00219947 /* Map Sources */ = { isa = PBXGroup; children = ( + 16E5A63815E531F200C92A5A /* RMCompositeSource.h */, + 16E5A63915E531F200C92A5A /* RMCompositeSource.m */, 1656665315A1DF7900EF3DC7 /* RMCoordinateGridSource.h */, 1656665415A1DF7900EF3DC7 /* RMCoordinateGridSource.m */, D1437B33122869E400888DAE /* RMDBMapSource.h */, D1437B32122869E400888DAE /* RMDBMapSource.m */, 1607499314E120A100D535F5 /* RMGenericMapSource.h */, 1607499414E120A100D535F5 /* RMGenericMapSource.m */, - DD98B6F814D76B930092882F /* RMMapBoxSource.h */, - DD98B6F914D76B930092882F /* RMMapBoxSource.m */, + DD98B6F814D76B930092882F /* RMMapboxSource.h */, + DD98B6F914D76B930092882F /* RMMapboxSource.m */, 16FFF2C914E3DBF700A170EC /* RMMapQuestOpenAerialSource.h */, 16FFF2CA14E3DBF700A170EC /* RMMapQuestOpenAerialSource.m */, DD8CDB4814E0507100B73EB9 /* RMMapQuestOSMSource.h */, @@ -301,14 +415,19 @@ 161E56391594664E00B00BB6 /* RMOpenSeaMapLayer.m */, B83E64ED0E80E73F001663B6 /* RMOpenStreetMapSource.h */, B83E64EE0E80E73F001663B6 /* RMOpenStreetMapSource.m */, + DD4195C7162356900049E6BA /* RMBingSource.h */, + DD4195C8162356900049E6BA /* RMBingSource.m */, + DD1985BF165C5F6400DF667F /* RMTileMillSource.h */, + DD1985C0165C5F6400DF667F /* RMTileMillSource.m */, ); - name = "Map sources"; + name = "Map Sources"; sourceTree = ""; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( - 17F31EFA1331050A00122B16 /* libMapView.a */, + 17F31EFA1331050A00122B16 /* libMapbox.a */, + DD6A83751644A20C0097F31F /* Mapbox.bundle */, ); name = Products; sourceTree = ""; @@ -316,13 +435,10 @@ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( - 2BF0E4540F73119C0095A926 /* Documentation */, - 2B246B230F8AE20300A7D55D /* Testing */, B8C9740D0E8A196E007D16AD /* Map */, - B83E67570E80F3FB001663B6 /* Resources */, + DD932BC2165C294100D69D49 /* Externals */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, - 32CA4F630368D1EE00C91783 /* MapView_Prefix.pch */, ); name = CustomTemplate; sourceTree = ""; @@ -330,44 +446,18 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( - B83E654A0E80E7A8001663B6 /* Proj4.xcodeproj */, - B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */, B83E65590E80E7EB001663B6 /* CoreFoundation.framework */, + 288765A40DF7441C002DB57D /* CoreGraphics.framework */, B83E65630E80E81C001663B6 /* CoreLocation.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, B83E65680E80E830001663B6 /* QuartzCore.framework */, 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */, ); name = Frameworks; sourceTree = ""; }; - 2B246B230F8AE20300A7D55D /* Testing */ = { - isa = PBXGroup; - children = ( - 2B8C8A230F8EB855002E8CF3 /* RouteMeTests.h */, - 2B8C8A240F8EB855002E8CF3 /* RouteMeTests.m */, - ); - name = Testing; - sourceTree = ""; - }; - 2BF0E4540F73119C0095A926 /* Documentation */ = { - isa = PBXGroup; - children = ( - B8C9740E0E8A198F007D16AD /* README.txt */, - ); - name = Documentation; - sourceTree = ""; - }; - 38D8184C0F6F67B90034598B /* Products */ = { - isa = PBXGroup; - children = ( - 38D818500F6F67B90034598B /* libProj4.a */, - ); - name = Products; - sourceTree = ""; - }; - B83E64CE0E80E73F001663B6 /* Tile Layer & Overlay */ = { + B83E64CE0E80E73F001663B6 /* Tile & Overlay Rendering */ = { isa = PBXGroup; children = ( B83E64D80E80E73F001663B6 /* RMTileImage.h */, @@ -378,8 +468,10 @@ 1609AF8D14068B09008344B7 /* RMMapOverlayView.m */, 16F3581915864135003A3AD9 /* RMMapScrollView.h */, 16F3581A15864135003A3AD9 /* RMMapScrollView.m */, + DD5FA1E915E2B020004EB6C5 /* RMLoadingTileView.h */, + DD5FA1EA15E2B020004EB6C5 /* RMLoadingTileView.m */, ); - name = "Tile Layer & Overlay"; + name = "Tile & Overlay Rendering"; sourceTree = ""; }; B83E64CF0E80E73F001663B6 /* Tile Cache */ = { @@ -389,6 +481,8 @@ 16EC85D1133CA6C300219947 /* RMCacheObject.m */, B83E64D00E80E73F001663B6 /* RMTileCache.h */, B83E64D10E80E73F001663B6 /* RMTileCache.m */, + DD4195FF16250ED40049E6BA /* RMTileCacheDownloadOperation.h */, + DD41960016250ED40049E6BA /* RMTileCacheDownloadOperation.m */, B83E64D20E80E73F001663B6 /* RMMemoryCache.h */, B83E64D30E80E73F001663B6 /* RMMemoryCache.m */, B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */, @@ -408,10 +502,11 @@ name = Projections; sourceTree = ""; }; - B83E64EB0E80E73F001663B6 /* Tile Source */ = { + B83E64EB0E80E73F001663B6 /* Tile Sources */ = { isa = PBXGroup; children = ( - 16EC85CB133CA69A00219947 /* Map sources */, + 16EC85CB133CA69A00219947 /* Map Sources */, + DDC4BED1152E3BC200089409 /* Interactivity */, B83E64EC0E80E73F001663B6 /* RMTileSource.h */, 16FBF07415936BF1004ECAD1 /* RMTileSourcesContainer.h */, 16FBF07515936BF1004ECAD1 /* RMTileSourcesContainer.m */, @@ -420,81 +515,76 @@ 16EC85CE133CA6C300219947 /* RMAbstractWebMapSource.h */, 16EC85CF133CA6C300219947 /* RMAbstractWebMapSource.m */, ); - name = "Tile Source"; - sourceTree = ""; - }; - B83E67570E80F3FB001663B6 /* Resources */ = { - isa = PBXGroup; - children = ( - 8D1107310486CEB800E47090 /* Info.plist */, - B86F26E10E877802007A3773 /* DesktopMapView-Info.plist */, - 966504690F6869810036562A /* loading.png */, - 2B2BADD60FA3B45A00EE37AA /* marker-X.png */, - B8474C6D0EB53A41006A0BC1 /* marker-blue.png */, - B8474C6E0EB53A41006A0BC1 /* marker-red-withletter.png */, - B8474C6F0EB53A41006A0BC1 /* marker-red.png */, - B8474C700EB53A41006A0BC1 /* marker-blue-withletter.png */, - ); - name = Resources; + name = "Tile Sources"; sourceTree = ""; }; B8474B8C0EB40094006A0BC1 /* FMDB */ = { isa = PBXGroup; children = ( - DD2B373F14CF8041008DE8CB /* FMDatabase.h */, - DD2B374014CF8041008DE8CB /* FMDatabase.m */, - DD2B374114CF8041008DE8CB /* FMDatabaseAdditions.h */, - DD2B374214CF8041008DE8CB /* FMDatabaseAdditions.m */, - DD2B374314CF8041008DE8CB /* FMResultSet.h */, - DD2B374414CF8041008DE8CB /* FMResultSet.m */, - DD2B374B14CF814F008DE8CB /* FMDatabasePool.h */, - DD2B374C14CF814F008DE8CB /* FMDatabasePool.m */, - DD2B374D14CF814F008DE8CB /* FMDatabaseQueue.h */, - DD2B374E14CF814F008DE8CB /* FMDatabaseQueue.m */, + DD56B9441961E23F00706C67 /* FMDatabase.h */, + DD56B9451961E23F00706C67 /* FMDatabase.m */, + DD56B9461961E23F00706C67 /* FMDatabaseAdditions.h */, + DD56B9471961E23F00706C67 /* FMDatabaseAdditions.m */, + DD56B9481961E23F00706C67 /* FMDatabasePool.h */, + DD56B9491961E23F00706C67 /* FMDatabasePool.m */, + DD56B94A1961E23F00706C67 /* FMDatabaseQueue.h */, + DD56B94B1961E23F00706C67 /* FMDatabaseQueue.m */, + DD56B94C1961E23F00706C67 /* FMDB.h */, + DD56B94D1961E23F00706C67 /* FMResultSet.h */, + DD56B94E1961E23F00706C67 /* FMResultSet.m */, ); name = FMDB; - path = FMDB/src; + path = Map/FMDB/src; sourceTree = ""; }; - B86F26A80E8742ED007A3773 /* Markers and other layers */ = { + B86F26A80E8742ED007A3773 /* Annotation Layers */ = { isa = PBXGroup; children = ( 160EEDAD13D41DEC007C5501 /* RMAnnotation.h */, 160EEDAE13D41DEC007C5501 /* RMAnnotation.m */, + DDE357E51651F570001DB842 /* RMPointAnnotation.h */, + DDE357E61651F570001DB842 /* RMPointAnnotation.m */, + DDE357EE165223A3001DB842 /* RMShapeAnnotation.h */, + DDE357EF165223A3001DB842 /* RMShapeAnnotation.m */, + DDE357F216522661001DB842 /* RMPolylineAnnotation.h */, + DDE357F316522661001DB842 /* RMPolylineAnnotation.m */, + DDE357F616522CD8001DB842 /* RMPolygonAnnotation.h */, + DDE357F716522CD8001DB842 /* RMPolygonAnnotation.m */, + DD63176117D15EB5008CA79B /* RMCircleAnnotation.h */, + DD63176217D15EB5008CA79B /* RMCircleAnnotation.m */, + DD63175D17D1506D008CA79B /* RMGreatCircleAnnotation.h */, + DD63175E17D1506D008CA79B /* RMGreatCircleAnnotation.m */, 16FAB66213E03D55002F4E1C /* RMQuadTree.h */, 16FAB66313E03D55002F4E1C /* RMQuadTree.m */, B86F26AC0E87442C007A3773 /* RMMapLayer.h */, B8F3FC600EA2B382004D8F85 /* RMMapLayer.m */, B8F3FC620EA2E792004D8F85 /* RMMarker.h */, B8F3FC630EA2E792004D8F85 /* RMMarker.m */, - B8CEB1C30ED5A3480014C431 /* RMPath.h */, - B8CEB1C40ED5A3480014C431 /* RMPath.m */, 16F98C941590CFF000FF90CE /* RMShape.h */, 16F98C951590CFF000FF90CE /* RMShape.m */, 25757F4D1291C8640083D504 /* RMCircle.h */, 25757F4E1291C8640083D504 /* RMCircle.m */, ); - name = "Markers and other layers"; + name = "Annotation Layers"; sourceTree = ""; }; B8C9740D0E8A196E007D16AD /* Map */ = { isa = PBXGroup; children = ( - 17F02BB01319BA4B00260C6B /* RouteMe.h */, - 96492C3F0FA8AD3400EBA6D2 /* RMGlobalConstants.h */, - B1EB26C510B5D8E6009F8658 /* RMNotifications.h */, + DD4BE197161CE296003EF677 /* Mapbox.h */, B8C974690E8A1A50007D16AD /* RMMapView.h */, B8C9746A0E8A1A50007D16AD /* RMMapView.m */, 12F2031E0EBB65E9003D7B6B /* RMMapViewDelegate.h */, - B8C974B30E8A23C5007D16AD /* Coordinate Systems */, - B83E64E20E80E73F001663B6 /* Projections */, + DD7C7E36164C894F0021CCA5 /* RMStaticMapView.h */, + DD7C7E37164C894F0021CCA5 /* RMStaticMapView.m */, + B83E64EB0E80E73F001663B6 /* Tile Sources */, B83E64CF0E80E73F001663B6 /* Tile Cache */, - B83E64EB0E80E73F001663B6 /* Tile Source */, - B83E64CE0E80E73F001663B6 /* Tile Layer & Overlay */, - B86F26A80E8742ED007A3773 /* Markers and other layers */, + B86F26A80E8742ED007A3773 /* Annotation Layers */, DD8FD7571559ED930044D96F /* User Location */, + DD3BEF71159134E0007892D8 /* Attribution */, 1266929E0EB75BEA00E002D5 /* Configuration */, - B8474B8C0EB40094006A0BC1 /* FMDB */, + DD932B5B165C261A00D69D49 /* Low-Level Details */, + DD932BC1165C287600D69D49 /* Resources */, ); path = Map; sourceTree = ""; @@ -512,6 +602,27 @@ name = "Coordinate Systems"; sourceTree = ""; }; + DD3BEF71159134E0007892D8 /* Attribution */ = { + isa = PBXGroup; + children = ( + DD3BEF7715913C55007892D8 /* RMAttributionViewController.h */, + DD3BEF7815913C55007892D8 /* RMAttributionViewController.m */, + ); + name = Attribution; + sourceTree = ""; + }; + DD76E12E161E347B00F60F43 /* SMCallout */ = { + isa = PBXGroup; + children = ( + DD1E3C6C161F954F004FC649 /* SMCalloutView.h */, + DD1E3C6D161F954F004FC649 /* SMCalloutView.m */, + DD5F5F9318C7C03C0085DE98 /* SMClassicCalloutView.h */, + DD5F5F9418C7C03C0085DE98 /* SMClassicCalloutView.m */, + ); + name = SMCallout; + path = Map; + sourceTree = ""; + }; DD8FD7571559ED930044D96F /* User Location */ = { isa = PBXGroup; children = ( @@ -519,26 +630,103 @@ DD8FD7531559E4A40044D96F /* RMUserLocation.m */, DDA6B8BB155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h */, DDA6B8BC155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.m */, - DD8FD7581559EDA80044D96F /* Resources */, ); name = "User Location"; sourceTree = ""; }; - DD8FD7581559EDA80044D96F /* Resources */ = { + DD932B5B165C261A00D69D49 /* Low-Level Details */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* MapView_Prefix.pch */, + 96492C3F0FA8AD3400EBA6D2 /* RMGlobalConstants.h */, + B1EB26C510B5D8E6009F8658 /* RMNotifications.h */, + B8C974B30E8A23C5007D16AD /* Coordinate Systems */, + B83E64E20E80E73F001663B6 /* Projections */, + B83E64CE0E80E73F001663B6 /* Tile & Overlay Rendering */, + ); + name = "Low-Level Details"; + sourceTree = ""; + }; + DD932BC1165C287600D69D49 /* Resources */ = { isa = PBXGroup; children = ( - DD8FD7631559EE120044D96F /* HeadingAngleSmall.png */, - DD8FD7641559EE120044D96F /* HeadingAngleSmall@2x.png */, - DD8FD7651559EE120044D96F /* TrackingDot.png */, - DD8FD7661559EE120044D96F /* TrackingDot@2x.png */, - DD8FD76C1559EE120044D96F /* TrackingDotHalo.png */, - DD8FD7691559EE120044D96F /* TrackingDotHalo@2x.png */, - DDA6B8C2155CAB9A003DB5D8 /* TrackingHeading.png */, - DDA6B8C3155CAB9A003DB5D8 /* TrackingHeading@2x.png */, - DDA6B8C0155CAB9A003DB5D8 /* TrackingLocation.png */, - DDA6B8C1155CAB9A003DB5D8 /* TrackingLocation@2x.png */, + DD932BA5165C287000D69D49 /* mapbox.png */, + DD932BA6165C287000D69D49 /* mapbox@2x.png */, + DDE68E5917D94C0500F1E869 /* mapbox-logo.png */, + DD36766A17D94F980001F27B /* mapbox-logo@2x.png */, + DDA256FD1798A95600BBB325 /* Compass.png */, + DDA256FC1798A95600BBB325 /* Compass@2x.png */, + DD932BA9165C287000D69D49 /* HeadingAngleSmall.png */, + DD932BAA165C287000D69D49 /* HeadingAngleSmall@2x.png */, + DD94D46816C2E064003D5739 /* HeadingAngleMedium.png */, + DD94D46916C2E064003D5739 /* HeadingAngleMedium@2x.png */, + DD94D46616C2E064003D5739 /* HeadingAngleLarge.png */, + DD94D46716C2E064003D5739 /* HeadingAngleLarge@2x.png */, + DD07A23217F3AF9800E420B2 /* HeadingAngleMaskSmall.png */, + DD07A23517F3AF9800E420B2 /* HeadingAngleMaskSmall@2x.png */, + DD07A23317F3AF9800E420B2 /* HeadingAngleMaskMedium.png */, + DD07A23617F3AF9800E420B2 /* HeadingAngleMaskMedium@2x.png */, + DD07A23417F3AF9800E420B2 /* HeadingAngleMaskLarge.png */, + DD07A23717F3AF9800E420B2 /* HeadingAngleMaskLarge@2x.png */, + DD932BAB165C287000D69D49 /* LoadingTile.png */, + DDC8D28517E92ED100A4FB32 /* LoadingTile6.png */, + DD932BA7165C287000D69D49 /* TrackingDot.png */, + DD932BA8165C287000D69D49 /* TrackingDot@2x.png */, + DD932BAD165C287000D69D49 /* TrackingDotHalo.png */, + DD932BAE165C287000D69D49 /* TrackingDotHalo@2x.png */, + DD932BAF165C287000D69D49 /* TrackingHeading.png */, + DD932BB0165C287000D69D49 /* TrackingHeading@2x.png */, + DDA256FE1798A95600BBB325 /* TrackingHeadingMask.png */, + DDA256FB1798A95600BBB325 /* TrackingHeadingMask@2x.png */, + DDA256FA1798A95600BBB325 /* TrackingHeadingMaskLandscape@2x.png */, + DD932BB1165C287000D69D49 /* TrackingLocation.png */, + DD932BB2165C287000D69D49 /* TrackingLocation@2x.png */, + DDA257001798A95600BBB325 /* TrackingLocationMask.png */, + DDA256F91798A95600BBB325 /* TrackingLocationMask@2x.png */, + DDA256F81798A95600BBB325 /* TrackingLocationMaskLandscape@2x.png */, + DDA256FF1798A95600BBB325 /* TrackingLocationOffMask.png */, + DDA256F71798A95600BBB325 /* TrackingLocationOffMask@2x.png */, + DDA256F61798A95600BBB325 /* TrackingLocationOffMaskLandscape@2x.png */, ); name = Resources; + path = ..; + sourceTree = ""; + }; + DD932BC2165C294100D69D49 /* Externals */ = { + isa = PBXGroup; + children = ( + B8474B8C0EB40094006A0BC1 /* FMDB */, + DDC4BEEE152E3DEC00089409 /* GRMustache */, + DDDFF7FE165D5BA200A9D877 /* Proj4 */, + DD76E12E161E347B00F60F43 /* SMCallout */, + ); + name = Externals; + sourceTree = ""; + }; + DDC4BED1152E3BC200089409 /* Interactivity */ = { + isa = PBXGroup; + children = ( + DDC4BED3152E3BD700089409 /* RMInteractiveSource.h */, + DDC4BED4152E3BD700089409 /* RMInteractiveSource.m */, + ); + name = Interactivity; + sourceTree = ""; + }; + DDC4BEEE152E3DEC00089409 /* GRMustache */ = { + isa = PBXGroup; + children = ( + DDEDBBCF1A81864800646DBB /* libGRMustache7-iOS.a */, + ); + name = GRMustache; + path = Map; + sourceTree = ""; + }; + DDDFF7FE165D5BA200A9D877 /* Proj4 */ = { + isa = PBXGroup; + children = ( + DD97C11516489678007C4652 /* libProj4.a */, + ); + name = Proj4; sourceTree = ""; }; /* End PBXGroup section */ @@ -549,53 +737,69 @@ buildActionMask = 2147483647; files = ( B8C974250E8A19B2007D16AD /* RMOpenStreetMapSource.h in Headers */, - B8C974220E8A19B2007D16AD /* RMProjection.h in Headers */, B8C974230E8A19B2007D16AD /* RMTileCache.h in Headers */, - B8C974260E8A19B2007D16AD /* RMTile.h in Headers */, - B8C974270E8A19B2007D16AD /* RMPixel.h in Headers */, - B8C9742A0E8A19B2007D16AD /* RMTileImage.h in Headers */, B8C9742B0E8A19B2007D16AD /* RMMemoryCache.h in Headers */, - B8C9742D0E8A19B2007D16AD /* RMFractalTileProjection.h in Headers */, B8C9742F0E8A19B2007D16AD /* RMMapLayer.h in Headers */, + DD56B9511961E23F00706C67 /* FMDatabaseAdditions.h in Headers */, B8C974620E8A19E8007D16AD /* RMTileSource.h in Headers */, B8C9746B0E8A1A50007D16AD /* RMMapView.h in Headers */, B8F3FC640EA2E792004D8F85 /* RMMarker.h in Headers */, B8474BA40EB40094006A0BC1 /* RMDatabaseCache.h in Headers */, - 23A0AAEB0EB90AA6003A4521 /* RMFoundation.h in Headers */, B8800FF20EC3A239003E9CDD /* RMMapViewDelegate.h in Headers */, B8800FF30EC3A23D003E9CDD /* RMConfiguration.h in Headers */, - B8CEB1C50ED5A3480014C431 /* RMPath.h in Headers */, - 96492C400FA8AD3400EBA6D2 /* RMGlobalConstants.h in Headers */, - B1EB26C610B5D8E6009F8658 /* RMNotifications.h in Headers */, - D1437B37122869E400888DAE /* RMDBMapSource.h in Headers */, + DD56B94F1961E23F00706C67 /* FMDatabase.h in Headers */, 25757F4F1291C8640083D504 /* RMCircle.h in Headers */, - 17F02BB11319BA4B00260C6B /* RouteMe.h in Headers */, 16EC85D2133CA6C300219947 /* RMAbstractMercatorTileSource.h in Headers */, 16EC85D4133CA6C300219947 /* RMAbstractWebMapSource.h in Headers */, + DD56B9581961E23F00706C67 /* FMResultSet.h in Headers */, 16EC85D6133CA6C300219947 /* RMCacheObject.h in Headers */, 160EEDAF13D41DEC007C5501 /* RMAnnotation.h in Headers */, + DD2B375514CF8197008DE8CB /* RMMBTilesSource.h in Headers */, + DD56B9551961E23F00706C67 /* FMDatabaseQueue.h in Headers */, + DD98B6FA14D76B930092882F /* RMMapboxSource.h in Headers */, + 1607499514E120A100D535F5 /* RMGenericMapSource.h in Headers */, + DDC4BED5152E3BD700089409 /* RMInteractiveSource.h in Headers */, + DD8FD7541559E4A40044D96F /* RMUserLocation.h in Headers */, + DDA6B8BD155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h in Headers */, + 16F98C961590CFF000FF90CE /* RMShape.h in Headers */, + DD4BE198161CE296003EF677 /* Mapbox.h in Headers */, + 16E5A63A15E531F200C92A5A /* RMCompositeSource.h in Headers */, + DD7C7E38164C894F0021CCA5 /* RMStaticMapView.h in Headers */, + DDE357E71651F570001DB842 /* RMPointAnnotation.h in Headers */, + DDE357F0165223A3001DB842 /* RMShapeAnnotation.h in Headers */, + DDE357F416522661001DB842 /* RMPolylineAnnotation.h in Headers */, + DDE357F816522CD8001DB842 /* RMPolygonAnnotation.h in Headers */, + DD1985C1165C5F6400DF667F /* RMTileMillSource.h in Headers */, + DD63176317D15EB5008CA79B /* RMCircleAnnotation.h in Headers */, + DD63175F17D1506D008CA79B /* RMGreatCircleAnnotation.h in Headers */, + B8C974220E8A19B2007D16AD /* RMProjection.h in Headers */, + B8C974260E8A19B2007D16AD /* RMTile.h in Headers */, + B8C974270E8A19B2007D16AD /* RMPixel.h in Headers */, + B8C9742A0E8A19B2007D16AD /* RMTileImage.h in Headers */, + B8C9742D0E8A19B2007D16AD /* RMFractalTileProjection.h in Headers */, + 23A0AAEB0EB90AA6003A4521 /* RMFoundation.h in Headers */, + 96492C400FA8AD3400EBA6D2 /* RMGlobalConstants.h in Headers */, + B1EB26C610B5D8E6009F8658 /* RMNotifications.h in Headers */, + DD5F5F9518C7C03C0085DE98 /* SMClassicCalloutView.h in Headers */, + D1437B37122869E400888DAE /* RMDBMapSource.h in Headers */, 1606C9FE13D86BA400547581 /* RMOpenCycleMapSource.h in Headers */, 16FAB66413E03D55002F4E1C /* RMQuadTree.h in Headers */, 160E535713FBDB48004F82F9 /* RMMapTiledLayerView.h in Headers */, 1609AF8E14068B09008344B7 /* RMMapOverlayView.h in Headers */, 16128CF5148D295300C23C0E /* RMOpenSeaMapSource.h in Headers */, - DD2B374514CF8041008DE8CB /* FMDatabase.h in Headers */, - DD2B374714CF8041008DE8CB /* FMDatabaseAdditions.h in Headers */, - DD2B374914CF8041008DE8CB /* FMResultSet.h in Headers */, - DD2B374F14CF814F008DE8CB /* FMDatabasePool.h in Headers */, - DD2B375114CF814F008DE8CB /* FMDatabaseQueue.h in Headers */, - DD2B375514CF8197008DE8CB /* RMMBTilesSource.h in Headers */, - DD98B6FA14D76B930092882F /* RMMapBoxSource.h in Headers */, DD8CDB4A14E0507100B73EB9 /* RMMapQuestOSMSource.h in Headers */, - 1607499514E120A100D535F5 /* RMGenericMapSource.h in Headers */, 16FFF2CB14E3DBF700A170EC /* RMMapQuestOpenAerialSource.h in Headers */, - DD8FD7541559E4A40044D96F /* RMUserLocation.h in Headers */, - DDA6B8BD155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.h in Headers */, + DD3BEF7915913C55007892D8 /* RMAttributionViewController.h in Headers */, 16F3581B15864135003A3AD9 /* RMMapScrollView.h in Headers */, - 16F98C961590CFF000FF90CE /* RMShape.h in Headers */, 16FBF07615936BF1004ECAD1 /* RMTileSourcesContainer.h in Headers */, + DD56B9531961E23F00706C67 /* FMDatabasePool.h in Headers */, 161E563A1594664E00B00BB6 /* RMOpenSeaMapLayer.h in Headers */, 1656665515A1DF7900EF3DC7 /* RMCoordinateGridSource.h in Headers */, + DD5FA1EB15E2B020004EB6C5 /* RMLoadingTileView.h in Headers */, + DD41960116250ED40049E6BA /* RMTileCacheDownloadOperation.h in Headers */, + DD4195C9162356900049E6BA /* RMBingSource.h in Headers */, + DD56B9571961E23F00706C67 /* FMDB.h in Headers */, + DD1E3C6E161F954F004FC649 /* SMCalloutView.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -613,20 +817,36 @@ buildRules = ( ); dependencies = ( - B8C974140E8A19B2007D16AD /* PBXTargetDependency */, + DD6A83901644A2810097F31F /* PBXTargetDependency */, ); name = MapView; productName = MapView; - productReference = 17F31EFA1331050A00122B16 /* libMapView.a */; + productReference = 17F31EFA1331050A00122B16 /* libMapbox.a */; productType = "com.apple.product-type.library.static"; }; + DD6A83741644A20C0097F31F /* Resources */ = { + isa = PBXNativeTarget; + buildConfigurationList = DD6A837E1644A20C0097F31F /* Build configuration list for PBXNativeTarget "Resources" */; + buildPhases = ( + DD6A83711644A20C0097F31F /* Sources */, + DD6A83731644A20C0097F31F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Resources; + productName = Resources; + productReference = DD6A83751644A20C0097F31F /* Mapbox.bundle */; + productType = "com.apple.product-type.bundle"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0450; + LastUpgradeCheck = 0500; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapView" */; compatibilityVersion = "Xcode 3.2"; @@ -637,31 +857,64 @@ Japanese, French, German, + en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 38D8184C0F6F67B90034598B /* Products */; - ProjectRef = B83E654A0E80E7A8001663B6 /* Proj4.xcodeproj */; - }, - ); projectRoot = ""; targets = ( B8C974130E8A19B2007D16AD /* MapView */, + DD6A83741644A20C0097F31F /* Resources */, ); }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 38D818500F6F67B90034598B /* libProj4.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libProj4.a; - remoteRef = 38D8184F0F6F67B90034598B /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ +/* Begin PBXResourcesBuildPhase section */ + DD6A83731644A20C0097F31F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DD932BB3165C287000D69D49 /* mapbox.png in Resources */, + DD932BB4165C287000D69D49 /* mapbox@2x.png in Resources */, + DD932BB7165C287000D69D49 /* HeadingAngleSmall.png in Resources */, + DD07A23A17F3AF9800E420B2 /* HeadingAngleMaskLarge.png in Resources */, + DD07A23C17F3AF9800E420B2 /* HeadingAngleMaskMedium@2x.png in Resources */, + DD07A23917F3AF9800E420B2 /* HeadingAngleMaskMedium.png in Resources */, + DDA257071798A95600BBB325 /* Compass@2x.png in Resources */, + DD932BB8165C287000D69D49 /* HeadingAngleSmall@2x.png in Resources */, + DD932BB9165C287000D69D49 /* LoadingTile.png in Resources */, + DDE68E5A17D94C0500F1E869 /* mapbox-logo.png in Resources */, + DD932BB5165C287000D69D49 /* TrackingDot.png in Resources */, + DD932BB6165C287000D69D49 /* TrackingDot@2x.png in Resources */, + DD932BBB165C287000D69D49 /* TrackingDotHalo.png in Resources */, + DD932BBC165C287000D69D49 /* TrackingDotHalo@2x.png in Resources */, + DDA257031798A95600BBB325 /* TrackingLocationMaskLandscape@2x.png in Resources */, + DDA257051798A95600BBB325 /* TrackingHeadingMaskLandscape@2x.png in Resources */, + DDA257061798A95600BBB325 /* TrackingHeadingMask@2x.png in Resources */, + DD932BBD165C287000D69D49 /* TrackingHeading.png in Resources */, + DDA2570B1798A95600BBB325 /* TrackingLocationMask.png in Resources */, + DDC8D28717E92ED100A4FB32 /* LoadingTile6.png in Resources */, + DD932BBE165C287000D69D49 /* TrackingHeading@2x.png in Resources */, + DDA257091798A95600BBB325 /* TrackingHeadingMask.png in Resources */, + DD932BBF165C287000D69D49 /* TrackingLocation.png in Resources */, + DD932BC0165C287000D69D49 /* TrackingLocation@2x.png in Resources */, + DDA2570A1798A95600BBB325 /* TrackingLocationOffMask.png in Resources */, + DDA257011798A95600BBB325 /* TrackingLocationOffMaskLandscape@2x.png in Resources */, + DDA257041798A95600BBB325 /* TrackingLocationMask@2x.png in Resources */, + DDA257081798A95600BBB325 /* Compass.png in Resources */, + DD07A23817F3AF9800E420B2 /* HeadingAngleMaskSmall.png in Resources */, + DD94D46A16C2E064003D5739 /* HeadingAngleLarge.png in Resources */, + DD94D46B16C2E064003D5739 /* HeadingAngleLarge@2x.png in Resources */, + DD07A23D17F3AF9800E420B2 /* HeadingAngleMaskLarge@2x.png in Resources */, + DD94D46C16C2E064003D5739 /* HeadingAngleMedium.png in Resources */, + DD94D46D16C2E064003D5739 /* HeadingAngleMedium@2x.png in Resources */, + DD07A23B17F3AF9800E420B2 /* HeadingAngleMaskSmall@2x.png in Resources */, + DD36766B17D94F980001F27B /* mapbox-logo@2x.png in Resources */, + DDA257021798A95600BBB325 /* TrackingLocationOffMask@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ B8C974340E8A19B2007D16AD /* Sources */ = { @@ -673,16 +926,18 @@ B8C974410E8A19B2007D16AD /* RMOpenStreetMapSource.m in Sources */, B8C974420E8A19B2007D16AD /* RMMemoryCache.m in Sources */, B8C974430E8A19B2007D16AD /* RMPixel.c in Sources */, + DD56B9541961E23F00706C67 /* FMDatabasePool.m in Sources */, B8C974440E8A19B2007D16AD /* RMFractalTileProjection.m in Sources */, B8C974480E8A19B2007D16AD /* RMTileCache.m in Sources */, + DD63176417D15EB5008CA79B /* RMCircleAnnotation.m in Sources */, B8C9744A0E8A19B2007D16AD /* RMProjection.m in Sources */, B8C9746C0E8A1A50007D16AD /* RMMapView.m in Sources */, B8F3FC610EA2B382004D8F85 /* RMMapLayer.m in Sources */, B8F3FC650EA2E792004D8F85 /* RMMarker.m in Sources */, + DD5F5F9618C7C03C0085DE98 /* SMClassicCalloutView.m in Sources */, B8474BA50EB40094006A0BC1 /* RMDatabaseCache.m in Sources */, 126693040EB76C0B00E002D5 /* RMConfiguration.m in Sources */, 23A0AAE90EB90A99003A4521 /* RMFoundation.c in Sources */, - B8CEB1C60ED5A3480014C431 /* RMPath.m in Sources */, D1437B36122869E400888DAE /* RMDBMapSource.m in Sources */, 25757F501291C8640083D504 /* RMCircle.m in Sources */, 16EC85D3133CA6C300219947 /* RMAbstractMercatorTileSource.m in Sources */, @@ -693,17 +948,16 @@ 16FAB66513E03D55002F4E1C /* RMQuadTree.m in Sources */, 160E535813FBDB48004F82F9 /* RMMapTiledLayerView.m in Sources */, 1609AF8F14068B09008344B7 /* RMMapOverlayView.m in Sources */, + DD56B9561961E23F00706C67 /* FMDatabaseQueue.m in Sources */, 16128CF6148D295300C23C0E /* RMOpenSeaMapSource.m in Sources */, - DD2B374614CF8041008DE8CB /* FMDatabase.m in Sources */, - DD2B374814CF8041008DE8CB /* FMDatabaseAdditions.m in Sources */, - DD2B374A14CF8041008DE8CB /* FMResultSet.m in Sources */, - DD2B375014CF814F008DE8CB /* FMDatabasePool.m in Sources */, - DD2B375214CF814F008DE8CB /* FMDatabaseQueue.m in Sources */, + DD63176017D1506D008CA79B /* RMGreatCircleAnnotation.m in Sources */, DD2B375614CF8197008DE8CB /* RMMBTilesSource.m in Sources */, - DD98B6FB14D76B930092882F /* RMMapBoxSource.m in Sources */, + DD98B6FB14D76B930092882F /* RMMapboxSource.m in Sources */, DD8CDB4B14E0507100B73EB9 /* RMMapQuestOSMSource.m in Sources */, 1607499614E120A100D535F5 /* RMGenericMapSource.m in Sources */, 16FFF2CC14E3DBF700A170EC /* RMMapQuestOpenAerialSource.m in Sources */, + DDC4BEF2152E3FAE00089409 /* RMInteractiveSource.m in Sources */, + DD3BEF7A15913C55007892D8 /* RMAttributionViewController.m in Sources */, DD8FD7551559E4A40044D96F /* RMUserLocation.m in Sources */, DDA6B8BE155CAB67003DB5D8 /* RMUserTrackingBarButtonItem.m in Sources */, 16F3581C15864135003A3AD9 /* RMMapScrollView.m in Sources */, @@ -711,16 +965,37 @@ 16FBF07715936BF1004ECAD1 /* RMTileSourcesContainer.m in Sources */, 161E563B1594664E00B00BB6 /* RMOpenSeaMapLayer.m in Sources */, 1656665615A1DF7900EF3DC7 /* RMCoordinateGridSource.m in Sources */, + DD56B9501961E23F00706C67 /* FMDatabase.m in Sources */, + 16E5A63B15E531F200C92A5A /* RMCompositeSource.m in Sources */, + DD56B9591961E23F00706C67 /* FMResultSet.m in Sources */, + DD5FA1EC15E2B020004EB6C5 /* RMLoadingTileView.m in Sources */, + DD41960216250ED40049E6BA /* RMTileCacheDownloadOperation.m in Sources */, + DD4195CA162356900049E6BA /* RMBingSource.m in Sources */, + DD1E3C6F161F954F004FC649 /* SMCalloutView.m in Sources */, + DD7C7E39164C894F0021CCA5 /* RMStaticMapView.m in Sources */, + DDE357E81651F570001DB842 /* RMPointAnnotation.m in Sources */, + DDE357F1165223A3001DB842 /* RMShapeAnnotation.m in Sources */, + DDE357F516522661001DB842 /* RMPolylineAnnotation.m in Sources */, + DDE357F916522CD8001DB842 /* RMPolygonAnnotation.m in Sources */, + DD1985C2165C5F6400DF667F /* RMTileMillSource.m in Sources */, + DD56B9521961E23F00706C67 /* FMDatabaseAdditions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DD6A83711644A20C0097F31F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - B8C974140E8A19B2007D16AD /* PBXTargetDependency */ = { + DD6A83901644A2810097F31F /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = Proj4; - targetProxy = B8C974150E8A19B2007D16AD /* PBXContainerItemProxy */; + target = DD6A83741644A20C0097F31F /* Resources */; + targetProxy = DD6A838F1644A2810097F31F /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -729,15 +1004,25 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = MapView_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - HEADER_SEARCH_PATHS = ../Proj4; + HEADER_SEARCH_PATHS = ( + "\"$(SRCROOT)/../Proj4\"", + "\"$(SRCROOT)/Map/GRMustache/include\"", + "\"$(SRCROOT)/Map/FMDB/src/fmdb\"", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/Map/GRMustache/lib\"", + "\"$(SRCROOT)/../Proj4\"", + ); OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = MapView; + PRODUCT_NAME = Mapbox; RUN_CLANG_STATIC_ANALYZER = NO; }; name = Debug; @@ -746,14 +1031,24 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = MapView_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = "NS_BLOCK_ASSERTIONS=1"; - HEADER_SEARCH_PATHS = ../Proj4; + HEADER_SEARCH_PATHS = ( + "\"$(SRCROOT)/../Proj4\"", + "\"$(SRCROOT)/Map/GRMustache/include\"", + "\"$(SRCROOT)/Map/FMDB/src/fmdb\"", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/Map/GRMustache/lib\"", + "\"$(SRCROOT)/../Proj4\"", + ); OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = MapView; + PRODUCT_NAME = Mapbox; ZERO_LINK = NO; }; name = Release; @@ -761,11 +1056,14 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = ( - armv6, - "$(ARCHS_STANDARD_32_BIT)", - ); - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Don't Code Sign"; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEPLOYMENT_POSTPROCESSING = NO; GCC_C_LANGUAGE_STANDARD = c99; @@ -777,12 +1075,12 @@ GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.0; - OTHER_CFLAGS = ( - "-O", - "-Wuninitialized", - ); + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; RUN_CLANG_STATIC_ANALYZER = NO; SDKROOT = iphoneos; @@ -796,11 +1094,14 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = ( - armv6, - "$(ARCHS_STANDARD_32_BIT)", - ); - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; COPY_PHASE_STRIP = YES; DEPLOYMENT_POSTPROCESSING = NO; GCC_C_LANGUAGE_STANDARD = c99; @@ -811,8 +1112,11 @@ GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.0; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; OTHER_LDFLAGS = ""; RUN_CLANG_STATIC_ANALYZER = NO; SDKROOT = iphoneos; @@ -822,6 +1126,56 @@ }; name = Release; }; + DD6A837F1644A20C0097F31F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Resources/Resources-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = Mapbox; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + DD6A83801644A20C0097F31F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Resources/Resources-Prefix.pch"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_NAME = Mapbox; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -843,6 +1197,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DD6A837E1644A20C0097F31F /* Build configuration list for PBXNativeTarget "Resources" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DD6A837F1644A20C0097F31F /* Debug */, + DD6A83801644A20C0097F31F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; diff --git a/MapView/MapView_Prefix.pch b/MapView/MapView_Prefix.pch index 1cb7c2ddc..f4aa28266 100644 --- a/MapView/MapView_Prefix.pch +++ b/MapView/MapView_Prefix.pch @@ -12,7 +12,7 @@ #endif #if DEBUG -#define RMLog(args...) NSLog(@"%@", [NSString stringWithFormat: args]) +#define RMLog(args...) NSLog(@"%@", [NSString stringWithFormat: args]) #define LogMethod() NSLog(@"logged method call: -[%@ %@] (line %d)", self, NSStringFromSelector(_cmd), __LINE__) #define WarnDeprecated() NSLog(@"***** WARNING: deprecated method call: -[%@ %@] (line %d)", self, NSStringFromSelector(_cmd), __LINE__) #else @@ -24,3 +24,8 @@ #define NS_BLOCK_ASSERTIONS 1 #endif +#define RMPostVersion6 (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_5_1) +#define RMPreVersion6 (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_5_1) + +#define RMPostVersion7 (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) +#define RMPreVersion7 (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) diff --git a/MapView/UnitTesting/RouteMeTests.h b/MapView/UnitTesting/RouteMeTests.h deleted file mode 100644 index 8513259d0..000000000 --- a/MapView/UnitTesting/RouteMeTests.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// RouteMeTests.h -// MapView -// -// Created by Hal Mueller on 4/6/09. -// Copyright 2009 Route-Me Contributors. All rights reserved. -// - -#import "GTMSenTestCase.h" -#import "GTMUIKit+UnitTesting.h" -#import - -@class RMMapView; - -/// Unit tests go here. See http://developer.apple.com/tools/unittest.html -///and http://code.google.com/p/google-toolbox-for-mac/wiki/iPhoneUnitTesting for guidance. -@interface RouteMeTests : SenTestCase { - RMMapView *mapView; - UIView *contentView; - CLLocationCoordinate2D initialCenter; -} - -@end diff --git a/MapView/UnitTesting/RouteMeTests.m b/MapView/UnitTesting/RouteMeTests.m deleted file mode 100644 index f31d458cd..000000000 --- a/MapView/UnitTesting/RouteMeTests.m +++ /dev/null @@ -1,393 +0,0 @@ -// -// RouteMeTests.m -// MapView -// -// Created by Hal Mueller on 4/6/09. -// Copyright 2009 Route-Me Contributors. All rights reserved. -// - -#import "RouteMeTests.h" -#import "RMMapView.h" -#import "RMCloudMadeMapSource.h" -#import "RMMarker.h" -#import "RMMarkerManager.h" - -@implementation RouteMeTests -#define kAccuracyThreshold .0001 -#define kAccuracyThresholdForGeographicCoordinates .00001 -#define kAccuracyThresholdForPixelCoordinates kAccuracyThreshold - -- (void)setUp { - [super setUp]; - - CGRect appRect = [[UIScreen mainScreen] applicationFrame]; - contentView = [[UIView alloc] initWithFrame:appRect]; - contentView.backgroundColor = [UIColor greenColor]; - - initialCenter.latitude = 66.44; - initialCenter.longitude = -178.0; - - mapView = [[RMMapView alloc] initWithFrame:CGRectMake(10,20,200,300) - WithLocation:initialCenter]; - [contentView addSubview:mapView]; -} - --(void)tearDown { - [mapView release]; mapView = nil; - [super tearDown]; -} - -- (void)testObjectCreation -{ - - STAssertNotNil((mapView = [[RMMapView alloc] init]), @"mapView alloc/init failed"); - STAssertNoThrow([mapView release], @"mapView release failed"); - mapView = nil; - - id myTilesource; - STAssertNotNil((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:@"0199bdee456e59ce950b0156029d6934" styleNumber:999]), - @"tilesource creation failed"); - STAssertNoThrow([myTilesource release], @"tilesource release failed"); - STAssertNil((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:nil styleNumber:999]), - @"empty CloudMade key does not trigger error"); - STAssertNoThrow([myTilesource release], @"tilesource release failed"); - STAssertThrows((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:@"0199bdee456e59ce950b0156029d693" styleNumber:999]), - @"bogus CloudMade key does not trigger error"); - STAssertNoThrow([myTilesource release], @"tilesource release failed"); -} - -- (void)testProgrammaticViewCreation -{ - STAssertNotNil(mapView, @"mapview creation failed"); - STAssertNotNil([mapView contents], @"mapView contents should not be nil"); -} - -- (void)testMarkerCreation -{ - // create markers from -183 to -169 longitude - initialCenter.longitude = -178.0; - - CLLocationCoordinate2D markerPosition; - NSUInteger nRows = 1; - NSUInteger nColumns = 8; - double columnSpacing = 2.0; - - UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"]; - STAssertNotNil(markerImage, @"testMarkerCreation marker image did not load"); - markerPosition.latitude = initialCenter.latitude - ((nRows - 1)/2.0 * columnSpacing); - NSUInteger i, j; - for (i = 0; i < nRows; i++) { - markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing); - for (j = 0; j < nColumns; j++) { - markerPosition.longitude += columnSpacing; - RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage]; - STAssertNotNil(newMarker, @"testMarkerCreation marker creation failed"); - [newMarker setUserInfo:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]]; - [mapView.contents.markerManager addMarker:newMarker - atLatLong:markerPosition]; - } - markerPosition.latitude += columnSpacing; - } -} - -- (void)testMarkerCoordinatesFarEast -{ - [mapView.contents setZoom:3.0]; - - // create markers from +177 to +191 longitude - initialCenter.longitude = +176.0; - CLLocationCoordinate2D markerPosition; - - NSUInteger nColumns = 8; - double columnSpacing = 2.0; - - UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"]; - markerPosition.latitude = initialCenter.latitude; - markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing); - NSUInteger j; - NSMutableArray *testMarkers = [NSMutableArray arrayWithCapacity:nColumns]; - for (j = 0; j < nColumns; j++) { - markerPosition.longitude += columnSpacing; - RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage]; - [testMarkers addObject:newMarker]; - [newMarker setUserInfo:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]]; - [mapView.contents.markerManager addMarker:newMarker - atLatLong:markerPosition]; - } - STAssertGreaterThan(columnSpacing, 0.0, @"this test requires positive columnSpacing"); - - RMMarkerManager *mangler = [[mapView contents] markerManager]; - - [[mapView contents] moveBy:CGSizeMake(-5.0, 0.0)]; -#ifdef DEBUG - RMSphericalTrapezium screenLimitsDegrees = [[mapView contents] latitudeLongitudeBoundingBox]; - RMLog(@"screen limits west: %4.1f east %4.1f", screenLimitsDegrees.southwest.longitude, screenLimitsDegrees.northeast.longitude); - RMLog(@"screen limits south: %4.1f north %4.1f", screenLimitsDegrees.southwest.latitude, screenLimitsDegrees.northeast.latitude); -#endif - - for (j = 1; j < nColumns; j++) { - RMMarker *leftMarker = [testMarkers objectAtIndex:j - 1]; - RMMarker *rightMarker = [testMarkers objectAtIndex:j]; - CGPoint leftScreenPosition = [mangler screenCoordinatesForMarker:leftMarker]; - CGPoint rightScreenPosition = [mangler screenCoordinatesForMarker:rightMarker]; - CLLocationCoordinate2D leftMarkerCoordinate, rightMarkerCoordinate; - leftMarkerCoordinate.longitude = [[(NSArray *)leftMarker.userInfo objectAtIndex:0] doubleValue]; - leftMarkerCoordinate.latitude = [[(NSArray *)leftMarker.userInfo objectAtIndex:1] doubleValue]; - rightMarkerCoordinate.longitude = [[(NSArray *)rightMarker.userInfo objectAtIndex:0] doubleValue]; - rightMarkerCoordinate.latitude = [[(NSArray *)rightMarker.userInfo objectAtIndex:1] doubleValue]; - STAssertLessThan(leftScreenPosition.x, rightScreenPosition.x, - @"screen position calculation failed (markers %d, %d): left (%f, %f) right (%f, %f) mapped to left (%f, %f) right (%f, %f)", - j-1, j, -// write these out as longitude/latitude instead of standard latitude/longitude to make comparisons easier - leftMarkerCoordinate.longitude, leftMarkerCoordinate.latitude, - rightMarkerCoordinate.longitude, rightMarkerCoordinate.latitude, - leftScreenPosition.x, leftScreenPosition.y, rightScreenPosition.x, rightScreenPosition.y); - CLLocationCoordinate2D computedLatitudeLongitude = - [mangler latitudeLongitudeForMarker:leftMarker]; - STAssertEqualsWithAccuracy(leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude, kAccuracyThresholdForGeographicCoordinates, - @"round-trip computation of longitude failed %f %f", - leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude); - STAssertEqualsWithAccuracy(leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude, kAccuracyThresholdForGeographicCoordinates, - @"round-trip computation of latitude failed %f %f", - leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude); - } - -} - -- (void)testMarkerCoordinatesFarWest -{ - [mapView.contents setZoom:3.0]; - - // create markers from -177 to -169 longitude - initialCenter.longitude = -178.0; - CLLocationCoordinate2D markerPosition; - - NSUInteger nColumns = 8; - double columnSpacing = 2.0; - - UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"]; - markerPosition.latitude = initialCenter.latitude; - markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing); - NSUInteger j; - NSMutableArray *testMarkers = [NSMutableArray arrayWithCapacity:nColumns]; - for (j = 0; j < nColumns; j++) { - markerPosition.longitude += columnSpacing; - RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage]; - [testMarkers addObject:newMarker]; - [newMarker setUserInfo:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]]; - [mapView.contents.markerManager addMarker:newMarker - atLatLong:markerPosition]; - } - STAssertGreaterThan(columnSpacing, 0.0, @"this test requires positive columnSpacing"); - - RMMarkerManager *mangler = [[mapView contents] markerManager]; - - [[mapView contents] moveBy:CGSizeMake(-5.0, 0.0)]; -#ifdef DEBUG - RMSphericalTrapezium screenLimitsDegrees = [[mapView contents] latitudeLongitudeBoundingBox]; - RMLog(@"screen limits west: %4.1f east %4.1f", screenLimitsDegrees.southwest.longitude, screenLimitsDegrees.northeast.longitude); - RMLog(@"screen limits south: %4.1f north %4.1f", screenLimitsDegrees.southwest.latitude, screenLimitsDegrees.northeast.latitude); -#endif - - for (j = 1; j < nColumns; j++) { - RMMarker *leftMarker = [testMarkers objectAtIndex:j - 1]; - RMMarker *rightMarker = [testMarkers objectAtIndex:j]; - CGPoint leftScreenPosition = [mangler screenCoordinatesForMarker:leftMarker]; - CGPoint rightScreenPosition = [mangler screenCoordinatesForMarker:rightMarker]; - CLLocationCoordinate2D leftMarkerCoordinate, rightMarkerCoordinate; - leftMarkerCoordinate.longitude = [[(NSArray *)leftMarker.userInfo objectAtIndex:0] doubleValue]; - leftMarkerCoordinate.latitude = [[(NSArray *)leftMarker.userInfo objectAtIndex:1] doubleValue]; - rightMarkerCoordinate.longitude = [[(NSArray *)rightMarker.userInfo objectAtIndex:0] doubleValue]; - rightMarkerCoordinate.latitude = [[(NSArray *)rightMarker.userInfo objectAtIndex:1] doubleValue]; - STAssertLessThan(leftScreenPosition.x, rightScreenPosition.x, - @"screen position calculation failed (markers %d, %d): left (%f, %f) right (%f, %f) mapped to left (%f, %f) right (%f, %f)", - j-1, j, - leftMarkerCoordinate.longitude, leftMarkerCoordinate.latitude, - rightMarkerCoordinate.longitude, rightMarkerCoordinate.latitude, - leftScreenPosition.x, leftScreenPosition.y, rightScreenPosition.x, rightScreenPosition.y); - CLLocationCoordinate2D computedLatitudeLongitude = - [mangler latitudeLongitudeForMarker:leftMarker]; - STAssertEqualsWithAccuracy(leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude, kAccuracyThresholdForGeographicCoordinates, - @"round-trip computation of longitude failed %f %f", - leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude); - STAssertEqualsWithAccuracy(leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude, kAccuracyThresholdForGeographicCoordinates, - @"round-trip computation of latitude failed %f %f", - leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude); - } - -} - -- (void)testScreenCoordinatesPacificNorthwest -{ - [[mapView contents] setZoom: 10]; - CLLocationCoordinate2D coord = {45.5,-121}; - [mapView moveToCoordinate:coord]; - - CGPoint point1 = [mapView coordinateToPixel:coord]; - - coord.longitude -= .125; - CGPoint point2 = [mapView coordinateToPixel:coord]; - - coord.longitude -= .125; - CGPoint point3 = [mapView coordinateToPixel:coord]; - - STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates, - @"Y pixel values should be equal"); - STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates, - @"Y pixel values should be equal"); - STAssertLessThan(point3.x, point2.x, - @"X pixel coordinates should be increasing left to right"); - STAssertLessThan(point2.x, point1.x, - @"X pixel coordinates should be increasing left to right"); -} - -- (void)testScreenCoordinatesFarEast -{ - [[mapView contents] setZoom: 10]; - CLLocationCoordinate2D coord = {45.5,179.9}; - [mapView moveToCoordinate:coord]; - - CGPoint point1 = [mapView coordinateToPixel:coord]; - - coord.longitude += .125; - CGPoint point2 = [mapView coordinateToPixel:coord]; - - coord.longitude += .125; - CGPoint point3 = [mapView coordinateToPixel:coord]; - - STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates, - @"Y pixel values should be equal"); - STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates, - @"Y pixel values should be equal"); - STAssertLessThan(point1.x, point2.x, - @"X pixel coordinates should be increasing left to right"); - STAssertLessThan(point2.x, point3.x, - @"X pixel coordinates should be increasing left to right"); -} - -- (void)testScreenCoordinatesFarWest -{ - [[mapView contents] setZoom: 10]; - CLLocationCoordinate2D coord = {45.5,-179.9}; - [mapView moveToCoordinate:coord]; - - CGPoint point1 = [mapView coordinateToPixel:coord]; - - coord.longitude -= .125; - CGPoint point2 = [mapView coordinateToPixel:coord]; - - coord.longitude -= .125; - CGPoint point3 = [mapView coordinateToPixel:coord]; - - STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates, - @"Y pixel values should be equal"); - STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates, - @"Y pixel values should be equal"); - STAssertLessThan(point3.x, point2.x, - @"X pixel coordinates should be increasing left to right"); - STAssertLessThan(point2.x, point1.x, - @"X pixel coordinates should be increasing left to right"); -} - -- (void)testZoomBounds -{ - double contentsMaxZoom, tilesourceMaxZoom, contentsZoom; - contentsMaxZoom = [[mapView contents] maxZoom]; - tilesourceMaxZoom = [[[mapView contents] tileSource] maxZoom]; - contentsZoom = [[mapView contents] zoom]; - STAssertLessThanOrEqual(contentsMaxZoom, tilesourceMaxZoom, @"map's maxZoom exceeds tilesource's maxZoom"); - STAssertLessThanOrEqual(contentsZoom, tilesourceMaxZoom, @"map's zoom exceeds tilesource's maxZoom"); - - double targetZoom = tilesourceMaxZoom + 0.4; - [[mapView contents] setZoom:targetZoom]; // try to exceed tilesource limit - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, @"map's zoom wrong after trying to exceed tilesource's maxZoom"); - - targetZoom = tilesourceMaxZoom + 0.5; - [[mapView contents] setZoom:targetZoom]; // try to exceed tilesource limit - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, @"map's zoom wrong after trying to exceed tilesource's maxZoom"); - - targetZoom = tilesourceMaxZoom - 1.6; - [[mapView contents] setZoom:targetZoom]; - CGPoint pivotPoint = CGPointMake(5., 5.); - [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom - 1.0, kAccuracyThreshold, - @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom-1 %f", - contentsZoom, tilesourceMaxZoom); - [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, - @"map's zoom [%f] wrong after zoomInToNextNativeZoomAt: for maxZoom %f (first)", - contentsZoom, tilesourceMaxZoom); - [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, - @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom %f (second)", - contentsZoom, tilesourceMaxZoom); - - - targetZoom = tilesourceMaxZoom - 1.5; - [[mapView contents] setZoom:targetZoom]; - pivotPoint = CGPointMake(5., 5.); - [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom - 1.0, kAccuracyThreshold, - @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom-1 %f", - contentsZoom, tilesourceMaxZoom); - [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, - @"map's zoom [%f] wrong after zoomInToNextNativeZoomAt: for maxZoom %f (first)", - contentsZoom, tilesourceMaxZoom); - [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, - @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom %f (second)", - contentsZoom, tilesourceMaxZoom); - - - double contentsMinZoom = 3.0; - [[mapView contents] setMinZoom:contentsMinZoom]; - targetZoom = contentsMinZoom + 0.6; - [[mapView contents] setZoom:targetZoom]; - contentsZoom = [[mapView contents] zoom]; - NSLog(@"zoom: %f minZoom: %f", contentsZoom, [[mapView contents] minZoom]); - [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, - @"map's zoom %f wrong after first zoomOutToNextNativeZoomAt: for minZoom %f", - contentsZoom, contentsMinZoom); - [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, - @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f", - contentsZoom, contentsMinZoom); - - contentsMinZoom = 3.0; - [[mapView contents] setMinZoom:contentsMinZoom]; - targetZoom = contentsMinZoom + 1.6; - [[mapView contents] setZoom:targetZoom]; - contentsZoom = [[mapView contents] zoom]; - NSLog(@"zoom: %f minZoom: %f", contentsZoom, [[mapView contents] minZoom]); - [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom+1.0, kAccuracyThreshold, - @"map's zoom %f wrong after first zoomOutToNextNativeZoomAt: for minZoom %f", - contentsZoom, contentsMinZoom); - [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, - @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f", - contentsZoom, contentsMinZoom); - [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; - contentsZoom = [[mapView contents] zoom]; - STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, - @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f", - contentsZoom, contentsMinZoom); - - -} - -@end diff --git a/Mapbox-iOS-SDK.podspec b/Mapbox-iOS-SDK.podspec new file mode 100644 index 000000000..1f5e0a937 --- /dev/null +++ b/Mapbox-iOS-SDK.podspec @@ -0,0 +1,81 @@ +Pod::Spec.new do |m| + + m.name = 'Mapbox-iOS-SDK' + m.version = '1.6.1' + + m.summary = 'An open source toolset for building mapping applications for iOS devices.' + m.description = 'An open source toolset for building mapping applications for iOS devices with great flexibility for visual styling, offline use, and customizability.' + m.homepage = 'https://mapbox.com/mapbox-ios-sdk-legacy' + m.license = 'BSD' + m.author = { 'Mapbox' => 'mobile@mapbox.com' } + m.screenshot = 'https://raw.github.com/mapbox/mapbox-ios-sdk-legacy/packaging/screenshot.png' + m.social_media_url = 'https://twitter.com/Mapbox' + + m.source = { + :git => 'https://github.com/mapbox/mapbox-ios-sdk-legacy.git', + :tag => m.version.to_s + } + + m.platform = :ios + m.ios.deployment_target = '5.0' + m.requires_arc = true + + m.module_name = 'Mapbox_iOS_SDK' + + m.source_files = 'Proj4/proj_api.h', 'MapView/Map/*.{h,c,m}' + + m.prefix_header_file = 'MapView/MapView_Prefix.pch' + + m.public_header_files = [ + 'MapView/Map/Mapbox.h', + 'MapView/Map/RMAnnotation.h', + 'MapView/Map/RMCacheObject.h', + 'MapView/Map/RMCircle.h', + 'MapView/Map/RMCircleAnnotation.h', + 'MapView/Map/RMCompositeSource.h', + 'MapView/Map/RMConfiguration.h', + 'MapView/Map/RMCoordinateGridSource.h', + 'MapView/Map/RMDatabaseCache.h', + 'MapView/Map/RMGreatCircleAnnotation.h', + 'MapView/Map/RMInteractiveSource.h', + 'MapView/Map/RMMBTilesSource.h', + 'MapView/Map/RMMapboxSource.h', + 'MapView/Map/RMMapView.h', + 'MapView/Map/RMMapViewDelegate.h', + 'MapView/Map/RMMarker.h', + 'MapView/Map/RMMemoryCache.h', + 'MapView/Map/RMPointAnnotation.h', + 'MapView/Map/RMPolygonAnnotation.h', + 'MapView/Map/RMPolylineAnnotation.h', + 'MapView/Map/RMShape.h', + 'MapView/Map/RMStaticMapView.h', + 'MapView/Map/RMTileCache.h', + 'MapView/Map/RMTileMillSource.h', + 'MapView/Map/RMUserLocation.h', + 'MapView/Map/RMUserTrackingBarButtonItem.h' + ] + + m.resource_bundle = { + 'Mapbox' => 'MapView/Map/Resources/*' + } + + m.documentation_url = 'https://www.mapbox.com/mapbox-ios-sdk-legacy' + + m.frameworks = 'CoreGraphics', 'CoreLocation', 'Foundation', 'QuartzCore', 'UIKit' + + m.libraries = 'Proj4', 'sqlite3', 'z' + + m.xcconfig = { + 'OTHER_LDFLAGS' => '-ObjC', + 'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/Mapbox-iOS-SDK/Proj4"' + } + + m.preserve_paths = 'MapView/MapView.xcodeproj', 'MapView/Map/Resources' + + m.vendored_libraries = 'Proj4/libProj4.a' + + m.dependency 'FMDB', '2.3' + m.dependency 'GRMustache', '7.3.0' + m.dependency 'SMCalloutView', '2.0' + +end diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..60e7fd08f --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ +Thank you kindly for your contribution. However, this repository is DEPRECATED; we will not be making further code changes here and your pull request will not be merged. + +Please refer to https://github.com/mapbox/mapbox-gl-native for current Mapbox iOS SDK development. We would be happy to receive a pull request there. diff --git a/Proj4/Proj4.xcodeproj/project.pbxproj b/Proj4/Proj4.xcodeproj/project.pbxproj index a8a1bc899..185aa64d3 100644 --- a/Proj4/Proj4.xcodeproj/project.pbxproj +++ b/Proj4/Proj4.xcodeproj/project.pbxproj @@ -812,7 +812,7 @@ GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_UNUSED_VARIABLE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 4.0; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; PRODUCT_NAME = Proj4; }; name = Debug; @@ -828,7 +828,7 @@ GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_UNUSED_VARIABLE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 4.0; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; PRODUCT_NAME = Proj4; STRIP_INSTALLED_PRODUCT = YES; }; @@ -837,10 +837,7 @@ 1DEB922308733DC00010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = ( - armv6, - "$(ARCHS_STANDARD_32_BIT)", - ); + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; CODE_SIGN_IDENTITY = "Don't Code Sign"; COPY_PHASE_STRIP = NO; DEPLOYMENT_POSTPROCESSING = YES; @@ -865,10 +862,7 @@ 1DEB922408733DC00010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = ( - armv6, - "$(ARCHS_STANDARD_32_BIT)", - ); + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; COPY_PHASE_STRIP = NO; DEPLOYMENT_POSTPROCESSING = YES; GCC_C_LANGUAGE_STANDARD = c99; diff --git a/Proj4/libProj4.a b/Proj4/libProj4.a new file mode 100644 index 000000000..7f6ea694a Binary files /dev/null and b/Proj4/libProj4.a differ diff --git a/README-old.markdown b/README-old.markdown new file mode 100644 index 000000000..014583667 --- /dev/null +++ b/README-old.markdown @@ -0,0 +1,89 @@ +Mapbox iOS SDK +-------------- + +Based on the Route-Me iOS map library (Alpstein fork) with [Mapbox](http://mapbox.com) customizations. + +Requires iOS 5 or greater (includes iOS 7+ support at runtime), Xcode 5.0 or greater, and ARC. + +[![](https://raw.github.com/mapbox/mapbox-ios-sdk-legacy/packaging/screenshot.png)]() + +Major differences from [Alpstein fork of Route-Me](https://github.com/Alpstein/route-me): + + * Requires iOS 5.0 and above. + * Supports Automatic Reference Counting (ARC). + * [Mapbox](http://mapbox.com) & [MBTiles](http://mbtiles.org) tile source integration code. + * [Mapbox Markers](http://mapbox.com/blog/markers/) support. + * [UTFGrid interactivity](http://mapbox.com/mbtiles-spec/utfgrid/). + * Improved network tile loading performance. + * A bulk, background map tile downloader for cache pre-population and offline use. + * Annotation callouts that behave like MapKit. + * Annotation convenience subclasses for points and shapes. + * Prepackaged static library. + * [CocoaPods](http://cocoapods.org) support. + * Removal of two-finger double-tap gesture for zoom out (to speed up two-finger single-tap recognition like MapKit). + * Different default starting location for maps. + * Built-in attribution view controller with button on map views & default OpenStreetMap attribution. + * Easy static map view support. + * Removal of included example projects in favor of separate examples on GitHub. + * A few added defaults for convenience. + * Improved documentation. + + +Route-Me +-------- + +Route-Me is an open source map library that runs natively on iOS. It's designed to look and feel much like the built-in iOS map library, but it's entirely open, and works with any map source using a pluggable backend system. + +Supported map tile sources include [Mapbox](http://mapbox.com/developers/api/)/[TileStream](https://github.com/mapbox/tilestream), the offline-capable, database-backed format [MBTiles](http://mbtiles.org), [OpenStreetMap](http://www.openstreetmap.org), and several others. + +Please note that you are responsible for getting permission to use the map data, and for ensuring your use adheres to the relevant terms of use. + +Installation +------------ + +There are three ways that you can install the SDK, depending upon your needs: + + 1. Clone from GitHub and integrate as a dependent Xcode project. + 1. Use the [static library](http://mapbox-ios-sdk.s3.amazonaws.com/index.html). Link it in your project, add `#import `, and additionally, include the `-ObjC` linker flag. + 1. Install via [CocoaPods](http://cocoapods.org). + +More detailed information on the installation options is available in the [SDK guide](http://mapbox.com/mapbox-ios-sdk-legacy/). + +The two main branches of the GitHub repository are pretty self-explanatory: `release` and `develop`. When we tag a [release](https://github.com/mapbox/mapbox-ios-sdk-legacy/tags), we also merge `develop` over to `release`, except in the case of minor point releases (e.g., `0.4.2`), where we might just bring over a fix or two from `develop`. + +Then, update the submodules: + + git submodule update --init + +Some example apps showing usage of the SDK (with screenshots): + + * [Mapbox iOS Example](https://github.com/mapbox/mapbox-ios-example) - online, offline, and interactive tile sources + * [Mapbox iOS SDK Offline Example](https://github.com/mapbox/mapbox-ios-sdk-offline) - offline tile source, written in Swift + * [Mapbox Me](https://github.com/mapbox/mapbox-me) - user location services and terrain toggling + * [Weekend Picks](https://github.com/mapbox/weekend-picks-template-ios) - markers and data + +More documentation and examples are available here: http://mapbox.com/mapbox-ios-sdk-legacy/ + +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-2014 Mapbox and Route-Me Contributors". Your data provider will have additional attribution requirements. + +News, Support and Contributing +------------------------------ + +Complete API documentation is available [online](http://mapbox.com/mapbox-ios-sdk-legacy/api/) or as an [Xcode docset Atom feed](http://mapbox.com/mapbox-ios-sdk-legacy/Docs/publish/docset.atom). + +We have a [basic technical overview](http://mapbox.com/mapbox-ios-sdk-legacy/) along with the installation instructions. + +Mapbox has an IRC channel on `irc.freenode.net` in `#mapbox`. + +To report bugs and help fix them, please use the [issue tracker](https://github.com/mapbox/mapbox-ios-sdk-legacy/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](https://github.com/ccgus/fmdb) by Gus Mueller (SQLite for caching and MBTiles) + * [GRMustache](https://github.com/groue/GRMustache) by Gwendal Roué (Mustache templates) + * [SMCalloutView](https://github.com/nfarina/calloutview) by Nick Farina (annotation callouts) diff --git a/README.markdown b/README.markdown index 4e9a47032..c316e0e38 100644 --- a/README.markdown +++ b/README.markdown @@ -1,78 +1,3 @@ -Route-Me: iOS map library (Alpstein fork) ------------------------------------------ +**This project is deprecated in favor of the [Mapbox iOS SDK](https://www.mapbox.com/ios-sdk/)** -Route-Me is an open source map library that runs natively on iOS. It's designed to look and feel much like the built-in iOS map library, but it's entirely open, and works with any map source. - -Currently, [OpenStreetMap][1], [OpenCycleMap][2], [OpenSeaMap][3], [MapQuest OSM][4], [MapQuest Open Aerial][5] and two offline, database-backed formats (DBMap and [MBTiles][6]) are supported as map sources. - -Please note that you are responsible for getting permission to use the map data, and for ensuring your use adheres to the relevant terms of use. - -MapBox users might be interested in the [MapBox fork][7], which includes lots of MapBox specific additions to Route-Me. - - [1]: http://www.openstreetmap.org/index.html - [2]: http://www.opencyclemap.org/ - [3]: http://www.openseamap.org/ - [4]: http://developer.mapquest.com/web/products/open/map - [5]: http://developer.mapquest.com/web/products/open/map - [6]: http://mbtiles.org - [7]: https://github.com/mapbox/mapbox-ios-sdk - - -Installing ----------- - -As Route-Me is undergoing some significant changes, the recommended course of action is to clone a copy of the repository: - - git://github.com/Alpstein/route-me.git - -Or, [download the trunk][dl]. - -Then, update the submodules (only FMDB at the moment): - - git submodule update --init - -See the 'samples' subdirectory for usage examples. - -There are three subdirectories - MapView, Proj4, and samples. Proj4 is a support class used to do map projections. The MapView project contains only the route-me map library. "samples" contains some ready-to-build projects which you may use as starting points for your own applications, and also some engineering test cases. `samples/MarkerMurder` and `samples/ProgrammaticMap` are the best places to look, to see how to embed a Route-Me map in your application. - -See LicenseRouteMe.txt for license details. In any app that uses the Route-Me library, include the following text on your "preferences" or "about" screen: "Uses Route-Me map library, (c) 2008-2012 Route-Me Contributors". Your data provider will have additional attribution requirements. - - - [dl]: https://github.com/Alpstein/route-me/zipball/release - - -News, Support and Contributing ------------------------------- - -Join our [mailing list][list] for news and to communicate with project members and other users: - -To report bugs and help fix them, please use the [issue tracker][tracker] - -[list]: http://groups.google.com/group/route-me-map -[tracker]: https://github.com/Alpstein/route-me/issues - - -Major changes in this fork (Alpstein/route-me) ----------------------------------------------- - -* RMMapView and RMMapContents have been merged into one file - -* The map uses an UIScrollView with a CATiledLayer for better performance - -* Tile cache refactoring - -* Tile source refactoring - -* Support for tile sources with multiple layers (e.g. OpenSeaMap) - -* Support for multiple tile sources on the map - -* Numerous performance improvements - -* Markers have been refactored into a MKMapView-like system, with annotations and on-demand markers - -* Automatic annotation clustering - -* Snapshots from the map - -* Requires at least iOS 4.0 and Xcode 4.3 +See [the old readme](README-old.markdown) for the old project details. diff --git a/install_docs.sh b/install_docs.sh new file mode 100755 index 000000000..00f5e45c1 --- /dev/null +++ b/install_docs.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +if [ -z `which appledoc` ]; then + echo "Unable to find appledoc. Consider installing it from source or Homebrew." + exit 1 +fi + +VERSION=$( git tag | sort -r | sed -n '1p' ) +echo "Creating new docs for $VERSION..." +echo + +appledoc \ + --output /tmp/`uuidgen` \ + --project-name "Mapbox iOS SDK $VERSION" \ + --project-company Mapbox \ + --create-docset \ + --company-id com.mapbox \ + --ignore build \ + --ignore FMDB \ + --ignore GRMustache \ + --ignore SMCalloutView \ + --ignore .c \ + --ignore .m \ + --ignore RMAttributionViewController.h \ + --ignore RMBingSource.h \ + --ignore RMCoordinateGridSource.h \ + --ignore RMDBMapSource.h \ + --ignore RMFoundation.h \ + --ignore RMFractalTileProjection.h \ + --ignore RMGenericMapSource.h \ + --ignore RMGlobalConstants.h \ + --ignore RMLoadingTileView.h \ + --ignore RMMapOverlayView.h \ + --ignore RMMapQuestOpenAerialSource.h \ + --ignore RMMapQuestOSMSource.h \ + --ignore RMMapScrollView.h \ + --ignore RMMapTiledLayerView.h \ + --ignore RMNotifications.h \ + --ignore RMOpenCycleMapSource.h \ + --ignore RMOpenSeaMapLayer.h \ + --ignore RMOpenSeaMapSource.h \ + --ignore RMPixel.h \ + --ignore RMProjection.h \ + --ignore RMTile.h \ + --ignore RMTileImage.h \ + --ignore RMTileSourcesContainer.h \ + --index-desc README.markdown \ + . \ No newline at end of file diff --git a/remove_docs.sh b/remove_docs.sh new file mode 100755 index 000000000..65841598e --- /dev/null +++ b/remove_docs.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +echo +echo "Removing docs from ~/Library/Developer/Shared/Documentation/DocSets..." +echo + +rm -rfv ~/Library/Developer/Shared/Documentation/DocSets/com.mapbox.Mapbox-1.* \ No newline at end of file diff --git a/samples/LayeredMap/Classes/ProgrammaticMapAppDelegate.h b/samples/LayeredMap/Classes/ProgrammaticMapAppDelegate.h deleted file mode 100644 index 2c378aa86..000000000 --- a/samples/LayeredMap/Classes/ProgrammaticMapAppDelegate.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// ProgrammaticMapAppDelegate.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -@class ProgrammaticMapViewController; - -@interface ProgrammaticMapAppDelegate : NSObject -{ - UIWindow *window; - ProgrammaticMapViewController *viewController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet ProgrammaticMapViewController *viewController; - -@end - diff --git a/samples/LayeredMap/Classes/ProgrammaticMapAppDelegate.m b/samples/LayeredMap/Classes/ProgrammaticMapAppDelegate.m deleted file mode 100644 index 0ae949b17..000000000 --- a/samples/LayeredMap/Classes/ProgrammaticMapAppDelegate.m +++ /dev/null @@ -1,31 +0,0 @@ -// -// ProgrammaticMapAppDelegate.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "ProgrammaticMapAppDelegate.h" -#import "ProgrammaticMapViewController.h" - -@implementation ProgrammaticMapAppDelegate - -@synthesize window; -@synthesize viewController; - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - // Override point for customization after app launch - [window addSubview:viewController.view]; - [window makeKeyAndVisible]; -} - -- (void)dealloc -{ - [viewController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/LayeredMap/Classes/ProgrammaticMapViewController.h b/samples/LayeredMap/Classes/ProgrammaticMapViewController.h deleted file mode 100644 index be33928b3..000000000 --- a/samples/LayeredMap/Classes/ProgrammaticMapViewController.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// ProgrammaticMapViewController.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -@class RMMapView; - -@interface ProgrammaticMapViewController : UIViewController -{ - RMMapView *mapView; -} - -@property(nonatomic,retain)RMMapView *mapView; - -- (IBAction)doTheTest:(id)sender; - -@end - diff --git a/samples/LayeredMap/Classes/ProgrammaticMapViewController.m b/samples/LayeredMap/Classes/ProgrammaticMapViewController.m deleted file mode 100644 index 9f030ca33..000000000 --- a/samples/LayeredMap/Classes/ProgrammaticMapViewController.m +++ /dev/null @@ -1,47 +0,0 @@ -// -// ProgrammaticMapViewController.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "ProgrammaticMapViewController.h" -#import "RMMapView.h" -#import "RMOpenSeaMapSource.h" - -@implementation ProgrammaticMapViewController - -@synthesize mapView; - -- (void)viewDidLoad -{ - NSLog(@"viewDidLoad"); - [super viewDidLoad]; - - CLLocationCoordinate2D firstLocation; - firstLocation.latitude = 51.2795; - firstLocation.longitude = 1.082; - - self.mapView = [[[RMMapView alloc] initWithFrame:CGRectMake(10, 20, 300, 340) andTilesource:[[RMOpenSeaMapSource new] autorelease]] autorelease]; - [mapView setBackgroundColor:[UIColor greenColor]]; - [[self view] addSubview:mapView]; - [[self view] sendSubviewToBack:mapView]; -} - -- (void)dealloc -{ - [mapView removeFromSuperview]; - self.mapView = nil; - [super dealloc]; -} - -- (IBAction)doTheTest:(id)sender -{ - CLLocationCoordinate2D secondLocation; - secondLocation.latitude = 54.185; - secondLocation.longitude = 12.09; - [self.mapView setCenterCoordinate:secondLocation]; -} - -@end diff --git a/samples/LayeredMap/Info.plist b/samples/LayeredMap/Info.plist deleted file mode 100644 index 62bd89184..000000000 --- a/samples/LayeredMap/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.mobilegeographics.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/samples/LayeredMap/LayeredMap.xcodeproj/project.pbxproj b/samples/LayeredMap/LayeredMap.xcodeproj/project.pbxproj deleted file mode 100755 index 619fbc7fd..000000000 --- a/samples/LayeredMap/LayeredMap.xcodeproj/project.pbxproj +++ /dev/null @@ -1,328 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1D3623260D0F684500981E51 /* ProgrammaticMapAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; - 2899E5220DE3E06400AC0155 /* ProgrammaticMapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */; }; - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; - 28D7ACF80DDB3853001CB0EB /* ProgrammaticMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */; }; - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */; }; - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */; }; - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */; }; - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; - 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* ProgrammaticMapAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticMapAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticMapAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* LayeredMap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LayeredMap.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ProgrammaticMapViewController.xib; sourceTree = ""; }; - 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 28D7ACF60DDB3853001CB0EB /* ProgrammaticMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticMapViewController.h; sourceTree = ""; }; - 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticMapViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = ""; }; - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 32CA4F630368D1EE00C91783 /* LayeredMap_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayeredMap_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */, - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */, - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */, - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - 1D3623240D0F684500981E51 /* ProgrammaticMapAppDelegate.h */, - 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */, - 28D7ACF60DDB3853001CB0EB /* ProgrammaticMapViewController.h */, - 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */, - ); - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* LayeredMap.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */, - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* LayeredMap_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */, - 28AD733E0D9D9553002E5188 /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */, - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */, - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765A40DF7441C002DB57D /* CoreGraphics.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */ = { - isa = PBXGroup; - children = ( - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* LayeredMap */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "LayeredMap" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */, - ); - name = LayeredMap; - productName = ProgrammaticMap; - productReference = 1D6058910D05DD3D006BFB54 /* LayeredMap.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "LayeredMap" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */; - ProjectRef = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* LayeredMap */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, - 2899E5220DE3E06400AC0155 /* ProgrammaticMapViewController.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* ProgrammaticMapAppDelegate.m in Sources */, - 28D7ACF80DDB3853001CB0EB /* ProgrammaticMapViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = LayeredMap_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - PRODUCT_NAME = LayeredMap; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = LayeredMap_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - PRODUCT_NAME = LayeredMap; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - SDKROOT = iphoneos; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "LayeredMap" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "LayeredMap" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/LayeredMap/LayeredMap_Prefix.pch b/samples/LayeredMap/LayeredMap_Prefix.pch deleted file mode 100644 index 092c26b68..000000000 --- a/samples/LayeredMap/LayeredMap_Prefix.pch +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'ProgrammaticMap' target in the 'ProgrammaticMap' project -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/samples/LayeredMap/MainWindow.xib b/samples/LayeredMap/MainWindow.xib deleted file mode 100644 index b411a1d09..000000000 --- a/samples/LayeredMap/MainWindow.xib +++ /dev/null @@ -1,206 +0,0 @@ - - - - 528 - 9E17 - 672 - 949.33 - 352.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - ProgrammaticMapViewController - - - - - 292 - {320, 480} - - 1 - MSAxIDEAA - - NO - NO - - - - - - YES - - - delegate - - - - 4 - - - - viewController - - - - 11 - - - - window - - - - 14 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - 3 - - - ProgrammaticMap App Delegate - - - -2 - - - - - 10 - - - - - 12 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 10.CustomClassName - 10.IBEditorWindowLastContentRect - 10.IBPluginDependency - 12.IBEditorWindowLastContentRect - 12.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - - - YES - UIApplication - UIResponder - ProgrammaticMapViewController - {{512, 351}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{525, 346}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - ProgrammaticMapAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 14 - - - - YES - - ProgrammaticMapAppDelegate - NSObject - - YES - - YES - viewController - window - - - YES - ProgrammaticMapViewController - UIWindow - - - - IBProjectSource - Classes/ProgrammaticMapAppDelegate.h - - - - ProgrammaticMapAppDelegate - NSObject - - IBUserSource - - - - - ProgrammaticMapViewController - UIViewController - - IBProjectSource - Classes/ProgrammaticMapViewController.h - - - - - 0 - ProgrammaticMap.xcodeproj - 3 - - diff --git a/samples/LayeredMap/ProgrammaticMapViewController.xib b/samples/LayeredMap/ProgrammaticMapViewController.xib deleted file mode 100644 index 7e317a87f..000000000 --- a/samples/LayeredMap/ProgrammaticMapViewController.xib +++ /dev/null @@ -1,202 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 274 - - YES - - - 292 - {{124, 403}, {72, 37}} - - NO - NO - 0 - 0 - - Helvetica-Bold - 1.500000e+01 - 16 - - 1 - Move - Move - Move - Move - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - {320, 460} - - - 3 - MC43NQA - - 2 - - - NO - - - - - - YES - - - view - - - - 7 - - - - doTheTest: - - - 7 - - 9 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - -2 - - - - - 6 - - - YES - - - - - - 8 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 6.IBEditorWindowLastContentRect - 6.IBPluginDependency - 8.IBPluginDependency - - - YES - ProgrammaticMapViewController - UIResponder - {{118, 28}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 9 - - - - YES - - ProgrammaticMapViewController - UIViewController - - doTheTest: - id - - - IBProjectSource - Classes/ProgrammaticMapViewController.h - - - - - 0 - ProgrammaticMap.xcodeproj - 3 - - diff --git a/samples/LayeredMap/main.m b/samples/LayeredMap/main.m deleted file mode 100644 index a02a4c0df..000000000 --- a/samples/LayeredMap/main.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// main.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/MBTilesDemo/Classes/ProgrammaticMapAppDelegate.h b/samples/MBTilesDemo/Classes/ProgrammaticMapAppDelegate.h deleted file mode 100644 index 2c378aa86..000000000 --- a/samples/MBTilesDemo/Classes/ProgrammaticMapAppDelegate.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// ProgrammaticMapAppDelegate.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -@class ProgrammaticMapViewController; - -@interface ProgrammaticMapAppDelegate : NSObject -{ - UIWindow *window; - ProgrammaticMapViewController *viewController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet ProgrammaticMapViewController *viewController; - -@end - diff --git a/samples/MBTilesDemo/Classes/ProgrammaticMapAppDelegate.m b/samples/MBTilesDemo/Classes/ProgrammaticMapAppDelegate.m deleted file mode 100644 index 0ae949b17..000000000 --- a/samples/MBTilesDemo/Classes/ProgrammaticMapAppDelegate.m +++ /dev/null @@ -1,31 +0,0 @@ -// -// ProgrammaticMapAppDelegate.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "ProgrammaticMapAppDelegate.h" -#import "ProgrammaticMapViewController.h" - -@implementation ProgrammaticMapAppDelegate - -@synthesize window; -@synthesize viewController; - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - // Override point for customization after app launch - [window addSubview:viewController.view]; - [window makeKeyAndVisible]; -} - -- (void)dealloc -{ - [viewController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/MBTilesDemo/Classes/ProgrammaticMapViewController.h b/samples/MBTilesDemo/Classes/ProgrammaticMapViewController.h deleted file mode 100644 index 2aeaf9139..000000000 --- a/samples/MBTilesDemo/Classes/ProgrammaticMapViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// ProgrammaticMapViewController.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -#import "RMMapView.h" - -@interface ProgrammaticMapViewController : UIViewController - -@property(nonatomic, retain) RMMapView *mapView; - -- (IBAction)swtichTilesource:(id)sender; - -@end - diff --git a/samples/MBTilesDemo/Classes/ProgrammaticMapViewController.m b/samples/MBTilesDemo/Classes/ProgrammaticMapViewController.m deleted file mode 100644 index dca0412ae..000000000 --- a/samples/MBTilesDemo/Classes/ProgrammaticMapViewController.m +++ /dev/null @@ -1,166 +0,0 @@ -// -// ProgrammaticMapViewController.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "ProgrammaticMapViewController.h" - -#import "RMMarker.h" -#import "RMProjection.h" -#import "RMAnnotation.h" -#import "RMQuadTree.h" - -#import "RMMBTilesSource.h" -#import "RMMapBoxSource.h" - -@implementation ProgrammaticMapViewController -{ - BOOL showsLocalTileSource; - CLLocationCoordinate2D center; -} - -@synthesize mapView; - -- (void)addMarkers -{ -#define kNumberRows 1 -#define kNumberColumns 9 -#define kSpacing 10.0 - - CLLocationCoordinate2D markerPosition; - - UIImage *redMarkerImage = [UIImage imageNamed:@"marker-red.png"]; - UIImage *blueMarkerImage = [UIImage imageNamed:@"marker-blue.png"]; - UIImage *xMarkerImage = [UIImage imageNamed:@"marker-X.png"]; - - markerPosition.latitude = center.latitude - ((kNumberRows - 1)/2.0 * kSpacing); - int i, j; - for (i = 0; i < kNumberRows; i++) - { - markerPosition.longitude = center.longitude - ((kNumberColumns - 1)/2.0 * kSpacing); - - for (j = 0; j < kNumberColumns; j++) - { - markerPosition.longitude += kSpacing; - NSLog(@"Add marker @ {%f,%f}", markerPosition.longitude, markerPosition.latitude); - - RMAnnotation *annotation = [RMAnnotation annotationWithMapView:self.mapView coordinate:markerPosition andTitle:[NSString stringWithFormat:@"%4.1f", markerPosition.longitude]]; - - if ((markerPosition.longitude < -180) ||(markerPosition.longitude > 0)) - { - annotation.annotationIcon = redMarkerImage; - annotation.anchorPoint = CGPointMake(0.5, 1.0); - } - else - { - annotation.annotationIcon = blueMarkerImage; - annotation.anchorPoint = CGPointMake(0.5, 1.0); - } - - [self.mapView addAnnotation:annotation]; - - annotation = [RMAnnotation annotationWithMapView:self.mapView coordinate:markerPosition andTitle:nil]; - annotation.annotationIcon = xMarkerImage; - annotation.anchorPoint = CGPointMake(0.5, 0.5); - - [self.mapView addAnnotation:annotation]; - } - - markerPosition.latitude += kSpacing; - } -} - -- (void)viewDidLoad -{ - NSLog(@"viewDidLoad"); - [super viewDidLoad]; - - center.latitude = 47.5635; - center.longitude = 10.20981; - - showsLocalTileSource = YES; - - NSURL *tilesURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"control-room-0.2.0" ofType:@"mbtiles"]]; - RMMBTilesSource *tileSource = [[[RMMBTilesSource alloc] initWithTileSetURL:tilesURL] autorelease]; - - self.mapView = [[[RMMapView alloc] initWithFrame:CGRectMake(10, 20, 300, 340) - andTilesource:tileSource - centerCoordinate:center - zoomLevel:1.5 - maxZoomLevel:[tileSource maxZoom] - minZoomLevel:[tileSource minZoom] - backgroundImage:nil] autorelease]; - - self.mapView.backgroundColor = [UIColor blackColor]; - self.mapView.delegate = self; - - [self.view addSubview:mapView]; - [self.view sendSubviewToBack:mapView]; - - [self performSelector:@selector(addMarkers) withObject:nil afterDelay:0.5]; -} - -- (void)dealloc -{ - [self.mapView removeFromSuperview]; - self.mapView = nil; - [super dealloc]; -} - -- (IBAction)swtichTilesource:(id)sender -{ - id newTileSource = nil; - - if (showsLocalTileSource) - { - showsLocalTileSource = NO; - - NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"geography-class" ofType:@"plist"]]; - newTileSource = [[[RMMapBoxSource alloc] initWithInfo:info] autorelease]; - } - else - { - showsLocalTileSource = YES; - - NSURL *tilesURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"control-room-0.2.0" ofType:@"mbtiles"]]; - newTileSource = [[[RMMBTilesSource alloc] initWithTileSetURL:tilesURL] autorelease]; - } - - self.mapView.tileSource = newTileSource; -} - -#pragma mark - -#pragma mark Delegate methods - -- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation -{ - RMMarker *marker = nil; - - if ([annotation.annotationType isEqualToString:kRMClusterAnnotationTypeName]) - { - marker = [[[RMMarker alloc] initWithUIImage:[UIImage imageNamed:@"marker-blue.png"] anchorPoint:annotation.anchorPoint] autorelease]; - - if (annotation.title) - { - marker.textForegroundColor = [UIColor whiteColor]; - [marker changeLabelUsingText:annotation.title]; - } - } - else - { - marker = [[[RMMarker alloc] initWithUIImage:annotation.annotationIcon anchorPoint:annotation.anchorPoint] autorelease]; - - if (annotation.title) - { - marker.textForegroundColor = [UIColor whiteColor]; - [marker changeLabelUsingText:annotation.title]; - } - } - - return marker; -} - -@end diff --git a/samples/MBTilesDemo/Info.plist b/samples/MBTilesDemo/Info.plist deleted file mode 100644 index 62bd89184..000000000 --- a/samples/MBTilesDemo/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.mobilegeographics.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/samples/MBTilesDemo/MBTilesDemo.xcodeproj/project.pbxproj b/samples/MBTilesDemo/MBTilesDemo.xcodeproj/project.pbxproj deleted file mode 100755 index 27d5fe283..000000000 --- a/samples/MBTilesDemo/MBTilesDemo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,348 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 160E121E14E02D43000E5EFB /* marker-blue.png in Resources */ = {isa = PBXBuildFile; fileRef = 160E121B14E02D43000E5EFB /* marker-blue.png */; }; - 160E121F14E02D43000E5EFB /* marker-red.png in Resources */ = {isa = PBXBuildFile; fileRef = 160E121C14E02D43000E5EFB /* marker-red.png */; }; - 160E122014E02D43000E5EFB /* marker-X.png in Resources */ = {isa = PBXBuildFile; fileRef = 160E121D14E02D43000E5EFB /* marker-X.png */; }; - 1611888B14D936E50054ED7A /* control-room-0.2.0.mbtiles in Resources */ = {isa = PBXBuildFile; fileRef = 1611888A14D936E50054ED7A /* control-room-0.2.0.mbtiles */; }; - 1611889214D937E00054ED7A /* geography-class.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1611889114D937E00054ED7A /* geography-class.plist */; }; - 1D3623260D0F684500981E51 /* ProgrammaticMapAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; - 2899E5220DE3E06400AC0155 /* ProgrammaticMapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */; }; - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; - 28D7ACF80DDB3853001CB0EB /* ProgrammaticMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */; }; - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */; }; - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */; }; - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */; }; - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; - 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 160E121B14E02D43000E5EFB /* marker-blue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-blue.png"; path = "../MarkerMurder/marker-blue.png"; sourceTree = ""; }; - 160E121C14E02D43000E5EFB /* marker-red.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-red.png"; path = "../MarkerMurder/marker-red.png"; sourceTree = ""; }; - 160E121D14E02D43000E5EFB /* marker-X.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-X.png"; path = "../MarkerMurder/marker-X.png"; sourceTree = ""; }; - 1611888A14D936E50054ED7A /* control-room-0.2.0.mbtiles */ = {isa = PBXFileReference; lastKnownFileType = file; path = "control-room-0.2.0.mbtiles"; sourceTree = ""; }; - 1611889114D937E00054ED7A /* geography-class.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "geography-class.plist"; sourceTree = ""; }; - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* ProgrammaticMapAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticMapAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticMapAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* MBTilesDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MBTilesDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ProgrammaticMapViewController.xib; sourceTree = ""; }; - 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 28D7ACF60DDB3853001CB0EB /* ProgrammaticMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticMapViewController.h; sourceTree = ""; }; - 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticMapViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = ""; }; - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 32CA4F630368D1EE00C91783 /* MBTilesDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBTilesDemo_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */, - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */, - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */, - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - 1D3623240D0F684500981E51 /* ProgrammaticMapAppDelegate.h */, - 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */, - 28D7ACF60DDB3853001CB0EB /* ProgrammaticMapViewController.h */, - 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */, - ); - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* MBTilesDemo.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */, - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* MBTilesDemo_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */, - 28AD733E0D9D9553002E5188 /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - 1611888A14D936E50054ED7A /* control-room-0.2.0.mbtiles */, - 1611889114D937E00054ED7A /* geography-class.plist */, - 160E121B14E02D43000E5EFB /* marker-blue.png */, - 160E121C14E02D43000E5EFB /* marker-red.png */, - 160E121D14E02D43000E5EFB /* marker-X.png */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */, - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */, - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765A40DF7441C002DB57D /* CoreGraphics.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */ = { - isa = PBXGroup; - children = ( - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* MBTilesDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MBTilesDemo" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */, - ); - name = MBTilesDemo; - productName = ProgrammaticMap; - productReference = 1D6058910D05DD3D006BFB54 /* MBTilesDemo.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MBTilesDemo" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */; - ProjectRef = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* MBTilesDemo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, - 2899E5220DE3E06400AC0155 /* ProgrammaticMapViewController.xib in Resources */, - 1611888B14D936E50054ED7A /* control-room-0.2.0.mbtiles in Resources */, - 1611889214D937E00054ED7A /* geography-class.plist in Resources */, - 160E121E14E02D43000E5EFB /* marker-blue.png in Resources */, - 160E121F14E02D43000E5EFB /* marker-red.png in Resources */, - 160E122014E02D43000E5EFB /* marker-X.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* ProgrammaticMapAppDelegate.m in Sources */, - 28D7ACF80DDB3853001CB0EB /* ProgrammaticMapViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MBTilesDemo_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - PRODUCT_NAME = MBTilesDemo; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MBTilesDemo_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - PRODUCT_NAME = MBTilesDemo; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.0; - SDKROOT = iphoneos; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MBTilesDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MBTilesDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/MBTilesDemo/MBTilesDemo_Prefix.pch b/samples/MBTilesDemo/MBTilesDemo_Prefix.pch deleted file mode 100644 index 092c26b68..000000000 --- a/samples/MBTilesDemo/MBTilesDemo_Prefix.pch +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'ProgrammaticMap' target in the 'ProgrammaticMap' project -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/samples/MBTilesDemo/MainWindow.xib b/samples/MBTilesDemo/MainWindow.xib deleted file mode 100644 index b411a1d09..000000000 --- a/samples/MBTilesDemo/MainWindow.xib +++ /dev/null @@ -1,206 +0,0 @@ - - - - 528 - 9E17 - 672 - 949.33 - 352.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - ProgrammaticMapViewController - - - - - 292 - {320, 480} - - 1 - MSAxIDEAA - - NO - NO - - - - - - YES - - - delegate - - - - 4 - - - - viewController - - - - 11 - - - - window - - - - 14 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - 3 - - - ProgrammaticMap App Delegate - - - -2 - - - - - 10 - - - - - 12 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 10.CustomClassName - 10.IBEditorWindowLastContentRect - 10.IBPluginDependency - 12.IBEditorWindowLastContentRect - 12.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - - - YES - UIApplication - UIResponder - ProgrammaticMapViewController - {{512, 351}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{525, 346}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - ProgrammaticMapAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 14 - - - - YES - - ProgrammaticMapAppDelegate - NSObject - - YES - - YES - viewController - window - - - YES - ProgrammaticMapViewController - UIWindow - - - - IBProjectSource - Classes/ProgrammaticMapAppDelegate.h - - - - ProgrammaticMapAppDelegate - NSObject - - IBUserSource - - - - - ProgrammaticMapViewController - UIViewController - - IBProjectSource - Classes/ProgrammaticMapViewController.h - - - - - 0 - ProgrammaticMap.xcodeproj - 3 - - diff --git a/samples/MBTilesDemo/ProgrammaticMapViewController.xib b/samples/MBTilesDemo/ProgrammaticMapViewController.xib deleted file mode 100644 index adcac13d7..000000000 --- a/samples/MBTilesDemo/ProgrammaticMapViewController.xib +++ /dev/null @@ -1,250 +0,0 @@ - - - - 528 - 10K549 - 1938 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 933 - - - YES - IBProxyObject - IBUIView - IBUIButton - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - YES - - - 292 - {{20, 403}, {280, 37}} - - - - NO - NO - IBCocoaTouchFramework - 0 - 0 - 1 - Switch the tile source - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - 3 - MAA - - - Helvetica-Bold - Helvetica - 2 - 15 - - - Helvetica-Bold - 15 - 16 - - - - {{0, 20}, {320, 460}} - - - - - 3 - MC43NQA - - 2 - - - NO - - IBCocoaTouchFramework - - - - - YES - - - view - - - - 7 - - - - swtichTilesource: - - - 7 - - 10 - - - - - YES - - 0 - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 6 - - - YES - - - - - - 8 - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 6.IBPluginDependency - 8.IBPluginDependency - - - YES - ProgrammaticMapViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 10 - - - - YES - - ProgrammaticMapViewController - UIViewController - - YES - - YES - doTheTest: - swtichTilesource: - - - YES - id - id - - - - YES - - YES - doTheTest: - swtichTilesource: - - - YES - - doTheTest: - id - - - swtichTilesource: - id - - - - - IBProjectSource - ./Classes/ProgrammaticMapViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - 933 - - diff --git a/samples/MBTilesDemo/control-room-0.2.0.mbtiles b/samples/MBTilesDemo/control-room-0.2.0.mbtiles deleted file mode 100644 index 1921b6cb8..000000000 Binary files a/samples/MBTilesDemo/control-room-0.2.0.mbtiles and /dev/null differ diff --git a/samples/MBTilesDemo/geography-class.plist b/samples/MBTilesDemo/geography-class.plist deleted file mode 100644 index 1cfdf5525..000000000 --- a/samples/MBTilesDemo/geography-class.plist +++ /dev/null @@ -1,48 +0,0 @@ - - - - - apiHostname - tiles.mapbox.com - apiPath - /mapbox - apiPort - 80 - apiScheme - http - attribution - - basename - geography-class.mbtiles - bounds - -179.9999250554491,-85.05112231458043,179.9999250554491,85.05112231458043 - center - 0,0,4 - description - One of the example maps that comes with TileMill - a bright & colorful world map that blends retro and high-tech with its folded paper texture and interactive flag tooltips. - formatter - function(options, data) { switch (options.format) { case 'full': return ''; break; case 'location': return ''; break; case 'teaser': default: return '<img src="data:image/png;base64,' + data.flagpng + '" style="box-shadow:0px 1px 5px #333;-moz-box-shadow:0px 1px 5px #333;-webkit-box-shadow:0px 1px 5px #333;" /><br /> <strong>' + data.ADMIN + '</strong>'; break; }} - gridURL - http://a.tiles.mapbox.com/mapbox/1.0.0/geography-class/{z}/{x}/{y}.grid.json - id - geography-class - maxzoom - 8 - minzoom - 0 - mtime - 1970-01-01T00:00:00Z - name - Geography Class - size - 0 - tileURL - http://a.tiles.mapbox.com/mapbox/1.0.0/geography-class/{z}/{x}/{y}.png - type - baselayer - version - 1.0.0 - scheme - tms - - diff --git a/samples/MBTilesDemo/main.m b/samples/MBTilesDemo/main.m deleted file mode 100644 index a02a4c0df..000000000 --- a/samples/MBTilesDemo/main.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// main.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/MapMemoryLeaksCheck/Classes/AppDelegate.h b/samples/MapMemoryLeaksCheck/Classes/AppDelegate.h deleted file mode 100644 index 0fc2fcfcd..000000000 --- a/samples/MapMemoryLeaksCheck/Classes/AppDelegate.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// ProgrammaticMapAppDelegate.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -@class MapViewController; - -@interface AppDelegate : NSObject -{ - UIWindow *window; - UINavigationController *navigationController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; - -@end - diff --git a/samples/MapMemoryLeaksCheck/Classes/AppDelegate.m b/samples/MapMemoryLeaksCheck/Classes/AppDelegate.m deleted file mode 100644 index b09332c44..000000000 --- a/samples/MapMemoryLeaksCheck/Classes/AppDelegate.m +++ /dev/null @@ -1,31 +0,0 @@ -// -// ProgrammaticMapAppDelegate.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "AppDelegate.h" -#import "RootViewController.h" - -@implementation AppDelegate - -@synthesize window; - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - navigationController = [[UINavigationController alloc] initWithRootViewController:[[[RootViewController alloc] initWithNibName:nil bundle:nil] autorelease]]; - - [window addSubview:navigationController.view]; - [window makeKeyAndVisible]; -} - -- (void)dealloc -{ - [navigationController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/MapMemoryLeaksCheck/Classes/MapViewController.h b/samples/MapMemoryLeaksCheck/Classes/MapViewController.h deleted file mode 100644 index a2ee40e48..000000000 --- a/samples/MapMemoryLeaksCheck/Classes/MapViewController.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// ProgrammaticMapViewController.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -@class RMMapView; - -@interface MapViewController : UIViewController -{ - RMMapView *mapView; -} - -@property (nonatomic,retain) RMMapView *mapView; - -@end - diff --git a/samples/MapMemoryLeaksCheck/Classes/MapViewController.m b/samples/MapMemoryLeaksCheck/Classes/MapViewController.m deleted file mode 100644 index 7c73ac42c..000000000 --- a/samples/MapMemoryLeaksCheck/Classes/MapViewController.m +++ /dev/null @@ -1,39 +0,0 @@ -// -// ProgrammaticMapViewController.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "MapViewController.h" -#import "RMMapView.h" - -@implementation MapViewController - -@synthesize mapView; - -- (void)viewDidLoad -{ - NSLog(@" => mapView viewDidLoad"); - [super viewDidLoad]; - - CLLocationCoordinate2D firstLocation; - firstLocation.latitude = 51.2795; - firstLocation.longitude = 1.082; - - self.mapView = [[[RMMapView alloc] initWithFrame:CGRectMake(10, 20, 300, 340)] autorelease]; - [mapView setBackgroundColor:[UIColor greenColor]]; - [self.view addSubview:mapView]; - [self.view sendSubviewToBack:mapView]; -} - -- (void)dealloc -{ - NSLog(@" => mapView dealloc"); - [mapView removeFromSuperview]; - self.mapView = nil; - [super dealloc]; -} - -@end diff --git a/samples/MapMemoryLeaksCheck/Classes/RootViewController.h b/samples/MapMemoryLeaksCheck/Classes/RootViewController.h deleted file mode 100644 index cddd33a86..000000000 --- a/samples/MapMemoryLeaksCheck/Classes/RootViewController.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// RootViewController.h -// MapMemoryLeaksCheck -// -// Created by Thomas Rasch on 11.10.11. -// Copyright (c) 2011 Alpstein. All rights reserved. -// - -#import - -@interface RootViewController : UIViewController - -@end diff --git a/samples/MapMemoryLeaksCheck/Classes/RootViewController.m b/samples/MapMemoryLeaksCheck/Classes/RootViewController.m deleted file mode 100644 index 49a621f68..000000000 --- a/samples/MapMemoryLeaksCheck/Classes/RootViewController.m +++ /dev/null @@ -1,42 +0,0 @@ -// -// RootViewController.m -// MapMemoryLeaksCheck -// -// Created by Thomas Rasch on 11.10.11. -// Copyright (c) 2011 Alpstein. All rights reserved. -// - -#import "RootViewController.h" - -#import "MapViewController.h" - -@implementation RootViewController - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil -{ - if (!(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) - return nil; - - return self; -} - -- (void)loadView -{ - [super loadView]; - - CGRect bounds = self.view.bounds; - - UIButton *showMapButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; - showMapButton.frame = CGRectMake(10.0, bounds.size.height - 100.0, bounds.size.width-20.0, 44.0); - [showMapButton setTitle:@"Show the map" forState:UIControlStateNormal]; - [showMapButton addTarget:self action:@selector(showTheMap) forControlEvents:UIControlEventTouchUpInside]; - [self.view addSubview:showMapButton]; -} - -- (void)showTheMap -{ - MapViewController *mapViewController = [[[MapViewController alloc] initWithNibName:nil bundle:nil] autorelease]; - [self.navigationController pushViewController:mapViewController animated:YES]; -} - -@end diff --git a/samples/MapMemoryLeaksCheck/Info.plist b/samples/MapMemoryLeaksCheck/Info.plist deleted file mode 100644 index daf7f7639..000000000 --- a/samples/MapMemoryLeaksCheck/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.mobilegeographics.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - - - diff --git a/samples/MapMemoryLeaksCheck/MainWindow.xib b/samples/MapMemoryLeaksCheck/MainWindow.xib deleted file mode 100644 index 34096ad59..000000000 --- a/samples/MapMemoryLeaksCheck/MainWindow.xib +++ /dev/null @@ -1,190 +0,0 @@ - - - - 528 - 10K549 - 1938 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 933 - - - YES - IBProxyObject - IBUICustomObject - IBUIWindow - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - IBCocoaTouchFramework - - - - 292 - {320, 480} - - - - - 1 - MSAxIDEAA - - NO - NO - - IBCocoaTouchFramework - - - - - YES - - - delegate - - - - 4 - - - - window - - - - 14 - - - - - YES - - 0 - - YES - - - - - - -1 - - - File's Owner - - - 3 - - - ProgrammaticMap App Delegate - - - -2 - - - - - 12 - - - YES - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 12.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - - - YES - UIApplication - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - AppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 17 - - - - YES - - AppDelegate - NSObject - - window - UIWindow - - - window - - window - UIWindow - - - - IBProjectSource - ./Classes/AppDelegate.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - 933 - - diff --git a/samples/MapMemoryLeaksCheck/MapMemoryLeaksCheck.xcodeproj/project.pbxproj b/samples/MapMemoryLeaksCheck/MapMemoryLeaksCheck.xcodeproj/project.pbxproj deleted file mode 100755 index 571a11f02..000000000 --- a/samples/MapMemoryLeaksCheck/MapMemoryLeaksCheck.xcodeproj/project.pbxproj +++ /dev/null @@ -1,336 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1611CFD614442C49006E802E /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1611CFD514442C49006E802E /* RootViewController.m */; }; - 1611D0391444579D006E802E /* error.png in Resources */ = {isa = PBXBuildFile; fileRef = 1611D0381444579D006E802E /* error.png */; }; - 1D3623260D0F684500981E51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; - 28D7ACF80DDB3853001CB0EB /* MapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* MapViewController.m */; }; - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */; }; - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */; }; - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */; }; - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; - 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1611CFD414442C49006E802E /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; - 1611CFD514442C49006E802E /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; - 1611D0381444579D006E802E /* error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = error.png; sourceTree = ""; }; - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* MapMemoryLeaksCheck.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MapMemoryLeaksCheck.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 28D7ACF60DDB3853001CB0EB /* MapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapViewController.h; sourceTree = ""; }; - 28D7ACF70DDB3853001CB0EB /* MapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MapViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = ""; }; - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 32CA4F630368D1EE00C91783 /* MapMemoryLeaksCheck_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapMemoryLeaksCheck_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */, - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */, - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */, - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - 1D3623240D0F684500981E51 /* AppDelegate.h */, - 1D3623250D0F684500981E51 /* AppDelegate.m */, - 1611CFD414442C49006E802E /* RootViewController.h */, - 1611CFD514442C49006E802E /* RootViewController.m */, - 28D7ACF60DDB3853001CB0EB /* MapViewController.h */, - 28D7ACF70DDB3853001CB0EB /* MapViewController.m */, - ); - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* MapMemoryLeaksCheck.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */, - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* MapMemoryLeaksCheck_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 1611D0381444579D006E802E /* error.png */, - 28AD733E0D9D9553002E5188 /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */, - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */, - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765A40DF7441C002DB57D /* CoreGraphics.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */ = { - isa = PBXGroup; - children = ( - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* MapMemoryLeaksCheck */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MapMemoryLeaksCheck" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */, - ); - name = MapMemoryLeaksCheck; - productName = ProgrammaticMap; - productReference = 1D6058910D05DD3D006BFB54 /* MapMemoryLeaksCheck.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapMemoryLeaksCheck" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */; - ProjectRef = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* MapMemoryLeaksCheck */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, - 1611D0391444579D006E802E /* error.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* AppDelegate.m in Sources */, - 28D7ACF80DDB3853001CB0EB /* MapViewController.m in Sources */, - 1611CFD614442C49006E802E /* RootViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapMemoryLeaksCheck_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 4.1; - PRODUCT_NAME = MapMemoryLeaksCheck; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapMemoryLeaksCheck_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 4.1; - PRODUCT_NAME = MapMemoryLeaksCheck; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.1; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.1; - SDKROOT = iphoneos; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MapMemoryLeaksCheck" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapMemoryLeaksCheck" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/MapMemoryLeaksCheck/MapMemoryLeaksCheck_Prefix.pch b/samples/MapMemoryLeaksCheck/MapMemoryLeaksCheck_Prefix.pch deleted file mode 100644 index 092c26b68..000000000 --- a/samples/MapMemoryLeaksCheck/MapMemoryLeaksCheck_Prefix.pch +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'ProgrammaticMap' target in the 'ProgrammaticMap' project -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/samples/MapMemoryLeaksCheck/error.png b/samples/MapMemoryLeaksCheck/error.png deleted file mode 100644 index 93cafb0f5..000000000 Binary files a/samples/MapMemoryLeaksCheck/error.png and /dev/null differ diff --git a/samples/MapMemoryLeaksCheck/main.m b/samples/MapMemoryLeaksCheck/main.m deleted file mode 100644 index a02a4c0df..000000000 --- a/samples/MapMemoryLeaksCheck/main.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// main.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/MapTestbed/Classes/FlipsideView.h b/samples/MapTestbed/Classes/FlipsideView.h deleted file mode 100644 index 4134079a8..000000000 --- a/samples/MapTestbed/Classes/FlipsideView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// FlipsideView.h -// MapTestbed : Diagnostic map -// - -#import - -@interface FlipsideView : UIView -{ -} - -@end diff --git a/samples/MapTestbed/Classes/FlipsideView.m b/samples/MapTestbed/Classes/FlipsideView.m deleted file mode 100644 index de0911002..000000000 --- a/samples/MapTestbed/Classes/FlipsideView.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// FlipsideView.m -// MapTestbed : Diagnostic map -// - -#import "FlipsideView.h" - -@implementation FlipsideView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return nil; - - return self; -} - -- (void)drawRect:(CGRect)rect -{ - // Drawing code -} - -- (void)dealloc -{ - [super dealloc]; -} - -@end diff --git a/samples/MapTestbed/Classes/FlipsideViewController.h b/samples/MapTestbed/Classes/FlipsideViewController.h deleted file mode 100644 index 34def1ee2..000000000 --- a/samples/MapTestbed/Classes/FlipsideViewController.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// FlipsideViewController.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@interface FlipsideViewController : UIViewController -{ - IBOutlet UITextField *centerLatitude; - IBOutlet UITextField *centerLongitude; - IBOutlet UITextField *zoomLevel; - IBOutlet UITextField *minZoom; - IBOutlet UITextField *maxZoom; - RMMapView *mapView; -} - -@property(nonatomic,retain) IBOutlet UITextField *centerLatitude; -@property(nonatomic,retain) IBOutlet UITextField *centerLongitude; -@property(nonatomic,retain) IBOutlet UITextField *zoomLevel; -@property(nonatomic,retain) IBOutlet UITextField *minZoom; -@property(nonatomic,retain) IBOutlet UITextField *maxZoom; - -@end diff --git a/samples/MapTestbed/Classes/FlipsideViewController.m b/samples/MapTestbed/Classes/FlipsideViewController.m deleted file mode 100644 index d80ee1656..000000000 --- a/samples/MapTestbed/Classes/FlipsideViewController.m +++ /dev/null @@ -1,73 +0,0 @@ -// -// FlipsideViewController.m -// MapTestbed : Diagnostic map -// - -#import "FlipsideViewController.h" -#import "MapTestbedAppDelegate.h" -#import "RootViewController.h" -#import "MainViewController.h" - -@implementation FlipsideViewController - -@synthesize centerLatitude; -@synthesize centerLongitude; -@synthesize zoomLevel; -@synthesize minZoom; -@synthesize maxZoom; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - mapView = [[[(MapTestbedAppDelegate *)[[UIApplication sharedApplication] delegate] rootViewController] mainViewController] mapView]; - - self.view.backgroundColor = [UIColor groupTableViewBackgroundColor]; -} - -// Override to allow orientations other than the default portrait orientation. -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - // Return YES for supported orientations - return YES; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)viewDidAppear:(BOOL)animated -{ - CLLocationCoordinate2D mapCenter = [mapView centerCoordinate]; - - [centerLatitude setText:[NSString stringWithFormat:@"%f", mapCenter.latitude]]; - [centerLongitude setText:[NSString stringWithFormat:@"%f", mapCenter.longitude]]; - [zoomLevel setText:[NSString stringWithFormat:@"%f", mapView.zoom]]; - [maxZoom setText:[NSString stringWithFormat:@"%f", mapView.maxZoom]]; - [minZoom setText:[NSString stringWithFormat:@"%f", mapView.minZoom]]; -} - -- (void)viewWillDisappear:(BOOL)animated -{ - CLLocationCoordinate2D newMapCenter; - - newMapCenter.latitude = [[centerLatitude text] doubleValue]; - newMapCenter.longitude = [[centerLongitude text] doubleValue]; - [mapView setCenterCoordinate:newMapCenter]; - [mapView setZoom:[[zoomLevel text] floatValue]]; - [mapView setMaxZoom:[[maxZoom text] floatValue]]; - [mapView setMinZoom:[[minZoom text] floatValue]]; -} - -- (void)dealloc -{ - self.centerLatitude = nil; - self.centerLongitude = nil; - self.zoomLevel = nil; - self.minZoom = nil; - self.maxZoom = nil; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbed/Classes/MainView.h b/samples/MapTestbed/Classes/MainView.h deleted file mode 100644 index ea20e09ea..000000000 --- a/samples/MapTestbed/Classes/MainView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// MainView.h -// MapTestbed : Diagnostic map -// - -#import - -@interface MainView : UIView -{ -} - -@end diff --git a/samples/MapTestbed/Classes/MainView.m b/samples/MapTestbed/Classes/MainView.m deleted file mode 100644 index f350d1b7c..000000000 --- a/samples/MapTestbed/Classes/MainView.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// MainView.m -// MapTestbed : Diagnostic map -// - -#import "MainView.h" - -@implementation MainView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return nil; - - return self; -} - -- (void)drawRect:(CGRect)rect -{ - // Drawing code -} - -- (void)dealloc -{ - [super dealloc]; -} - -@end diff --git a/samples/MapTestbed/Classes/MainViewController.h b/samples/MapTestbed/Classes/MainViewController.h deleted file mode 100644 index 1588f45f6..000000000 --- a/samples/MapTestbed/Classes/MainViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// MainViewController.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@interface MainViewController : UIViewController -{ - IBOutlet RMMapView * mapView; - IBOutlet UITextView * infoTextView; -} - -@property (nonatomic, retain) IBOutlet RMMapView *mapView; -@property (nonatomic, retain) IBOutlet UITextView *infoTextView; - -- (void)updateInfo; - -@end diff --git a/samples/MapTestbed/Classes/MainViewController.m b/samples/MapTestbed/Classes/MainViewController.m deleted file mode 100644 index 4ba8f167f..000000000 --- a/samples/MapTestbed/Classes/MainViewController.m +++ /dev/null @@ -1,120 +0,0 @@ -// -// MainViewController.m -// MapTestbed : Diagnostic map -// - -#import "MainViewController.h" -#import "MapTestbedAppDelegate.h" - -#import "MainView.h" -#import "RMPath.h" -#import "RMShape.h" -#import "RMMarker.h" -#import "RMAnnotation.h" - -@implementation MainViewController - -@synthesize mapView; -@synthesize infoTextView; - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil -{ - if (!(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) - return nil; - - return self; -} - -// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. -- (void)viewDidLoad -{ - [super viewDidLoad]; - mapView.delegate = self; - mapView.decelerationMode = RMMapDecelerationNormal; - [self updateInfo]; -} - -// Override to allow orientations other than the default portrait orientation. -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - // Return YES for supported orientations - return YES; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)viewDidAppear:(BOOL)animated -{ - [self updateInfo]; -} - -- (void)dealloc -{ - self.infoTextView = nil; - self.mapView = nil; - [super dealloc]; -} - -- (void)updateInfo -{ - CLLocationCoordinate2D mapCenter = [self.mapView centerCoordinate]; - - float routemeMetersPerPixel = [self.mapView metersPerPixel]; - double truescaleDenominator = [self.mapView scaleDenominator]; - - [infoTextView setText:[NSString stringWithFormat:@"Latitude : %f\nLongitude : %f\nZoom level : %.2f\nMeter per pixel : %.1f\nTrue scale : 1:%.0f", - mapCenter.latitude, - mapCenter.longitude, - self.mapView.zoom, - routemeMetersPerPixel, - truescaleDenominator]]; -} - -#pragma mark - -#pragma mark Delegate methods - -- (void)afterMapMove:(RMMapView *)map -{ - [self updateInfo]; -} - -- (void)afterMapZoom:(RMMapView *)map -{ - [self updateInfo]; -} - -- (RMMapLayer *)mapView:(RMMapView *)aMapView layerForAnnotation:(RMAnnotation *)annotation -{ - if ([annotation.annotationType isEqualToString:@"path"]) - { -// RMPath *testPath = [[[RMPath alloc] initWithView:aMapView] autorelease]; - RMShape *testPath = [[[RMShape alloc] initWithView:aMapView] autorelease]; - [testPath setLineColor:[annotation.userInfo objectForKey:@"lineColor"]]; - [testPath setFillColor:[annotation.userInfo objectForKey:@"fillColor"]]; - [testPath setLineWidth:[[annotation.userInfo objectForKey:@"lineWidth"] floatValue]]; -// testPath.scaleLineWidth = YES; - - if ([[annotation.userInfo objectForKey:@"closePath"] boolValue]) - [testPath closePath]; - - for (CLLocation *location in [annotation.userInfo objectForKey:@"linePoints"]) - { - [testPath addLineToCoordinate:location.coordinate]; - } - - return testPath; - } - - if ([annotation.annotationType isEqualToString:@"marker"]) - { - return [[[RMMarker alloc] initWithUIImage:annotation.annotationIcon anchorPoint:annotation.anchorPoint] autorelease]; - } - - return nil; -} - -@end diff --git a/samples/MapTestbed/Classes/MapTestbedAppDelegate.h b/samples/MapTestbed/Classes/MapTestbedAppDelegate.h deleted file mode 100644 index 227fb9823..000000000 --- a/samples/MapTestbed/Classes/MapTestbedAppDelegate.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// MapTestbedAppDelegate.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@class RootViewController; -@class RMMapContents; - -@interface MapTestbedAppDelegate : NSObject -{ - UIWindow *window; - RootViewController *rootViewController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet RootViewController *rootViewController; - -@end - diff --git a/samples/MapTestbed/Classes/MapTestbedAppDelegate.m b/samples/MapTestbed/Classes/MapTestbedAppDelegate.m deleted file mode 100644 index 0386e688c..000000000 --- a/samples/MapTestbed/Classes/MapTestbedAppDelegate.m +++ /dev/null @@ -1,135 +0,0 @@ -// -// MapTestbedAppDelegate.m -// MapTestbed : Diagnostic map -// - -#import "MapTestbedAppDelegate.h" -#import "RootViewController.h" -#import "MainViewController.h" - -#import "RMAnnotation.h" - -@implementation MapTestbedAppDelegate - -@synthesize window; -@synthesize rootViewController; - -- (RMMapView *)mapView -{ - return [[[(MapTestbedAppDelegate *)[[UIApplication sharedApplication] delegate] rootViewController] mainViewController] mapView]; -} - --(void)performTestPart2 -{ - CLLocationCoordinate2D pt; - pt.latitude = 48.86600492029781f; - pt.longitude = 2.3194026947021484f; - - [[self mapView] setCenterCoordinate:pt animated:NO]; -} - --(void)performTestPart3 -{ - // path returns to correct position after this zoom - CLLocationCoordinate2D northeast, southwest; - northeast.latitude = 48.885875363989435f; - northeast.longitude = 2.338285446166992f; - southwest.latitude = 48.860406466081656f; - southwest.longitude = 2.2885894775390625; - - [[self mapView] zoomWithLatitudeLongitudeBoundsSouthWest:southwest northEast:northeast animated:NO]; -} - -- (void)performTest -{ - NSLog(@"testing paths"); - RMMapView *mapView = [self mapView]; - - UIImage *xMarkerImage = [UIImage imageNamed:@"marker-X.png"]; - - // if we zoom with bounds after the paths are created, nothing is displayed on the map - CLLocationCoordinate2D northeast = CLLocationCoordinate2DMake(48.885875363989435f, 2.338285446166992f), - southwest = CLLocationCoordinate2DMake(48.860406466081656f, 2.2885894775390625); - - [mapView zoomWithLatitudeLongitudeBoundsSouthWest:southwest northEast:northeast animated:NO]; - - NSArray *linePoints = [NSArray arrayWithObjects: - [[[CLLocation alloc] initWithLatitude:48.884238608729035f longitude:2.297086715698242f] autorelease], - [[[CLLocation alloc] initWithLatitude:48.878481319827735f longitude:2.294340133666992f] autorelease], - [[[CLLocation alloc] initWithLatitude:48.87351371451778f longitude:2.2948551177978516f] autorelease], - [[[CLLocation alloc] initWithLatitude:48.86600492029781f longitude:2.3194026947021484f] autorelease], - nil]; - - // draw a green path south down an avenue and southeast on Champs-Elysees - RMAnnotation *pathAnnotation = [RMAnnotation annotationWithMapView:mapView coordinate:((CLLocation *)[linePoints objectAtIndex:0]).coordinate andTitle:nil]; - pathAnnotation.annotationType = @"path"; - pathAnnotation.userInfo = [NSDictionary dictionaryWithObjectsAndKeys: - linePoints,@"linePoints", - [UIColor greenColor],@"lineColor", - [UIColor clearColor],@"fillColor", - [NSNumber numberWithFloat:20.0f],@"lineWidth", - nil]; - [pathAnnotation setBoundingBoxFromLocations:linePoints]; - [mapView addAnnotation:pathAnnotation]; - - for (NSUInteger i=0; i<[linePoints count]; ++i) - { - CLLocation *currentLocation = [linePoints objectAtIndex:i]; - - RMAnnotation *markerAnnotation = [RMAnnotation annotationWithMapView:mapView coordinate:currentLocation.coordinate andTitle:[NSString stringWithFormat:@"R %d", i+1]]; - markerAnnotation.annotationType = @"marker"; - markerAnnotation.annotationIcon = xMarkerImage; - markerAnnotation.anchorPoint = CGPointMake(0.5, 1.0); - [mapView addAnnotation:markerAnnotation]; - } - - linePoints = [NSArray arrayWithObjects: - [[[CLLocation alloc] initWithLatitude:48.86637615203047f longitude:2.3236513137817383f] autorelease], - [[[CLLocation alloc] initWithLatitude:48.86372241857954f longitude:2.321462631225586f] autorelease], - [[[CLLocation alloc] initWithLatitude:48.86087090984738f longitude:2.330174446105957f] autorelease], - [[[CLLocation alloc] initWithLatitude:48.86369418661614f longitude:2.332019805908203f] autorelease], - nil]; - - pathAnnotation = [RMAnnotation annotationWithMapView:mapView coordinate:((CLLocation *)[linePoints objectAtIndex:0]).coordinate andTitle:nil]; - pathAnnotation.annotationType = @"path"; - pathAnnotation.userInfo = [NSDictionary dictionaryWithObjectsAndKeys: - linePoints,@"linePoints", - [UIColor blueColor],@"lineColor", - [UIColor colorWithRed:0.1 green:0.1 blue:0.8 alpha:0.5],@"fillColor", - [NSNumber numberWithFloat:10.0f],@"lineWidth", - [NSNumber numberWithBool:YES],@"closePath", - nil]; - [pathAnnotation setBoundingBoxFromLocations:linePoints]; - [mapView addAnnotation:pathAnnotation]; - - for (NSUInteger i=0; i<[linePoints count]; ++i) - { - CLLocation *currentLocation = [linePoints objectAtIndex:i]; - - RMAnnotation *markerAnnotation = [RMAnnotation annotationWithMapView:mapView coordinate:currentLocation.coordinate andTitle:[NSString stringWithFormat:@"S %d", i+1]]; - markerAnnotation.annotationType = @"marker"; - markerAnnotation.annotationIcon = xMarkerImage; - markerAnnotation.anchorPoint = CGPointMake(0.5, 1.0); - [mapView addAnnotation:markerAnnotation]; - } - -// [self performSelector:@selector(performTestPart2) withObject:nil afterDelay:3.0f]; -// [self performSelector:@selector(performTestPart3) withObject:nil afterDelay:7.0f]; -} - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - [window addSubview:[rootViewController view]]; - [window makeKeyAndVisible]; - - [self performSelector:@selector(performTest) withObject:nil afterDelay:0.25f]; -} - -- (void)dealloc -{ - [rootViewController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbed/Classes/RootViewController.h b/samples/MapTestbed/Classes/RootViewController.h deleted file mode 100644 index cc575e72d..000000000 --- a/samples/MapTestbed/Classes/RootViewController.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// RootViewController.h -// MapTestbed : Diagnostic map -// - -#import - -@class MainViewController; -@class FlipsideViewController; - -@interface RootViewController : UIViewController -{ - UIButton *infoButton; - MainViewController *mainViewController; - FlipsideViewController *flipsideViewController; - UINavigationBar *flipsideNavigationBar; -} - -@property (nonatomic, retain) IBOutlet UIButton *infoButton; -@property (nonatomic, retain) MainViewController *mainViewController; -@property (nonatomic, retain) UINavigationBar *flipsideNavigationBar; -@property (nonatomic, retain) FlipsideViewController *flipsideViewController; - -- (IBAction)toggleView; - -@end diff --git a/samples/MapTestbed/Classes/RootViewController.m b/samples/MapTestbed/Classes/RootViewController.m deleted file mode 100644 index 3193e08a8..000000000 --- a/samples/MapTestbed/Classes/RootViewController.m +++ /dev/null @@ -1,108 +0,0 @@ -// -// RootViewController.m -// MapTestbed : Diagnostic map -// - -#import "RootViewController.h" -#import "MainViewController.h" -#import "FlipsideViewController.h" - -@implementation RootViewController - -@synthesize infoButton; -@synthesize flipsideNavigationBar; -@synthesize mainViewController; -@synthesize flipsideViewController; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - MainViewController *viewController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil]; - self.mainViewController = viewController; - [viewController release]; - - [self.view insertSubview:mainViewController.view belowSubview:infoButton]; -} - -- (void)loadFlipsideViewController -{ - FlipsideViewController *viewController = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil]; - self.flipsideViewController = viewController; - [viewController release]; - - // Set up the navigation bar - UINavigationBar *aNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)]; - aNavigationBar.barStyle = UIBarStyleBlackOpaque; - self.flipsideNavigationBar = aNavigationBar; - [aNavigationBar release]; - - UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(toggleView)]; - UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"MapTestbed"]; - navigationItem.rightBarButtonItem = buttonItem; - [flipsideNavigationBar pushNavigationItem:navigationItem animated:NO]; - [navigationItem release]; - [buttonItem release]; -} - -- (IBAction)toggleView -{ - /* - This method is called when the info or Done button is pressed. - It flips the displayed view from the main view to the flipside view and vice-versa. - */ - if (flipsideViewController == nil) - [self loadFlipsideViewController]; - - UIView *mainView = mainViewController.view; - UIView *flipsideView = flipsideViewController.view; - - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:1]; - [UIView setAnimationTransition:([mainView superview] ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES]; - - if ([mainView superview] != nil) { - [flipsideViewController viewWillAppear:YES]; - [mainViewController viewWillDisappear:YES]; - [mainView removeFromSuperview]; - [infoButton removeFromSuperview]; - [self.view addSubview:flipsideView]; - [self.view insertSubview:flipsideNavigationBar aboveSubview:flipsideView]; - [mainViewController viewDidDisappear:YES]; - [flipsideViewController viewDidAppear:YES]; - - } else { - [mainViewController viewWillAppear:YES]; - [flipsideViewController viewWillDisappear:YES]; - [flipsideView removeFromSuperview]; - [flipsideNavigationBar removeFromSuperview]; - [self.view addSubview:mainView]; - [self.view insertSubview:infoButton aboveSubview:mainViewController.view]; - [flipsideViewController viewDidDisappear:YES]; - [mainViewController viewDidAppear:YES]; - } - [UIView commitAnimations]; -} - -// Override to allow orientations other than the default portrait orientation. -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - // Return YES for supported orientations - return YES; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)dealloc -{ - [infoButton release]; - [flipsideNavigationBar release]; - [mainViewController release]; - [flipsideViewController release]; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbed/FlipsideView.xib b/samples/MapTestbed/FlipsideView.xib deleted file mode 100644 index d5e010f90..000000000 --- a/samples/MapTestbed/FlipsideView.xib +++ /dev/null @@ -1,495 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 274 - - YES - - - 292 - {{20, 61}, {175, 21}} - - NO - YES - NO - Map center latitude - - 1 - MCAwIDAAA - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 170}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - 2 - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 95}, {175, 21}} - - NO - YES - NO - Map center longitude - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 136}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 141}, {175, 21}} - - NO - YES - NO - Zoom level - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 204}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 209}, {175, 21}} - - NO - YES - NO - Zoom Minimun - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 90}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 175}, {175, 21}} - - NO - YES - NO - Zoom Maximum - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 58}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - {320, 460} - - - 1 - MC44Njk1NjUyNSAwLjg2OTU2NTI1IDAuODY5NTY1MjUAA - - NO - - 2 - - - - - - YES - - - view - - - - 41 - - - - centerLatitude - - - - 65 - - - - centerLongitude - - - - 66 - - - - zoomLevel - - - - 67 - - - - maxZoom - - - - 68 - - - - minZoom - - - - 69 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - -2 - - - - - 40 - - - YES - - - - - - - - - - - - - - - 42 - - - - - 43 - - - - - 44 - - - - - 45 - - - - - 46 - - - - - 47 - - - - - 48 - - - - - 49 - - - - - 50 - - - - - 51 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 40.CustomClassName - 40.IBEditorWindowLastContentRect - 40.IBPluginDependency - 40.IBUserGuides - 42.IBPluginDependency - 43.IBPluginDependency - 44.IBPluginDependency - 45.IBPluginDependency - 46.IBPluginDependency - 47.IBPluginDependency - 48.IBPluginDependency - 49.IBPluginDependency - 50.IBPluginDependency - 51.IBPluginDependency - - - YES - FlipsideViewController - UIResponder - FlipsideView - {{637, 393}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - YES - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 69 - - - - YES - - FlipsideView - UIView - - IBProjectSource - Classes/FlipsideView.h - - - - FlipsideViewController - UIViewController - - YES - - YES - centerLatitude - centerLongitude - maxZoom - minZoom - zoomLevel - - - YES - UITextField - UITextField - UITextField - UITextField - UITextField - - - - IBProjectSource - Classes/FlipsideViewController.h - - - - - 0 - MapTestbed.xcodeproj - 3 - - diff --git a/samples/MapTestbed/Info.plist b/samples/MapTestbed/Info.plist deleted file mode 100644 index fdf834060..000000000 --- a/samples/MapTestbed/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/samples/MapTestbed/MainView.xib b/samples/MapTestbed/MainView.xib deleted file mode 100644 index ad38d3d32..000000000 --- a/samples/MapTestbed/MainView.xib +++ /dev/null @@ -1,260 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 274 - - YES - - - 274 - - YES - - - 274 - {{0, 342}, {320, 118}} - - - 1 - MC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC42OTk5OTk5OQA - - NO - YES - YES - NO - NO - NO - NO - NO - Ly8KLy8gIE1haW5WaWV3Q29udHJvbGxlci5tCi8vICBTYW1wbGUyIDogRGlhZ25vc3RpYyBtYXAKLy8K -CiNpbXBvcnQgIk1haW5WaWV3Q29udHJvbGxlci5oIgojaW1wb3J0ICJNYWluVmlldy5oIgoKQGltcGxl -bWVudGF0aW9uIE1haW5WaWV3Q29udHJvbGxlcgoKQHN5bnRoZXNpemUgbWFwVmlldzsKQHN5bnRoZXNp -emUgdGV4dFZpZXc7CgotIChpZClpbml0V2l0aE5pYk5hbWU6KE5TU3RyaW5nICopbmliTmFtZU9yTmls -IGJ1bmRsZTooTlNCdW5kbGUgKiluaWJCdW5kbGVPck5pbCB7CiAgICBpZiAoc2VsZiA9IFtzdXBlciBp -bml0V2l0aE5pYk5hbWU6bmliTmFtZU9yTmlsIGJ1bmRsZTpuaWJCdW5kbGVPck5pbF0pIHsKICAgICAg -ICAvLyBDdXN0b20gaW5pdGlhbGl6YXRpb24KICAgIH0KICAgIHJldHVybiBzZWxmOwp9CgoKLy8gSW1w -bGVtZW50IHZpZXdEaWRMb2FkIHRvIGRvIGFkZGl0aW9uYWwgc2V0dXAgYWZ0ZXIgbG9hZGluZyB0aGUg -dmlldywgdHlwaWNhbGx5IGZyb20gYSBuaWIuCi0gKHZvaWQpdmlld0RpZExvYWQgewogICAgW3N1cGVy -IHZpZXdEaWRMb2FkXTsKICAgIFt0ZXh0VmlldyBzZXRUZXh0OkAidG90byBlc3QgZW4gdmFjYW5jZXMi -XTsKfQoKCi8qCiAvLyBPdmVycmlkZSB0byBhbGxvdyBvcmllbnRhdGlvbnMgb3RoZXIgdGhhbiB0aGUg -ZGVmYXVsdCBwb3J0cmFpdCBvcmllbnRhdGlvbi4KIC0gKEJPT0wpc2hvdWxkQXV0b3JvdGF0ZVRvSW50 -ZXJmYWNlT3JpZW50YXRpb246KFVJSW50ZXJmYWNlT3JpZW50YXRpb24paW50ZXJmYWNlT3JpZW50YXRp -b24gewogLy8gUmV0dXJuIFlFUyBmb3Igc3VwcG9ydGVkIG9yaWVudGF0aW9ucwogcmV0dXJuIChpbnRl -cmZhY2VPcmllbnRhdGlvbiA9PSBVSUludGVyZmFjZU9yaWVudGF0aW9uUG9ydHJhaXQpOwogfQoqLwoK -Ci0gKHZvaWQpZGlkUmVjZWl2ZU1lbW9yeVdhcm5pbmcgewogICAgW3N1cGVyIGRpZFJlY2VpdmVNZW1v -cnlXYXJuaW5nXTsgLy8gUmVsZWFzZXMgdGhlIHZpZXcgaWYgaXQgZG9lc24ndCBoYXZlIGEgc3VwZXJ2 -aWV3CiAgICAvLyBSZWxlYXNlIGFueXRoaW5nIHRoYXQncyBub3QgZXNzZW50aWFsLCBzdWNoIGFzIGNh -Y2hlZCBkYXRhCn0KCgotICh2b2lkKWRlYWxsb2MgewogICAgW3N1cGVyIGRlYWxsb2NdOwp9CgoKQGVu -ZAo - - 3 - MQA - - - - {320, 460} - - - 3 - MQA - - 2 - - - NO - YES - - - {320, 460} - - - 3 - MQA - - - NO - - - - - YES - - - view - - - - 40 - - - - mapView - - - - 41 - - - - infoTextView - - - - 46 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - -2 - - - - - 37 - - - YES - - - - - - 39 - - - YES - - - - - - 44 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 37.IBEditorWindowLastContentRect - 37.IBPluginDependency - 39.CustomClassName - 39.IBPluginDependency - 44.IBPluginDependency - - - YES - MainViewController - UIResponder - {{741, 489}, {320, 460}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RMMapView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 46 - - - - YES - - MainViewController - UIViewController - - YES - - YES - infoTextView - mapView - - - YES - UITextView - RMMapView - - - - IBProjectSource - Classes/MainViewController.h - - - - - 0 - MapTestbed.xcodeproj - 3 - - diff --git a/samples/MapTestbed/MainWindow.xib b/samples/MapTestbed/MainWindow.xib deleted file mode 100644 index 133308fc3..000000000 --- a/samples/MapTestbed/MainWindow.xib +++ /dev/null @@ -1,310 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - - 1316 - - {320, 480} - - - 1 - MCAwIDAAA - - NO - YES - - - - - - 274 - - YES - - - 265 - {{274, 414}, {18, 19}} - - NO - NO - 0 - 0 - - Helvetica-Bold - 1.500000e+01 - 16 - - 3 - YES - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - {320, 460} - - - 3 - MQA - - 2 - - - NO - - - - - - - YES - - - delegate - - - - 4 - - - - window - - - - 5 - - - - rootViewController - - - - 10 - - - - infoButton - - - - 20 - - - - toggleView - - - 7 - - 21 - - - - - YES - - 0 - - YES - - - - - - 2 - - - YES - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - 3 - - - - - 8 - - - YES - - - - - - -2 - - - - - 18 - - - YES - - - - - - 19 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 18.IBPluginDependency - 19.IBPluginDependency - 2.IBAttributePlaceholdersKey - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - 8.CustomClassName - 8.IBEditorWindowLastContentRect - 8.IBPluginDependency - - - YES - UIApplication - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - YES - - YES - - - YES - - - {{700, 391}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MapTestbedAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RootViewController - {{391, 356}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 21 - - - - YES - - MapTestbedAppDelegate - NSObject - - YES - - YES - rootViewController - window - - - YES - RootViewController - UIWindow - - - - IBProjectSource - Classes/MapTestbedAppDelegate.h - - - - RootViewController - UIViewController - - toggleView - id - - - infoButton - UIButton - - - IBProjectSource - Classes/RootViewController.h - - - - - 0 - MapTestbed.xcodeproj - 3 - - diff --git a/samples/MapTestbed/MapTestbed.xcodeproj/project.pbxproj b/samples/MapTestbed/MapTestbed.xcodeproj/project.pbxproj deleted file mode 100755 index 0a476ca6b..000000000 --- a/samples/MapTestbed/MapTestbed.xcodeproj/project.pbxproj +++ /dev/null @@ -1,381 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1D3623260D0F684500981E51 /* MapTestbedAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* MapTestbedAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754A0DD40C5E005A515E /* FlipsideView.xib */; }; - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754B0DD40C5E005A515E /* MainView.xib */; }; - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754C0DD40C5E005A515E /* MainWindow.xib */; }; - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765580DF743DE002DB57D /* CoreGraphics.framework */; }; - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A30DB2D0840083E9F9 /* FlipsideView.m */; }; - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A50DB2D0840083E9F9 /* MainView.m */; }; - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A90DB2D0DB0083E9F9 /* MainViewController.m */; }; - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */; }; - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */; }; - 2B93B7110FAA5C140062B299 /* marker-X.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B93B7100FAA5C140062B299 /* marker-X.png */; }; - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */; }; - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E10F649CE100377FFE /* QuartzCore.framework */; }; - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */; }; - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE3697D0F673B95003DC21C /* libMapView.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; - EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* MapTestbedAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapTestbedAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* MapTestbedAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MapTestbedAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* MapTestbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MapTestbed.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 280E754A0DD40C5E005A515E /* FlipsideView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FlipsideView.xib; sourceTree = ""; }; - 280E754B0DD40C5E005A515E /* MainView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainView.xib; sourceTree = ""; }; - 280E754C0DD40C5E005A515E /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 288765580DF743DE002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 289233A20DB2D0840083E9F9 /* FlipsideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideView.h; path = Classes/FlipsideView.h; sourceTree = ""; }; - 289233A30DB2D0840083E9F9 /* FlipsideView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideView.m; path = Classes/FlipsideView.m; sourceTree = ""; }; - 289233A40DB2D0840083E9F9 /* MainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainView.h; path = Classes/MainView.h; sourceTree = ""; }; - 289233A50DB2D0840083E9F9 /* MainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainView.m; path = Classes/MainView.m; sourceTree = ""; }; - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = ""; }; - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = ""; }; - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideViewController.h; path = Classes/FlipsideViewController.h; sourceTree = ""; }; - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideViewController.m; path = Classes/FlipsideViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2B93B7100FAA5C140062B299 /* marker-X.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "marker-X.png"; sourceTree = ""; }; - 2BB42C520F678FA9009967BB /* MapTestbed_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapTestbed_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */, - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */, - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */, - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */, - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Application Controllers */ = { - isa = PBXGroup; - children = ( - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */, - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */, - 1D3623240D0F684500981E51 /* MapTestbedAppDelegate.h */, - 1D3623250D0F684500981E51 /* MapTestbedAppDelegate.m */, - ); - name = "Application Controllers"; - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* MapTestbed.app */, - ); - name = Products; - sourceTree = ""; - }; - 281C6CD70DB2D82200F60ACC /* Flipside View */ = { - isa = PBXGroup; - children = ( - 289233A20DB2D0840083E9F9 /* FlipsideView.h */, - 289233A30DB2D0840083E9F9 /* FlipsideView.m */, - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */, - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */, - ); - name = "Flipside View"; - sourceTree = ""; - }; - 289233A00DB2D0730083E9F9 /* Main View */ = { - isa = PBXGroup; - children = ( - 289233A40DB2D0840083E9F9 /* MainView.h */, - 289233A50DB2D0840083E9F9 /* MainView.m */, - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */, - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */, - ); - name = "Main View"; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */, - 289233A00DB2D0730083E9F9 /* Main View */, - 281C6CD70DB2D82200F60ACC /* Flipside View */, - 080E96DDFE201D6D7F000001 /* Application Controllers */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 2BB42C520F678FA9009967BB /* MapTestbed_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 280E754A0DD40C5E005A515E /* FlipsideView.xib */, - 280E754B0DD40C5E005A515E /* MainView.xib */, - 280E754C0DD40C5E005A515E /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - 2B93B7100FAA5C140062B299 /* marker-X.png */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 288765580DF743DE002DB57D /* CoreGraphics.framework */, - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */, - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */, - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */, - ); - name = Frameworks; - sourceTree = ""; - }; - EBE3696E0F673B95003DC21C /* Products */ = { - isa = PBXGroup; - children = ( - EBE3697D0F673B95003DC21C /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* MapTestbed */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MapTestbed" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BB42BEF0F678951009967BB /* PBXTargetDependency */, - ); - name = MapTestbed; - productName = Sample2; - productReference = 1D6058910D05DD3D006BFB54 /* MapTestbed.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapTestbed" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - en, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = EBE3696E0F673B95003DC21C /* Products */; - ProjectRef = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* MapTestbed */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - EBE3697D0F673B95003DC21C /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */, - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */, - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */, - 2B93B7110FAA5C140062B299 /* marker-X.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* MapTestbedAppDelegate.m in Sources */, - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */, - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */, - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */, - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */, - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BB42BEF0F678951009967BB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapTestbed_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = MapTestbed; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_DYNAMIC_NO_PIC = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapTestbed_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = MapTestbed; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - SDKROOT = iphoneos; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MapTestbed" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapTestbed" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/MapTestbed/MapTestbed_Prefix.pch b/samples/MapTestbed/MapTestbed_Prefix.pch deleted file mode 100644 index 54e6560b0..000000000 --- a/samples/MapTestbed/MapTestbed_Prefix.pch +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'MapTestbed' target in the 'MapTestbed' project -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/samples/MapTestbed/main.m b/samples/MapTestbed/main.m deleted file mode 100644 index b370a3ea8..000000000 --- a/samples/MapTestbed/main.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// main.m -// MapTestbed : Diagnostic map -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/MapTestbed/marker-X.png b/samples/MapTestbed/marker-X.png deleted file mode 100644 index e35f589bf..000000000 Binary files a/samples/MapTestbed/marker-X.png and /dev/null differ diff --git a/samples/MapTestbedFlipMaps/Classes/FlipsideView.h b/samples/MapTestbedFlipMaps/Classes/FlipsideView.h deleted file mode 100644 index 4134079a8..000000000 --- a/samples/MapTestbedFlipMaps/Classes/FlipsideView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// FlipsideView.h -// MapTestbed : Diagnostic map -// - -#import - -@interface FlipsideView : UIView -{ -} - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/FlipsideView.m b/samples/MapTestbedFlipMaps/Classes/FlipsideView.m deleted file mode 100644 index de0911002..000000000 --- a/samples/MapTestbedFlipMaps/Classes/FlipsideView.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// FlipsideView.m -// MapTestbed : Diagnostic map -// - -#import "FlipsideView.h" - -@implementation FlipsideView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return nil; - - return self; -} - -- (void)drawRect:(CGRect)rect -{ - // Drawing code -} - -- (void)dealloc -{ - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/FlipsideViewController.h b/samples/MapTestbedFlipMaps/Classes/FlipsideViewController.h deleted file mode 100644 index b7403905e..000000000 --- a/samples/MapTestbedFlipMaps/Classes/FlipsideViewController.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// FlipsideViewController.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@interface FlipsideViewController : UIViewController -{ - IBOutlet RMMapView *mapView; - IBOutlet UITextView *infoTextView; -} - -@property (nonatomic, retain) IBOutlet RMMapView *mapView; -@property (nonatomic, retain) IBOutlet UITextView *infoTextView; - -- (void)updateInfo; - -@end - diff --git a/samples/MapTestbedFlipMaps/Classes/FlipsideViewController.m b/samples/MapTestbedFlipMaps/Classes/FlipsideViewController.m deleted file mode 100644 index ead2cd079..000000000 --- a/samples/MapTestbedFlipMaps/Classes/FlipsideViewController.m +++ /dev/null @@ -1,114 +0,0 @@ -// -// FlipsideViewController.m -// MapTestbed : Diagnostic map -// - -#import "FlipsideViewController.h" -#import "MapTestbedAppDelegate.h" -#import "RMAnnotation.h" -#import "RMMarker.h" - -@implementation FlipsideViewController - -@synthesize mapView; -@synthesize infoTextView; - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil -{ - if (!(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) - return nil; - - return self; -} - -// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. -- (void)viewDidLoad -{ - [super viewDidLoad]; - mapView.delegate = self; - [self updateInfo]; - - RMAnnotation *annotation = [RMAnnotation annotationWithMapView:mapView coordinate:[mapView centerCoordinate] andTitle:@"Hello"]; - annotation.annotationIcon = [UIImage imageNamed:@"marker-blue.png"]; - annotation.anchorPoint = CGPointMake(0.5, 1.0); - annotation.userInfo = [NSDictionary dictionaryWithObjectsAndKeys: - [UIColor blueColor],@"foregroundColor", - nil]; - [mapView addAnnotation:annotation]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)viewDidAppear:(BOOL)animated -{ - [self updateInfo]; -} - -- (void)dealloc -{ - self.infoTextView = nil; - self.mapView = nil; - [super dealloc]; -} - -- (void)updateInfo -{ - CLLocationCoordinate2D mapCenter = [mapView centerCoordinate]; - - float routemeMetersPerPixel = [mapView metersPerPixel]; - double truescaleDenominator = [mapView scaleDenominator]; - - [infoTextView setText:[NSString stringWithFormat:@"Latitude : %f\nLongitude : %f\nZoom level : %.2f\nMeter per pixel : %.1f\nTrue scale : 1:%.0f", - mapCenter.latitude, - mapCenter.longitude, - mapView.zoom, - routemeMetersPerPixel, - truescaleDenominator]]; -} - -#pragma mark - -#pragma mark Delegate methods - -- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation -{ - RMMarker *marker = [[[RMMarker alloc] initWithUIImage:annotation.annotationIcon anchorPoint:annotation.anchorPoint] autorelease]; - [marker setTextForegroundColor:[annotation.userInfo objectForKey:@"foregroundColor"]]; - [marker changeLabelUsingText:annotation.title]; - return marker; -} - -- (void)mapView:(RMMapView *)map didDragAnnotation:(RMAnnotation *)annotation withEvent:(UIEvent *)event -{ - if ([[event allTouches] count] == 1) - { - UITouch *touch = [[event allTouches] anyObject]; - if (touch.phase == UITouchPhaseMoved) - { - CGPoint currentPosition = [touch locationInView:mapView]; - CGPoint previousPosition = [touch previousLocationInView:mapView]; - CGPoint screenPosition = annotation.position; - screenPosition.x += (currentPosition.x - previousPosition.x); - screenPosition.y += (currentPosition.y - previousPosition.y); - - CLLocationCoordinate2D newCoordinate = [mapView pixelToCoordinate:screenPosition]; - NSLog(@"New location latitude:%lf longitude:%lf", newCoordinate.latitude, newCoordinate.longitude); - annotation.coordinate = newCoordinate; - } - } -} - -- (void)afterMapMove:(RMMapView *)map -{ - [self updateInfo]; -} - -- (void)afterMapZoom:(RMMapView *)map -{ - [self updateInfo]; -} - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/MainView.h b/samples/MapTestbedFlipMaps/Classes/MainView.h deleted file mode 100644 index ea20e09ea..000000000 --- a/samples/MapTestbedFlipMaps/Classes/MainView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// MainView.h -// MapTestbed : Diagnostic map -// - -#import - -@interface MainView : UIView -{ -} - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/MainView.m b/samples/MapTestbedFlipMaps/Classes/MainView.m deleted file mode 100644 index f350d1b7c..000000000 --- a/samples/MapTestbedFlipMaps/Classes/MainView.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// MainView.m -// MapTestbed : Diagnostic map -// - -#import "MainView.h" - -@implementation MainView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return nil; - - return self; -} - -- (void)drawRect:(CGRect)rect -{ - // Drawing code -} - -- (void)dealloc -{ - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/MainViewController.h b/samples/MapTestbedFlipMaps/Classes/MainViewController.h deleted file mode 100644 index 648162a5c..000000000 --- a/samples/MapTestbedFlipMaps/Classes/MainViewController.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// MainViewController.h -// MapTestbed : Diagnostic map -// - -#import - -#import "RMMapView.h" - -@interface MainViewController : UIViewController -{ - IBOutlet RMMapView *mapView; - IBOutlet UITextView *infoTextView; - IBOutlet UISegmentedControl *mapSelectControl; -} - -@property (nonatomic, retain) IBOutlet RMMapView *mapView; -@property (nonatomic, retain) IBOutlet UITextView *infoTextView; - -- (IBAction) mapSelectChange; - -- (void)updateInfo; - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/MainViewController.m b/samples/MapTestbedFlipMaps/Classes/MainViewController.m deleted file mode 100644 index 339d73139..000000000 --- a/samples/MapTestbedFlipMaps/Classes/MainViewController.m +++ /dev/null @@ -1,151 +0,0 @@ -// -// MainViewController.m -// MapTestbed : Diagnostic map -// - -#import "MainViewController.h" -#import "MapTestbedAppDelegate.h" -#import "RMMarker.h" -#import "RMAnnotation.h" - -#import "MainView.h" -#import "RMTileSource.h" - -#import "RMOpenCycleMapSource.h" -#import "RMOpenStreetMapSource.h" -#import "RMOpenSeaMapSource.h" -#import "RMMapQuestOSMSource.h" -#import "RMMapQuestOpenAerialSource.h" - -@implementation MainViewController - -@synthesize mapView; -@synthesize infoTextView; - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil -{ - if (!(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) - return nil; - - return self; -} - -// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. -- (void)viewDidLoad -{ - [super viewDidLoad]; - mapView.delegate = self; - mapView.decelerationMode = RMMapDecelerationFast; - [self updateInfo]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileNotification:) name:RMTileRequested object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileNotification:) name:RMTileRetrieved object:nil]; - - [mapView setMinZoom:1.0]; - [mapView setMaxZoom:20.0]; - - RMAnnotation *annotation = [RMAnnotation annotationWithMapView:mapView coordinate:[mapView centerCoordinate] andTitle:@"Hello"]; - annotation.annotationIcon = [UIImage imageNamed:@"marker-blue.png"]; - annotation.anchorPoint = CGPointMake(0.5, 1.0); - annotation.userInfo = [NSDictionary dictionaryWithObjectsAndKeys: - [UIColor blueColor],@"foregroundColor", - nil]; - [mapView addAnnotation:annotation]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)viewDidAppear:(BOOL)animated -{ - [self updateInfo]; -} - -- (void)dealloc -{ - self.infoTextView = nil; - self.mapView = nil; - [super dealloc]; -} - -- (void)updateInfo -{ - CLLocationCoordinate2D mapCenter = [mapView centerCoordinate]; - - float routemeMetersPerPixel = [mapView metersPerPixel]; // really meters/pixel - double truescaleDenominator = [mapView scaleDenominator]; - - [infoTextView setText:[NSString stringWithFormat:@"Latitude : %f\nLongitude : %f\nZoom level : %.2f\nMeter per pixel : %.1f\nTrue scale : 1:%.0f", - mapCenter.latitude, - mapCenter.longitude, - mapView.zoom, - routemeMetersPerPixel, - truescaleDenominator]]; -} - -- (IBAction)mapSelectChange -{ - switch (mapSelectControl.selectedSegmentIndex) - { - case 1: - [mapView setTileSource:[[[RMOpenCycleMapSource alloc] init] autorelease]]; - break; - - case 2: - [mapView setTileSource:[[[RMOpenSeaMapSource alloc] init] autorelease]]; - break; - - case 3: - [mapView setTileSource:[[[RMMapQuestOSMSource alloc] init] autorelease]]; - break; - - case 4: - [mapView setTileSource:[[[RMMapQuestOpenAerialSource alloc] init] autorelease]]; - break; - - default: - [mapView setTileSource:[[[RMOpenStreetMapSource alloc] init] autorelease]]; - break; - } -} - -#pragma mark - -#pragma mark Delegate methods - -- (void)afterMapMove:(RMMapView *)map -{ - [self updateInfo]; -} - -- (void)afterMapZoom:(RMMapView *)map -{ - [self updateInfo]; -} - -- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation -{ - RMMarker *marker = [[[RMMarker alloc] initWithUIImage:annotation.annotationIcon anchorPoint:annotation.anchorPoint] autorelease]; - [marker setTextForegroundColor:[annotation.userInfo objectForKey:@"foregroundColor"]]; - [marker changeLabelUsingText:annotation.title]; - return marker; -} - -#pragma mark - -#pragma mark Notification methods - -- (void)tileNotification:(NSNotification *)notification -{ - static int outstandingTiles = 0; - - if (notification.name == RMTileRequested) - outstandingTiles++; - else if(notification.name == RMTileRetrieved) - outstandingTiles--; - - [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:(outstandingTiles > 0)]; -} - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/MapTestbedAppDelegate.h b/samples/MapTestbedFlipMaps/Classes/MapTestbedAppDelegate.h deleted file mode 100644 index 99cc674e8..000000000 --- a/samples/MapTestbedFlipMaps/Classes/MapTestbedAppDelegate.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// MapTestbedAppDelegate.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@class RootViewController; - -@interface MapTestbedAppDelegate : NSObject -{ - UIWindow *window; - RootViewController *rootViewController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet RootViewController *rootViewController; - -@end - diff --git a/samples/MapTestbedFlipMaps/Classes/MapTestbedAppDelegate.m b/samples/MapTestbedFlipMaps/Classes/MapTestbedAppDelegate.m deleted file mode 100644 index 37c82a6c9..000000000 --- a/samples/MapTestbedFlipMaps/Classes/MapTestbedAppDelegate.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// MapTestbedAppDelegate.m -// MapTestbed : Diagnostic map -// - -#import "MapTestbedAppDelegate.h" -#import "RootViewController.h" - -@implementation MapTestbedAppDelegate - -@synthesize window; -@synthesize rootViewController; - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - [window addSubview:[rootViewController view]]; - [window makeKeyAndVisible]; -} - -- (void)dealloc -{ - self.rootViewController = nil; - self.window = nil; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/RootViewController.h b/samples/MapTestbedFlipMaps/Classes/RootViewController.h deleted file mode 100644 index cc575e72d..000000000 --- a/samples/MapTestbedFlipMaps/Classes/RootViewController.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// RootViewController.h -// MapTestbed : Diagnostic map -// - -#import - -@class MainViewController; -@class FlipsideViewController; - -@interface RootViewController : UIViewController -{ - UIButton *infoButton; - MainViewController *mainViewController; - FlipsideViewController *flipsideViewController; - UINavigationBar *flipsideNavigationBar; -} - -@property (nonatomic, retain) IBOutlet UIButton *infoButton; -@property (nonatomic, retain) MainViewController *mainViewController; -@property (nonatomic, retain) UINavigationBar *flipsideNavigationBar; -@property (nonatomic, retain) FlipsideViewController *flipsideViewController; - -- (IBAction)toggleView; - -@end diff --git a/samples/MapTestbedFlipMaps/Classes/RootViewController.m b/samples/MapTestbedFlipMaps/Classes/RootViewController.m deleted file mode 100644 index 783b49a9d..000000000 --- a/samples/MapTestbedFlipMaps/Classes/RootViewController.m +++ /dev/null @@ -1,102 +0,0 @@ -// -// RootViewController.m -// MapTestbed : Diagnostic map -// - -#import "RootViewController.h" -#import "MainViewController.h" -#import "FlipsideViewController.h" - -@implementation RootViewController - -@synthesize infoButton; -@synthesize flipsideNavigationBar; -@synthesize mainViewController; -@synthesize flipsideViewController; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - MainViewController *viewController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil]; - self.mainViewController = viewController; - [viewController release]; - - [self.view insertSubview:mainViewController.view belowSubview:infoButton]; -} - -- (void)loadFlipsideViewController -{ - FlipsideViewController *viewController = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil]; - self.flipsideViewController = viewController; - [viewController release]; - - // Set up the navigation bar - UINavigationBar *aNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)]; - aNavigationBar.barStyle = UIBarStyleBlackOpaque; - self.flipsideNavigationBar = aNavigationBar; - [aNavigationBar release]; - - UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(toggleView)]; - UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"MapTestbed"]; - navigationItem.rightBarButtonItem = buttonItem; - [flipsideNavigationBar pushNavigationItem:navigationItem animated:NO]; - [navigationItem release]; - [buttonItem release]; -} - -- (IBAction)toggleView -{ - /* - This method is called when the info or Done button is pressed. - It flips the displayed view from the main view to the flipside view and vice-versa. - */ - if (flipsideViewController == nil) - [self loadFlipsideViewController]; - - UIView *mainView = mainViewController.view; - UIView *flipsideView = flipsideViewController.view; - - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:1]; - [UIView setAnimationTransition:([mainView superview] ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES]; - - if ([mainView superview] != nil) { - [flipsideViewController viewWillAppear:YES]; - [mainViewController viewWillDisappear:YES]; - [mainView removeFromSuperview]; - [infoButton removeFromSuperview]; - [self.view addSubview:flipsideView]; - [self.view insertSubview:flipsideNavigationBar aboveSubview:flipsideView]; - [mainViewController viewDidDisappear:YES]; - [flipsideViewController viewDidAppear:YES]; - - } else { - [mainViewController viewWillAppear:YES]; - [flipsideViewController viewWillDisappear:YES]; - [flipsideView removeFromSuperview]; - [flipsideNavigationBar removeFromSuperview]; - [self.view addSubview:mainView]; - [self.view insertSubview:infoButton aboveSubview:mainViewController.view]; - [flipsideViewController viewDidDisappear:YES]; - [mainViewController viewDidAppear:YES]; - } - [UIView commitAnimations]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)dealloc -{ - [infoButton release]; - [flipsideNavigationBar release]; - [mainViewController release]; - [flipsideViewController release]; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedFlipMaps/FlipsideView.xib b/samples/MapTestbedFlipMaps/FlipsideView.xib deleted file mode 100644 index ae0a80605..000000000 --- a/samples/MapTestbedFlipMaps/FlipsideView.xib +++ /dev/null @@ -1,260 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 274 - - YES - - - 274 - - YES - - - 274 - {{0, 342}, {320, 118}} - - - 1 - MC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC42OTk5OTk5OQA - - NO - YES - YES - NO - NO - NO - NO - NO - Ly8KLy8gIE1haW5WaWV3Q29udHJvbGxlci5tCi8vICBTYW1wbGUyIDogRGlhZ25vc3RpYyBtYXAKLy8K -CiNpbXBvcnQgIk1haW5WaWV3Q29udHJvbGxlci5oIgojaW1wb3J0ICJNYWluVmlldy5oIgoKQGltcGxl -bWVudGF0aW9uIE1haW5WaWV3Q29udHJvbGxlcgoKQHN5bnRoZXNpemUgbWFwVmlldzsKQHN5bnRoZXNp -emUgdGV4dFZpZXc7CgotIChpZClpbml0V2l0aE5pYk5hbWU6KE5TU3RyaW5nICopbmliTmFtZU9yTmls -IGJ1bmRsZTooTlNCdW5kbGUgKiluaWJCdW5kbGVPck5pbCB7CiAgICBpZiAoc2VsZiA9IFtzdXBlciBp -bml0V2l0aE5pYk5hbWU6bmliTmFtZU9yTmlsIGJ1bmRsZTpuaWJCdW5kbGVPck5pbF0pIHsKICAgICAg -ICAvLyBDdXN0b20gaW5pdGlhbGl6YXRpb24KICAgIH0KICAgIHJldHVybiBzZWxmOwp9CgoKLy8gSW1w -bGVtZW50IHZpZXdEaWRMb2FkIHRvIGRvIGFkZGl0aW9uYWwgc2V0dXAgYWZ0ZXIgbG9hZGluZyB0aGUg -dmlldywgdHlwaWNhbGx5IGZyb20gYSBuaWIuCi0gKHZvaWQpdmlld0RpZExvYWQgewogICAgW3N1cGVy -IHZpZXdEaWRMb2FkXTsKICAgIFt0ZXh0VmlldyBzZXRUZXh0OkAidG90byBlc3QgZW4gdmFjYW5jZXMi -XTsKfQoKCi8qCiAvLyBPdmVycmlkZSB0byBhbGxvdyBvcmllbnRhdGlvbnMgb3RoZXIgdGhhbiB0aGUg -ZGVmYXVsdCBwb3J0cmFpdCBvcmllbnRhdGlvbi4KIC0gKEJPT0wpc2hvdWxkQXV0b3JvdGF0ZVRvSW50 -ZXJmYWNlT3JpZW50YXRpb246KFVJSW50ZXJmYWNlT3JpZW50YXRpb24paW50ZXJmYWNlT3JpZW50YXRp -b24gewogLy8gUmV0dXJuIFlFUyBmb3Igc3VwcG9ydGVkIG9yaWVudGF0aW9ucwogcmV0dXJuIChpbnRl -cmZhY2VPcmllbnRhdGlvbiA9PSBVSUludGVyZmFjZU9yaWVudGF0aW9uUG9ydHJhaXQpOwogfQoqLwoK -Ci0gKHZvaWQpZGlkUmVjZWl2ZU1lbW9yeVdhcm5pbmcgewogICAgW3N1cGVyIGRpZFJlY2VpdmVNZW1v -cnlXYXJuaW5nXTsgLy8gUmVsZWFzZXMgdGhlIHZpZXcgaWYgaXQgZG9lc24ndCBoYXZlIGEgc3VwZXJ2 -aWV3CiAgICAvLyBSZWxlYXNlIGFueXRoaW5nIHRoYXQncyBub3QgZXNzZW50aWFsLCBzdWNoIGFzIGNh -Y2hlZCBkYXRhCn0KCgotICh2b2lkKWRlYWxsb2MgewogICAgW3N1cGVyIGRlYWxsb2NdOwp9CgoKQGVu -ZAo - - 3 - MQA - - - - {320, 460} - - - 3 - MQA - - 2 - - - NO - YES - - - {320, 460} - - - 3 - MQA - - - NO - - - - - YES - - - view - - - - 40 - - - - mapView - - - - 41 - - - - infoTextView - - - - 46 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - -2 - - - - - 37 - - - YES - - - - - - 39 - - - YES - - - - - - 44 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 37.IBEditorWindowLastContentRect - 37.IBPluginDependency - 39.CustomClassName - 39.IBPluginDependency - 44.IBPluginDependency - - - YES - FlipsideViewController - UIResponder - {{741, 296}, {320, 460}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RMMapView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 46 - - - - YES - - FlipsideViewController - UIViewController - - YES - - YES - infoTextView - mapView - - - YES - UITextView - RMMapView - - - - IBProjectSource - Classes/FlipsideViewController.h - - - - - 0 - MapTestbedFlipMaps.xcodeproj - 3 - - diff --git a/samples/MapTestbedFlipMaps/Info.plist b/samples/MapTestbedFlipMaps/Info.plist deleted file mode 100644 index fdf834060..000000000 --- a/samples/MapTestbedFlipMaps/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/samples/MapTestbedFlipMaps/MainView.xib b/samples/MapTestbedFlipMaps/MainView.xib deleted file mode 100644 index 70b46804b..000000000 --- a/samples/MapTestbedFlipMaps/MainView.xib +++ /dev/null @@ -1,453 +0,0 @@ - - - - 528 - 10K549 - 1938 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 933 - - - YES - IBUITextView - IBUISegmentedControl - IBUIView - IBProxyObject - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - YES - - - 274 - - YES - - - 292 - - YES - - - 292 - {{5, 20}, {310, 30}} - - - - NO - NO - IBCocoaTouchFramework - 2 - 5 - 0 - - YES - Street - Cycle - Sea - MQ OSM - MQ Aerial - - - YES - - - - - - - - YES - - - - - - - - YES - {0, 0} - {0, 0} - {0, 0} - {0, 0} - {0, 0} - - - YES - - - - - - - - - {320, 460} - - - - - 3 - MQA - - 2 - - - NO - NO - IBCocoaTouchFramework - - - - 274 - {{0, 342}, {320, 118}} - - - - - 1 - MC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC42OTk5OTk5OQA - - NO - YES - YES - IBCocoaTouchFramework - NO - NO - NO - NO - NO - Ly8KLy8gIE1haW5WaWV3Q29udHJvbGxlci5tCi8vICBTYW1wbGUyIDogRGlhZ25vc3RpYyBtYXAKLy8K -CiNpbXBvcnQgIk1haW5WaWV3Q29udHJvbGxlci5oIgojaW1wb3J0ICJNYWluVmlldy5oIgoKQGltcGxl -bWVudGF0aW9uIE1haW5WaWV3Q29udHJvbGxlcgoKQHN5bnRoZXNpemUgbWFwVmlldzsKQHN5bnRoZXNp -emUgdGV4dFZpZXc7CgotIChpZClpbml0V2l0aE5pYk5hbWU6KE5TU3RyaW5nICopbmliTmFtZU9yTmls -IGJ1bmRsZTooTlNCdW5kbGUgKiluaWJCdW5kbGVPck5pbCB7CiAgICBpZiAoc2VsZiA9IFtzdXBlciBp -bml0V2l0aE5pYk5hbWU6bmliTmFtZU9yTmlsIGJ1bmRsZTpuaWJCdW5kbGVPck5pbF0pIHsKICAgICAg -ICAvLyBDdXN0b20gaW5pdGlhbGl6YXRpb24KICAgIH0KICAgIHJldHVybiBzZWxmOwp9CgoKLy8gSW1w -bGVtZW50IHZpZXdEaWRMb2FkIHRvIGRvIGFkZGl0aW9uYWwgc2V0dXAgYWZ0ZXIgbG9hZGluZyB0aGUg -dmlldywgdHlwaWNhbGx5IGZyb20gYSBuaWIuCi0gKHZvaWQpdmlld0RpZExvYWQgewogICAgW3N1cGVy -IHZpZXdEaWRMb2FkXTsKICAgIFt0ZXh0VmlldyBzZXRUZXh0OkAidG90byBlc3QgZW4gdmFjYW5jZXMi -XTsKfQoKCi8qCiAvLyBPdmVycmlkZSB0byBhbGxvdyBvcmllbnRhdGlvbnMgb3RoZXIgdGhhbiB0aGUg -ZGVmYXVsdCBwb3J0cmFpdCBvcmllbnRhdGlvbi4KIC0gKEJPT0wpc2hvdWxkQXV0b3JvdGF0ZVRvSW50 -ZXJmYWNlT3JpZW50YXRpb246KFVJSW50ZXJmYWNlT3JpZW50YXRpb24paW50ZXJmYWNlT3JpZW50YXRp -b24gewogLy8gUmV0dXJuIFlFUyBmb3Igc3VwcG9ydGVkIG9yaWVudGF0aW9ucwogcmV0dXJuIChpbnRl -cmZhY2VPcmllbnRhdGlvbiA9PSBVSUludGVyZmFjZU9yaWVudGF0aW9uUG9ydHJhaXQpOwogfQoqLwoK -Ci0gKHZvaWQpZGlkUmVjZWl2ZU1lbW9yeVdhcm5pbmcgewogICAgW3N1cGVyIGRpZFJlY2VpdmVNZW1v -cnlXYXJuaW5nXTsgLy8gUmVsZWFzZXMgdGhlIHZpZXcgaWYgaXQgZG9lc24ndCBoYXZlIGEgc3VwZXJ2 -aWV3CiAgICAvLyBSZWxlYXNlIGFueXRoaW5nIHRoYXQncyBub3QgZXNzZW50aWFsLCBzdWNoIGFzIGNh -Y2hlZCBkYXRhCn0KCgotICh2b2lkKWRlYWxsb2MgewogICAgW3N1cGVyIGRlYWxsb2NdOwp9CgoKQGVu -ZAo - - 3 - MQA - - - IBCocoaTouchFramework - - - 1 - 4 - - - Helvetica - 14 - 16 - - - - {320, 460} - - - - - 3 - MQA - - - NO - YES - IBCocoaTouchFramework - - - {320, 460} - - - - - NO - IBCocoaTouchFramework - - - - - YES - - - infoTextView - - - - 46 - - - - mapView - - - - 57 - - - - view - - - - 58 - - - - mapSelectControl - - - - 54 - - - - mapSelectChange - - - 13 - - 53 - - - - - YES - - 0 - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 37 - - - YES - - - - - - 39 - - - YES - - - - - - - 44 - - - - - 56 - - - YES - - - - - - 49 - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 37.IBPluginDependency - 39.CustomClassName - 39.IBPluginDependency - 44.IBPluginDependency - 49.IBPluginDependency - 56.CustomClassName - 56.IBPluginDependency - - - YES - MainViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MainView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RMMapView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 58 - - - - YES - - MainView - UIView - - IBProjectSource - ./Classes/MainView.h - - - - MainViewController - UIViewController - - mapSelectChange - id - - - mapSelectChange - - mapSelectChange - id - - - - YES - - YES - infoTextView - mapSelectControl - mapView - - - YES - UITextView - UISegmentedControl - RMMapView - - - - YES - - YES - infoTextView - mapSelectControl - mapView - - - YES - - infoTextView - UITextView - - - mapSelectControl - UISegmentedControl - - - mapView - RMMapView - - - - - IBProjectSource - ./Classes/MainViewController.h - - - - RMMapView - UIView - - IBProjectSource - ./Classes/RMMapView.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - 933 - - diff --git a/samples/MapTestbedFlipMaps/MainWindow.xib b/samples/MapTestbedFlipMaps/MainWindow.xib deleted file mode 100644 index 133308fc3..000000000 --- a/samples/MapTestbedFlipMaps/MainWindow.xib +++ /dev/null @@ -1,310 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - - 1316 - - {320, 480} - - - 1 - MCAwIDAAA - - NO - YES - - - - - - 274 - - YES - - - 265 - {{274, 414}, {18, 19}} - - NO - NO - 0 - 0 - - Helvetica-Bold - 1.500000e+01 - 16 - - 3 - YES - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - {320, 460} - - - 3 - MQA - - 2 - - - NO - - - - - - - YES - - - delegate - - - - 4 - - - - window - - - - 5 - - - - rootViewController - - - - 10 - - - - infoButton - - - - 20 - - - - toggleView - - - 7 - - 21 - - - - - YES - - 0 - - YES - - - - - - 2 - - - YES - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - 3 - - - - - 8 - - - YES - - - - - - -2 - - - - - 18 - - - YES - - - - - - 19 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 18.IBPluginDependency - 19.IBPluginDependency - 2.IBAttributePlaceholdersKey - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - 8.CustomClassName - 8.IBEditorWindowLastContentRect - 8.IBPluginDependency - - - YES - UIApplication - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - YES - - YES - - - YES - - - {{700, 391}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MapTestbedAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RootViewController - {{391, 356}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 21 - - - - YES - - MapTestbedAppDelegate - NSObject - - YES - - YES - rootViewController - window - - - YES - RootViewController - UIWindow - - - - IBProjectSource - Classes/MapTestbedAppDelegate.h - - - - RootViewController - UIViewController - - toggleView - id - - - infoButton - UIButton - - - IBProjectSource - Classes/RootViewController.h - - - - - 0 - MapTestbed.xcodeproj - 3 - - diff --git a/samples/MapTestbedFlipMaps/MapTestbedFlipMaps.xcodeproj/project.pbxproj b/samples/MapTestbedFlipMaps/MapTestbedFlipMaps.xcodeproj/project.pbxproj deleted file mode 100755 index ca6909f01..000000000 --- a/samples/MapTestbedFlipMaps/MapTestbedFlipMaps.xcodeproj/project.pbxproj +++ /dev/null @@ -1,393 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1D3623260D0F684500981E51 /* MapTestbedAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* MapTestbedAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754A0DD40C5E005A515E /* FlipsideView.xib */; }; - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754B0DD40C5E005A515E /* MainView.xib */; }; - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754C0DD40C5E005A515E /* MainWindow.xib */; }; - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765580DF743DE002DB57D /* CoreGraphics.framework */; }; - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A30DB2D0840083E9F9 /* FlipsideView.m */; }; - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A50DB2D0840083E9F9 /* MainView.m */; }; - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A90DB2D0DB0083E9F9 /* MainViewController.m */; }; - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */; }; - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */; }; - 966506150F68C9800036562A /* marker-blue.png in Resources */ = {isa = PBXBuildFile; fileRef = 966506140F68C9800036562A /* marker-blue.png */; }; - B1833A6910AF020A003FDF97 /* error.png in Resources */ = {isa = PBXBuildFile; fileRef = B1833A6610AF020A003FDF97 /* error.png */; }; - B1833A6A10AF020A003FDF97 /* loading.png in Resources */ = {isa = PBXBuildFile; fileRef = B1833A6710AF020A003FDF97 /* loading.png */; }; - B1833A6B10AF020A003FDF97 /* missing.png in Resources */ = {isa = PBXBuildFile; fileRef = B1833A6810AF020A003FDF97 /* missing.png */; }; - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */; }; - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E10F649CE100377FFE /* QuartzCore.framework */; }; - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */; }; - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE3697D0F673B95003DC21C /* libMapView.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; - EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* MapTestbedAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapTestbedAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* MapTestbedAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MapTestbedAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* FlipMaps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlipMaps.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 280E754A0DD40C5E005A515E /* FlipsideView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FlipsideView.xib; sourceTree = ""; }; - 280E754B0DD40C5E005A515E /* MainView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainView.xib; sourceTree = ""; }; - 280E754C0DD40C5E005A515E /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 288765580DF743DE002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 289233A20DB2D0840083E9F9 /* FlipsideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideView.h; path = Classes/FlipsideView.h; sourceTree = ""; }; - 289233A30DB2D0840083E9F9 /* FlipsideView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideView.m; path = Classes/FlipsideView.m; sourceTree = ""; }; - 289233A40DB2D0840083E9F9 /* MainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainView.h; path = Classes/MainView.h; sourceTree = ""; }; - 289233A50DB2D0840083E9F9 /* MainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainView.m; path = Classes/MainView.m; sourceTree = ""; }; - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = ""; }; - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = ""; }; - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideViewController.h; path = Classes/FlipsideViewController.h; sourceTree = ""; }; - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideViewController.m; path = Classes/FlipsideViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2BB42C520F678FA9009967BB /* MapTestbed_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapTestbed_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 966506140F68C9800036562A /* marker-blue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "marker-blue.png"; sourceTree = ""; }; - B1833A6610AF020A003FDF97 /* error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = error.png; sourceTree = ""; }; - B1833A6710AF020A003FDF97 /* loading.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = loading.png; sourceTree = ""; }; - B1833A6810AF020A003FDF97 /* missing.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = missing.png; sourceTree = ""; }; - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */, - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */, - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */, - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */, - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Application Controllers */ = { - isa = PBXGroup; - children = ( - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */, - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */, - 1D3623240D0F684500981E51 /* MapTestbedAppDelegate.h */, - 1D3623250D0F684500981E51 /* MapTestbedAppDelegate.m */, - ); - name = "Application Controllers"; - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* FlipMaps.app */, - ); - name = Products; - sourceTree = ""; - }; - 281C6CD70DB2D82200F60ACC /* Flipside View */ = { - isa = PBXGroup; - children = ( - 289233A20DB2D0840083E9F9 /* FlipsideView.h */, - 289233A30DB2D0840083E9F9 /* FlipsideView.m */, - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */, - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */, - ); - name = "Flipside View"; - sourceTree = ""; - }; - 289233A00DB2D0730083E9F9 /* Main View */ = { - isa = PBXGroup; - children = ( - 289233A40DB2D0840083E9F9 /* MainView.h */, - 289233A50DB2D0840083E9F9 /* MainView.m */, - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */, - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */, - ); - name = "Main View"; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */, - 289233A00DB2D0730083E9F9 /* Main View */, - 281C6CD70DB2D82200F60ACC /* Flipside View */, - 080E96DDFE201D6D7F000001 /* Application Controllers */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 2BB42C520F678FA9009967BB /* MapTestbed_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - B1833A6610AF020A003FDF97 /* error.png */, - B1833A6710AF020A003FDF97 /* loading.png */, - B1833A6810AF020A003FDF97 /* missing.png */, - 966506140F68C9800036562A /* marker-blue.png */, - 280E754A0DD40C5E005A515E /* FlipsideView.xib */, - 280E754B0DD40C5E005A515E /* MainView.xib */, - 280E754C0DD40C5E005A515E /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 288765580DF743DE002DB57D /* CoreGraphics.framework */, - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */, - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */, - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */, - ); - name = Frameworks; - sourceTree = ""; - }; - EBE3696E0F673B95003DC21C /* Products */ = { - isa = PBXGroup; - children = ( - EBE3697D0F673B95003DC21C /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* FlipMaps */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "FlipMaps" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BB42BEF0F678951009967BB /* PBXTargetDependency */, - ); - name = FlipMaps; - productName = Sample2; - productReference = 1D6058910D05DD3D006BFB54 /* FlipMaps.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapTestbedFlipMaps" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - en, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = EBE3696E0F673B95003DC21C /* Products */; - ProjectRef = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* FlipMaps */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - EBE3697D0F673B95003DC21C /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */, - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */, - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */, - 966506150F68C9800036562A /* marker-blue.png in Resources */, - B1833A6910AF020A003FDF97 /* error.png in Resources */, - B1833A6A10AF020A003FDF97 /* loading.png in Resources */, - B1833A6B10AF020A003FDF97 /* missing.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* MapTestbedAppDelegate.m in Sources */, - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */, - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */, - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */, - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */, - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BB42BEF0F678951009967BB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapTestbed_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = FlipMaps; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_DYNAMIC_NO_PIC = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapTestbed_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = MapTestbed; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - SDKROOT = iphoneos; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "FlipMaps" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapTestbedFlipMaps" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/MapTestbedFlipMaps/MapTestbed_Prefix.pch b/samples/MapTestbedFlipMaps/MapTestbed_Prefix.pch deleted file mode 100644 index 54e6560b0..000000000 --- a/samples/MapTestbedFlipMaps/MapTestbed_Prefix.pch +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'MapTestbed' target in the 'MapTestbed' project -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/samples/MapTestbedFlipMaps/error.png b/samples/MapTestbedFlipMaps/error.png deleted file mode 100644 index 04cbc6506..000000000 Binary files a/samples/MapTestbedFlipMaps/error.png and /dev/null differ diff --git a/samples/MapTestbedFlipMaps/loading.png b/samples/MapTestbedFlipMaps/loading.png deleted file mode 100644 index d09dacda0..000000000 Binary files a/samples/MapTestbedFlipMaps/loading.png and /dev/null differ diff --git a/samples/MapTestbedFlipMaps/main.m b/samples/MapTestbedFlipMaps/main.m deleted file mode 100644 index b370a3ea8..000000000 --- a/samples/MapTestbedFlipMaps/main.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// main.m -// MapTestbed : Diagnostic map -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/MapTestbedFlipMaps/marker-blue.png b/samples/MapTestbedFlipMaps/marker-blue.png deleted file mode 100644 index 8a3970fe5..000000000 Binary files a/samples/MapTestbedFlipMaps/marker-blue.png and /dev/null differ diff --git a/samples/MapTestbedFlipMaps/missing.png b/samples/MapTestbedFlipMaps/missing.png deleted file mode 100644 index 8205b1c37..000000000 Binary files a/samples/MapTestbedFlipMaps/missing.png and /dev/null differ diff --git a/samples/MapTestbedTwoMaps/Classes/FlipsideView.h b/samples/MapTestbedTwoMaps/Classes/FlipsideView.h deleted file mode 100644 index 4134079a8..000000000 --- a/samples/MapTestbedTwoMaps/Classes/FlipsideView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// FlipsideView.h -// MapTestbed : Diagnostic map -// - -#import - -@interface FlipsideView : UIView -{ -} - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/FlipsideView.m b/samples/MapTestbedTwoMaps/Classes/FlipsideView.m deleted file mode 100644 index de0911002..000000000 --- a/samples/MapTestbedTwoMaps/Classes/FlipsideView.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// FlipsideView.m -// MapTestbed : Diagnostic map -// - -#import "FlipsideView.h" - -@implementation FlipsideView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return nil; - - return self; -} - -- (void)drawRect:(CGRect)rect -{ - // Drawing code -} - -- (void)dealloc -{ - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/FlipsideViewController.h b/samples/MapTestbedTwoMaps/Classes/FlipsideViewController.h deleted file mode 100644 index ed3b72c69..000000000 --- a/samples/MapTestbedTwoMaps/Classes/FlipsideViewController.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// FlipsideViewController.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@interface FlipsideViewController : UIViewController -{ - IBOutlet UITextField *centerLatitude; - IBOutlet UITextField *centerLongitude; - IBOutlet UITextField *zoomLevel; - IBOutlet UITextField *minZoom; - IBOutlet UITextField *maxZoom; - RMMapView *mapView; -} - -@property(nonatomic,retain) IBOutlet UITextField *centerLatitude; -@property(nonatomic,retain) IBOutlet UITextField *centerLongitude; -@property(nonatomic,retain) IBOutlet UITextField *zoomLevel; -@property(nonatomic,retain) IBOutlet UITextField *minZoom; -@property(nonatomic,retain) IBOutlet UITextField *maxZoom; - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/FlipsideViewController.m b/samples/MapTestbedTwoMaps/Classes/FlipsideViewController.m deleted file mode 100644 index d5d35694c..000000000 --- a/samples/MapTestbedTwoMaps/Classes/FlipsideViewController.m +++ /dev/null @@ -1,66 +0,0 @@ -// -// FlipsideViewController.m -// MapTestbed : Diagnostic map -// - -#import "FlipsideViewController.h" -#import "MapTestbedTwoMapsAppDelegate.h" -#import "MainViewController.h" -#import "RootViewController.h" - -@implementation FlipsideViewController - -@synthesize centerLatitude; -@synthesize centerLongitude; -@synthesize zoomLevel; -@synthesize minZoom; -@synthesize maxZoom; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - mapView = [[[(MapTestbedTwoMapsAppDelegate *)[[UIApplication sharedApplication] delegate] rootViewController] mainViewController] upperMapView]; - - self.view.backgroundColor = [UIColor groupTableViewBackgroundColor]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)viewDidAppear:(BOOL)animated -{ - CLLocationCoordinate2D mapCenter = [mapView centerCoordinate]; - - [centerLatitude setText:[NSString stringWithFormat:@"%f", mapCenter.latitude]]; - [centerLongitude setText:[NSString stringWithFormat:@"%f", mapCenter.longitude]]; - [zoomLevel setText:[NSString stringWithFormat:@"%f", mapView.zoom]]; - [maxZoom setText:[NSString stringWithFormat:@"%f", mapView.maxZoom]]; - [minZoom setText:[NSString stringWithFormat:@"%f", mapView.minZoom]]; -} - -- (void)viewWillDisappear:(BOOL)animated -{ - CLLocationCoordinate2D newMapCenter; - - newMapCenter.latitude = [[centerLatitude text] doubleValue]; - newMapCenter.longitude = [[centerLongitude text] doubleValue]; - [mapView setCenterCoordinate:newMapCenter animated:NO]; - [mapView setZoom:[[zoomLevel text] floatValue]]; - [mapView setMaxZoom:[[maxZoom text] floatValue]]; - [mapView setMinZoom:[[minZoom text] floatValue]]; -} - -- (void)dealloc -{ - self.centerLatitude = nil; - self.centerLongitude = nil; - self.zoomLevel = nil; - self.minZoom = nil; - self.maxZoom = nil; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/MainView.h b/samples/MapTestbedTwoMaps/Classes/MainView.h deleted file mode 100644 index ea20e09ea..000000000 --- a/samples/MapTestbedTwoMaps/Classes/MainView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// MainView.h -// MapTestbed : Diagnostic map -// - -#import - -@interface MainView : UIView -{ -} - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/MainView.m b/samples/MapTestbedTwoMaps/Classes/MainView.m deleted file mode 100644 index f350d1b7c..000000000 --- a/samples/MapTestbedTwoMaps/Classes/MainView.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// MainView.m -// MapTestbed : Diagnostic map -// - -#import "MainView.h" - -@implementation MainView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return nil; - - return self; -} - -- (void)drawRect:(CGRect)rect -{ - // Drawing code -} - -- (void)dealloc -{ - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/MainViewController.h b/samples/MapTestbedTwoMaps/Classes/MainViewController.h deleted file mode 100644 index f9997abcd..000000000 --- a/samples/MapTestbedTwoMaps/Classes/MainViewController.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// MainViewController.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@interface MainViewController : UIViewController -{ - IBOutlet RMMapView *upperMapView; - IBOutlet RMMapView *lowerMapView; -} - -@property (nonatomic, retain) IBOutlet RMMapView *upperMapView; -@property (nonatomic, retain) IBOutlet RMMapView *lowerMapView; - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/MainViewController.m b/samples/MapTestbedTwoMaps/Classes/MainViewController.m deleted file mode 100644 index 56c5d4ba0..000000000 --- a/samples/MapTestbedTwoMaps/Classes/MainViewController.m +++ /dev/null @@ -1,98 +0,0 @@ -// -// MainViewController.m -// MapTestbed : Diagnostic map -// - -#import "MainViewController.h" -#import "MapTestbedTwoMapsAppDelegate.h" -#import "RMOpenStreetMapSource.h" -#import "RMOpenCycleMapSource.h" - -#import "MainView.h" - -@implementation MainViewController - -@synthesize upperMapView; -@synthesize lowerMapView; - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil -{ - if (!(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) - return nil; - - return self; -} - -// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileNotification:) name:RMTileRequested object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileNotification:) name:RMTileRetrieved object:nil]; - - CLLocationCoordinate2D center; - center.latitude = 47.592; - center.longitude = -122.333; - - [upperMapView setDelegate:self]; - upperMapView.tileSource = [[[RMOpenStreetMapSource alloc] init] autorelease]; - [upperMapView setCenterCoordinate:center animated:NO]; - - [lowerMapView setDelegate:self]; - lowerMapView.tileSource = [[[RMOpenCycleMapSource alloc] init] autorelease]; - [lowerMapView setCenterCoordinate:center animated:NO]; - - NSLog(@"%@ %@", upperMapView, lowerMapView); -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)viewDidAppear:(BOOL)animated -{ -} - -- (void)dealloc -{ - self.upperMapView = nil; - self.lowerMapView = nil; - [super dealloc]; -} - -#pragma mark - -#pragma mark Delegate methods - -- (void)afterMapMove:(RMMapView *)map -{ - if (map == upperMapView) - [lowerMapView setCenterCoordinate:upperMapView.centerCoordinate animated:NO]; -} - -- (void)afterMapZoom:(RMMapView *)map -{ - if (map == upperMapView) { - lowerMapView.zoom = upperMapView.zoom; - [lowerMapView setCenterCoordinate:upperMapView.centerCoordinate animated:NO]; - } -} - -#pragma mark - -#pragma mark Notification methods - -- (void)tileNotification:(NSNotification *)notification -{ - static int outstandingTiles = 0; - - if (notification.name == RMTileRequested) - outstandingTiles++; - else if(notification.name == RMTileRetrieved) - outstandingTiles--; - - [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:(outstandingTiles > 0)]; -} - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/MapTestbedTwoMapsAppDelegate.h b/samples/MapTestbedTwoMaps/Classes/MapTestbedTwoMapsAppDelegate.h deleted file mode 100644 index 5487a38a8..000000000 --- a/samples/MapTestbedTwoMaps/Classes/MapTestbedTwoMapsAppDelegate.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// MapTestbedAppDelegate.h -// MapTestbed : Diagnostic map -// - -#import -#import "RMMapView.h" - -@class RootViewController; - -@interface MapTestbedTwoMapsAppDelegate : NSObject -{ - UIWindow *window; - RootViewController *rootViewController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet RootViewController *rootViewController; - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/MapTestbedTwoMapsAppDelegate.m b/samples/MapTestbedTwoMaps/Classes/MapTestbedTwoMapsAppDelegate.m deleted file mode 100644 index 172655af5..000000000 --- a/samples/MapTestbedTwoMaps/Classes/MapTestbedTwoMapsAppDelegate.m +++ /dev/null @@ -1,35 +0,0 @@ -// -// MapTestbedAppDelegate.m -// MapTestbed : Diagnostic map -// - -#import "MapTestbedTwoMapsAppDelegate.h" -#import "RootViewController.h" - -#import "RMPath.h" - -@implementation MapTestbedTwoMapsAppDelegate - -@synthesize window; -@synthesize rootViewController; - -- (void)performTest -{ -} - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - [window addSubview:[rootViewController view]]; - [window makeKeyAndVisible]; - - [self performSelector:@selector(performTest) withObject:nil afterDelay:1.0]; -} - -- (void)dealloc -{ - [rootViewController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/RootViewController.h b/samples/MapTestbedTwoMaps/Classes/RootViewController.h deleted file mode 100644 index cc575e72d..000000000 --- a/samples/MapTestbedTwoMaps/Classes/RootViewController.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// RootViewController.h -// MapTestbed : Diagnostic map -// - -#import - -@class MainViewController; -@class FlipsideViewController; - -@interface RootViewController : UIViewController -{ - UIButton *infoButton; - MainViewController *mainViewController; - FlipsideViewController *flipsideViewController; - UINavigationBar *flipsideNavigationBar; -} - -@property (nonatomic, retain) IBOutlet UIButton *infoButton; -@property (nonatomic, retain) MainViewController *mainViewController; -@property (nonatomic, retain) UINavigationBar *flipsideNavigationBar; -@property (nonatomic, retain) FlipsideViewController *flipsideViewController; - -- (IBAction)toggleView; - -@end diff --git a/samples/MapTestbedTwoMaps/Classes/RootViewController.m b/samples/MapTestbedTwoMaps/Classes/RootViewController.m deleted file mode 100644 index d3400c627..000000000 --- a/samples/MapTestbedTwoMaps/Classes/RootViewController.m +++ /dev/null @@ -1,101 +0,0 @@ -// -// RootViewController.m -// MapTestbed : Diagnostic map -// - -#import "RootViewController.h" -#import "MainViewController.h" -#import "FlipsideViewController.h" - -@implementation RootViewController - -@synthesize infoButton; -@synthesize flipsideNavigationBar; -@synthesize mainViewController; -@synthesize flipsideViewController; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - MainViewController *viewController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil]; - self.mainViewController = viewController; - [viewController release]; - - [self.view insertSubview:mainViewController.view belowSubview:infoButton]; -} - -- (void)loadFlipsideViewController -{ - FlipsideViewController *viewController = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil]; - self.flipsideViewController = viewController; - [viewController release]; - - // Set up the navigation bar - UINavigationBar *aNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)]; - aNavigationBar.barStyle = UIBarStyleBlackOpaque; - self.flipsideNavigationBar = aNavigationBar; - [aNavigationBar release]; - - UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(toggleView)]; - UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"MapTestbed"]; - navigationItem.rightBarButtonItem = buttonItem; - [flipsideNavigationBar pushNavigationItem:navigationItem animated:NO]; - [navigationItem release]; - [buttonItem release]; -} - -- (IBAction)toggleView -{ - /* - This method is called when the info or Done button is pressed. - It flips the displayed view from the main view to the flipside view and vice-versa. - */ - if (flipsideViewController == nil) - [self loadFlipsideViewController]; - - UIView *mainView = mainViewController.view; - UIView *flipsideView = flipsideViewController.view; - - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:1]; - [UIView setAnimationTransition:([mainView superview] ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES]; - - if ([mainView superview] != nil) { - [flipsideViewController viewWillAppear:YES]; - [mainViewController viewWillDisappear:YES]; - [mainView removeFromSuperview]; - [infoButton removeFromSuperview]; - [self.view addSubview:flipsideView]; - [self.view insertSubview:flipsideNavigationBar aboveSubview:flipsideView]; - [mainViewController viewDidDisappear:YES]; - [flipsideViewController viewDidAppear:YES]; - - } else { - [mainViewController viewWillAppear:YES]; - [flipsideViewController viewWillDisappear:YES]; - [flipsideView removeFromSuperview]; - [flipsideNavigationBar removeFromSuperview]; - [self.view addSubview:mainView]; - [self.view insertSubview:infoButton aboveSubview:mainViewController.view]; - [flipsideViewController viewDidDisappear:YES]; - [mainViewController viewDidAppear:YES]; - } - [UIView commitAnimations]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)dealloc -{ - [infoButton release]; - [flipsideNavigationBar release]; - [mainViewController release]; - [flipsideViewController release]; - [super dealloc]; -} - -@end diff --git a/samples/MapTestbedTwoMaps/FlipsideView.xib b/samples/MapTestbedTwoMaps/FlipsideView.xib deleted file mode 100644 index d5e010f90..000000000 --- a/samples/MapTestbedTwoMaps/FlipsideView.xib +++ /dev/null @@ -1,495 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 274 - - YES - - - 292 - {{20, 61}, {175, 21}} - - NO - YES - NO - Map center latitude - - 1 - MCAwIDAAA - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 170}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - 2 - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 95}, {175, 21}} - - NO - YES - NO - Map center longitude - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 136}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 141}, {175, 21}} - - NO - YES - NO - Zoom level - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 204}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 209}, {175, 21}} - - NO - YES - NO - Zoom Minimun - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 90}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 175}, {175, 21}} - - NO - YES - NO - Zoom Maximum - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 58}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - {320, 460} - - - 1 - MC44Njk1NjUyNSAwLjg2OTU2NTI1IDAuODY5NTY1MjUAA - - NO - - 2 - - - - - - YES - - - view - - - - 41 - - - - centerLatitude - - - - 65 - - - - centerLongitude - - - - 66 - - - - zoomLevel - - - - 67 - - - - maxZoom - - - - 68 - - - - minZoom - - - - 69 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - -2 - - - - - 40 - - - YES - - - - - - - - - - - - - - - 42 - - - - - 43 - - - - - 44 - - - - - 45 - - - - - 46 - - - - - 47 - - - - - 48 - - - - - 49 - - - - - 50 - - - - - 51 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 40.CustomClassName - 40.IBEditorWindowLastContentRect - 40.IBPluginDependency - 40.IBUserGuides - 42.IBPluginDependency - 43.IBPluginDependency - 44.IBPluginDependency - 45.IBPluginDependency - 46.IBPluginDependency - 47.IBPluginDependency - 48.IBPluginDependency - 49.IBPluginDependency - 50.IBPluginDependency - 51.IBPluginDependency - - - YES - FlipsideViewController - UIResponder - FlipsideView - {{637, 393}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - YES - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 69 - - - - YES - - FlipsideView - UIView - - IBProjectSource - Classes/FlipsideView.h - - - - FlipsideViewController - UIViewController - - YES - - YES - centerLatitude - centerLongitude - maxZoom - minZoom - zoomLevel - - - YES - UITextField - UITextField - UITextField - UITextField - UITextField - - - - IBProjectSource - Classes/FlipsideViewController.h - - - - - 0 - MapTestbed.xcodeproj - 3 - - diff --git a/samples/MapTestbedTwoMaps/Info.plist b/samples/MapTestbedTwoMaps/Info.plist deleted file mode 100644 index fdf834060..000000000 --- a/samples/MapTestbedTwoMaps/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/samples/MapTestbedTwoMaps/MainView.xib b/samples/MapTestbedTwoMaps/MainView.xib deleted file mode 100644 index ea7273dae..000000000 --- a/samples/MapTestbedTwoMaps/MainView.xib +++ /dev/null @@ -1,227 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 274 - - YES - - - 274 - {320, 225} - - - 1 - MSAwLjE1OTAzMTQ4IDAuMTM1NDQ5ODMAA - - NO - YES - - - - 274 - {{0, 238}, {320, 222}} - - - 1 - MC41MTU4ODg1MSAwLjQ2OTcxMDQxIDEAA - - NO - YES - - - {320, 460} - - - 1 - MC4zNzk1OTUzNCAxIDAuMjkxNTQ3MTgAA - - NO - - - - - YES - - - view - - - - 40 - - - - upperMapView - - - - 47 - - - - lowerMapView - - - - 50 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - -2 - - - - - 37 - - - YES - - - - - - - 39 - - - YES - - - Upper Map View - - - 49 - - - Lower Map View - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 37.IBEditorWindowLastContentRect - 37.IBPluginDependency - 39.CustomClassName - 39.IBPluginDependency - 49.CustomClassName - 49.IBPluginDependency - - - YES - MainViewController - UIResponder - {{741, 489}, {320, 460}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RMMapView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RMMapView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 50 - - - - YES - - MainViewController - UIViewController - - YES - - YES - lowerMapView - upperMapView - - - YES - RMMapView - RMMapView - - - - IBProjectSource - Classes/MainViewController.h - - - - - 0 - MapTestbedTwoMaps.xcodeproj - 3 - - diff --git a/samples/MapTestbedTwoMaps/MainWindow.xib b/samples/MapTestbedTwoMaps/MainWindow.xib deleted file mode 100644 index c406b7396..000000000 --- a/samples/MapTestbedTwoMaps/MainWindow.xib +++ /dev/null @@ -1,314 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - - 1316 - - {320, 480} - - 1 - MCAwIDAAA - - NO - YES - - - - - - 274 - - YES - - - 265 - {{274, 414}, {18, 19}} - - NO - NO - 0 - 0 - - Helvetica-Bold - 1.500000e+01 - 16 - - 4 - YES - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - {320, 460} - - 3 - MQA - - 2 - - - NO - - - - - - - YES - - - delegate - - - - 4 - - - - window - - - - 5 - - - - rootViewController - - - - 10 - - - - infoButton - - - - 20 - - - - toggleView - - - 7 - - 21 - - - - - YES - - 0 - - YES - - - - - - 2 - - - YES - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - 3 - - - - - 8 - - - YES - - - - - - -2 - - - - - 18 - - - YES - - - - - - 19 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 18.IBPluginDependency - 19.IBPluginDependency - 2.IBAttributePlaceholdersKey - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - 8.CustomClassName - 8.IBEditorWindowLastContentRect - 8.IBPluginDependency - - - YES - UIApplication - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - YES - - YES - - - YES - - - {{700, 391}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MapTestbedTwoMapsAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RootViewController - {{391, 356}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 21 - - - - YES - - MapTestbedTwoMapsAppDelegate - NSObject - - YES - - YES - rootViewController - window - - - YES - RootViewController - UIWindow - - - - IBProjectSource - Classes/MapTestbedTwoMapsAppDelegate.h - - - - MapTestbedTwoMapsAppDelegate - NSObject - - IBUserSource - - - - - RootViewController - UIViewController - - toggleView - id - - - infoButton - UIButton - - - IBProjectSource - Classes/RootViewController.h - - - - - 0 - MapTestbedTwoMaps.xcodeproj - 3 - - diff --git a/samples/MapTestbedTwoMaps/MapTestbedTwoMaps.xcodeproj/project.pbxproj b/samples/MapTestbedTwoMaps/MapTestbedTwoMaps.xcodeproj/project.pbxproj deleted file mode 100755 index b8638068a..000000000 --- a/samples/MapTestbedTwoMaps/MapTestbedTwoMaps.xcodeproj/project.pbxproj +++ /dev/null @@ -1,377 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1D3623260D0F684500981E51 /* MapTestbedTwoMapsAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* MapTestbedTwoMapsAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754A0DD40C5E005A515E /* FlipsideView.xib */; }; - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754B0DD40C5E005A515E /* MainView.xib */; }; - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754C0DD40C5E005A515E /* MainWindow.xib */; }; - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765580DF743DE002DB57D /* CoreGraphics.framework */; }; - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A30DB2D0840083E9F9 /* FlipsideView.m */; }; - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A50DB2D0840083E9F9 /* MainView.m */; }; - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A90DB2D0DB0083E9F9 /* MainViewController.m */; }; - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */; }; - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */; }; - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */; }; - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E10F649CE100377FFE /* QuartzCore.framework */; }; - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */; }; - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE3697D0F673B95003DC21C /* libMapView.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; - EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* MapTestbedTwoMapsAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapTestbedTwoMapsAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* MapTestbedTwoMapsAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MapTestbedTwoMapsAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* TwoMaps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TwoMaps.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 280E754A0DD40C5E005A515E /* FlipsideView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FlipsideView.xib; sourceTree = ""; }; - 280E754B0DD40C5E005A515E /* MainView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainView.xib; sourceTree = ""; }; - 280E754C0DD40C5E005A515E /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 288765580DF743DE002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 289233A20DB2D0840083E9F9 /* FlipsideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideView.h; path = Classes/FlipsideView.h; sourceTree = ""; }; - 289233A30DB2D0840083E9F9 /* FlipsideView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideView.m; path = Classes/FlipsideView.m; sourceTree = ""; }; - 289233A40DB2D0840083E9F9 /* MainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainView.h; path = Classes/MainView.h; sourceTree = ""; }; - 289233A50DB2D0840083E9F9 /* MainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainView.m; path = Classes/MainView.m; sourceTree = ""; }; - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = ""; }; - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = ""; }; - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideViewController.h; path = Classes/FlipsideViewController.h; sourceTree = ""; }; - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideViewController.m; path = Classes/FlipsideViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2BB42C520F678FA9009967BB /* MapTestbedTwoMaps_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapTestbedTwoMaps_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */, - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */, - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */, - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */, - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Application Controllers */ = { - isa = PBXGroup; - children = ( - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */, - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */, - 1D3623240D0F684500981E51 /* MapTestbedTwoMapsAppDelegate.h */, - 1D3623250D0F684500981E51 /* MapTestbedTwoMapsAppDelegate.m */, - ); - name = "Application Controllers"; - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* TwoMaps.app */, - ); - name = Products; - sourceTree = ""; - }; - 281C6CD70DB2D82200F60ACC /* Flipside View */ = { - isa = PBXGroup; - children = ( - 289233A20DB2D0840083E9F9 /* FlipsideView.h */, - 289233A30DB2D0840083E9F9 /* FlipsideView.m */, - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */, - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */, - ); - name = "Flipside View"; - sourceTree = ""; - }; - 289233A00DB2D0730083E9F9 /* Main View */ = { - isa = PBXGroup; - children = ( - 289233A40DB2D0840083E9F9 /* MainView.h */, - 289233A50DB2D0840083E9F9 /* MainView.m */, - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */, - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */, - ); - name = "Main View"; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */, - 289233A00DB2D0730083E9F9 /* Main View */, - 281C6CD70DB2D82200F60ACC /* Flipside View */, - 080E96DDFE201D6D7F000001 /* Application Controllers */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 2BB42C520F678FA9009967BB /* MapTestbedTwoMaps_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 280E754A0DD40C5E005A515E /* FlipsideView.xib */, - 280E754B0DD40C5E005A515E /* MainView.xib */, - 280E754C0DD40C5E005A515E /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 288765580DF743DE002DB57D /* CoreGraphics.framework */, - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */, - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */, - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */, - ); - name = Frameworks; - sourceTree = ""; - }; - EBE3696E0F673B95003DC21C /* Products */ = { - isa = PBXGroup; - children = ( - EBE3697D0F673B95003DC21C /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* MapTestbedTwoMaps */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MapTestbedTwoMaps" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BB42BEF0F678951009967BB /* PBXTargetDependency */, - ); - name = MapTestbedTwoMaps; - productName = Sample2; - productReference = 1D6058910D05DD3D006BFB54 /* TwoMaps.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapTestbedTwoMaps" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - en, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = EBE3696E0F673B95003DC21C /* Products */; - ProjectRef = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* MapTestbedTwoMaps */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - EBE3697D0F673B95003DC21C /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */, - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */, - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* MapTestbedTwoMapsAppDelegate.m in Sources */, - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */, - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */, - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */, - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */, - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BB42BEF0F678951009967BB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapTestbedTwoMaps_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = TwoMaps; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_DYNAMIC_NO_PIC = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MapTestbedTwoMaps_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = TwoMaps; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - SDKROOT = iphoneos; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "MapTestbedTwoMaps" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MapTestbedTwoMaps" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/MapTestbedTwoMaps/MapTestbedTwoMaps_Prefix.pch b/samples/MapTestbedTwoMaps/MapTestbedTwoMaps_Prefix.pch deleted file mode 100644 index 6c15d1f1d..000000000 --- a/samples/MapTestbedTwoMaps/MapTestbedTwoMaps_Prefix.pch +++ /dev/null @@ -1,9 +0,0 @@ -// -// Prefix header for all source files of the 'MapTestbed' target in the 'MapTestbed' project -// - -#ifdef __OBJC__ - #import - #import -#endif -#define LogMethod() NSLog(@"%s logged method call: -[%@ %s] (line %d)", _cmd, self, _cmd, __LINE__) diff --git a/samples/MapTestbedTwoMaps/main.m b/samples/MapTestbedTwoMaps/main.m deleted file mode 100644 index b370a3ea8..000000000 --- a/samples/MapTestbedTwoMaps/main.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// main.m -// MapTestbed : Diagnostic map -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/MarkerMurder/Classes/FlipsideView.h b/samples/MarkerMurder/Classes/FlipsideView.h deleted file mode 100644 index ce0418437..000000000 --- a/samples/MarkerMurder/Classes/FlipsideView.h +++ /dev/null @@ -1,10 +0,0 @@ -// -// FlipsideView.h -// SampleMap : Diagnostic map -// - -#import - -@interface FlipsideView : UIView - -@end diff --git a/samples/MarkerMurder/Classes/FlipsideView.m b/samples/MarkerMurder/Classes/FlipsideView.m deleted file mode 100644 index 71314e27b..000000000 --- a/samples/MarkerMurder/Classes/FlipsideView.m +++ /dev/null @@ -1,18 +0,0 @@ -// -// FlipsideView.m -// SampleMap : Diagnostic map -// - -#import "FlipsideView.h" - -@implementation FlipsideView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return nil; - - return self; -} - -@end diff --git a/samples/MarkerMurder/Classes/FlipsideViewController.h b/samples/MarkerMurder/Classes/FlipsideViewController.h deleted file mode 100644 index 5e5c3f473..000000000 --- a/samples/MarkerMurder/Classes/FlipsideViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// FlipsideViewController.h -// SampleMap : Diagnostic map -// - -#import -#import "RMMapView.h" - -@interface FlipsideViewController : UIViewController - -@property(nonatomic,retain) IBOutlet UITextField *centerLatitude; -@property(nonatomic,retain) IBOutlet UITextField *centerLongitude; -@property(nonatomic,retain) IBOutlet UITextField *zoomLevel; -@property(nonatomic,retain) IBOutlet UITextField *minZoom; -@property(nonatomic,retain) IBOutlet UITextField *maxZoom; - -- (IBAction)clearSharedNSURLCache; -- (IBAction)clearMapContentsCachedImages; - -@end diff --git a/samples/MarkerMurder/Classes/FlipsideViewController.m b/samples/MarkerMurder/Classes/FlipsideViewController.m deleted file mode 100644 index d6f26e044..000000000 --- a/samples/MarkerMurder/Classes/FlipsideViewController.m +++ /dev/null @@ -1,82 +0,0 @@ -// -// FlipsideViewController.m -// SampleMap : Diagnostic map -// - -#import "FlipsideViewController.h" -#import "MarkerMurderAppDelegate.h" -#import "MainViewController.h" -#import "RootViewController.h" - -@implementation FlipsideViewController - -@synthesize centerLatitude; -@synthesize centerLongitude; -@synthesize zoomLevel; -@synthesize minZoom; -@synthesize maxZoom; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.view.backgroundColor = [UIColor groupTableViewBackgroundColor]; -} - -- (void)didReceiveMemoryWarning -{ - RMLog(@"didReceiveMemoryWarning %@", self); - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (RMMapView *)mapView -{ - return [[[(MarkerMurderAppDelegate *)[[UIApplication sharedApplication] delegate] rootViewController] mainViewController] mapView]; -} - - -- (void)viewDidAppear:(BOOL)animated -{ - CLLocationCoordinate2D mapCenter = [[self mapView] centerCoordinate]; - - [centerLatitude setText:[NSString stringWithFormat:@"%f", mapCenter.latitude]]; - [centerLongitude setText:[NSString stringWithFormat:@"%f", mapCenter.longitude]]; - [zoomLevel setText:[NSString stringWithFormat:@"%.1f", [self mapView].zoom]]; - [maxZoom setText:[NSString stringWithFormat:@"%.1f", [self mapView].maxZoom]]; - [minZoom setText:[NSString stringWithFormat:@"%.1f", [self mapView].minZoom]]; -} - -- (void)viewWillDisappear:(BOOL)animated -{ - CLLocationCoordinate2D newMapCenter; - - newMapCenter.latitude = [[centerLatitude text] doubleValue]; - newMapCenter.longitude = [[centerLongitude text] doubleValue]; - [[self mapView] setCenterCoordinate:newMapCenter animated:NO]; - [[self mapView] setZoom:[[zoomLevel text] floatValue]]; - [[self mapView] setMaxZoom:[[maxZoom text] floatValue]]; - [[self mapView] setMinZoom:[[minZoom text] floatValue]]; -} - -- (void)dealloc -{ - self.centerLatitude = nil; - self.centerLongitude = nil; - self.zoomLevel = nil; - self.minZoom = nil; - self.maxZoom = nil; - [super dealloc]; -} - -- (IBAction)clearSharedNSURLCache -{ - [[NSURLCache sharedURLCache] removeAllCachedResponses]; -} - -- (IBAction)clearMapContentsCachedImages -{ - [[self mapView] removeAllCachedImages]; -} - -@end diff --git a/samples/MarkerMurder/Classes/MainView.h b/samples/MarkerMurder/Classes/MainView.h deleted file mode 100644 index 475135711..000000000 --- a/samples/MarkerMurder/Classes/MainView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// MainView.h -// SampleMap : Diagnostic map -// - -#import - -@interface MainView : UIView -{ -} - -@end diff --git a/samples/MarkerMurder/Classes/MainView.m b/samples/MarkerMurder/Classes/MainView.m deleted file mode 100644 index 14969a39f..000000000 --- a/samples/MarkerMurder/Classes/MainView.m +++ /dev/null @@ -1,18 +0,0 @@ -// -// MainView.m -// SampleMap : Diagnostic map -// - -#import "MainView.h" - -@implementation MainView - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - return self; - - return self; -} - -@end diff --git a/samples/MarkerMurder/Classes/MainViewController.h b/samples/MarkerMurder/Classes/MainViewController.h deleted file mode 100644 index af446cbd6..000000000 --- a/samples/MarkerMurder/Classes/MainViewController.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// MainViewController.h -// SampleMap : Diagnostic map -// - -#import -#import "RMMapView.h" - -@interface MainViewController : UIViewController - -@property (nonatomic, retain) IBOutlet RMMapView *mapView; -@property (nonatomic, retain) IBOutlet UITextView *infoTextView; -@property (nonatomic, retain) IBOutlet UILabel *mppLabel; -@property (nonatomic, retain) IBOutlet UIImageView *mppImage; - -- (void)updateInfo; - -@end diff --git a/samples/MarkerMurder/Classes/MainViewController.m b/samples/MarkerMurder/Classes/MainViewController.m deleted file mode 100644 index c2ae40fa9..000000000 --- a/samples/MarkerMurder/Classes/MainViewController.m +++ /dev/null @@ -1,383 +0,0 @@ -// -// MainViewController.m -// SampleMap : Diagnostic map -// - -#import "MainViewController.h" -#import "MarkerMurderAppDelegate.h" - -#import "MainView.h" - -#import "RMOpenStreetMapSource.h" -#import "RMOpenSeaMapLayer.h" -#import "RMMapView.h" -#import "RMMarker.h" -#import "RMCircle.h" -#import "RMProjection.h" -#import "RMAnnotation.h" -#import "RMQuadTree.h" -#import "RMCoordinateGridSource.h" -#import "RMOpenCycleMapSource.h" - -@implementation MainViewController -{ - CLLocationCoordinate2D center; - - BOOL tapped; - NSUInteger tapCount; -} - -@synthesize mapView; -@synthesize infoTextView; -@synthesize mppLabel, mppImage; - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil -{ - if (!(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) - return nil; - - //Notifications for tile requests. This code allows for a class to know when a tile is requested and retrieved -// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileRequested:) name:@"RMTileRequested" object:nil ]; -// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileRetrieved:) name:@"RMTileRetrieved" object:nil ]; - - tapped = NO; - tapCount = 0; - - return self; -} - -- (void)tileRequested:(NSNotification *)notification -{ - NSLog(@"Tile request started."); -} - -- (void)tileRetrieved:(NSNotification *)notification -{ - NSLog(@"Tile request ended."); -} - -#define kNumberRows 2 -#define kNumberColumns 9 -#define kSpacing 0.1 - -#define kCircleAnnotationType @"circleAnnotation" -#define kDraggableAnnotationType @"draggableAnnotation" - -- (void)addMarkers -{ - CLLocationCoordinate2D markerPosition; - - UIImage *redMarkerImage = [UIImage imageNamed:@"marker-red.png"]; - UIImage *blueMarkerImage = [UIImage imageNamed:@"marker-blue.png"]; - - markerPosition.latitude = center.latitude - ((kNumberRows - 1)/2.0 * kSpacing); - - for (int i = 0; i < kNumberRows; i++) - { - markerPosition.longitude = center.longitude - ((kNumberColumns - 1)/2.0 * kSpacing); - - for (int j = 0; j < kNumberColumns; j++) - { - markerPosition.longitude += kSpacing; - - NSLog(@"Add marker @ {%f,%f} = {%f,%f}", markerPosition.longitude, markerPosition.latitude, [mapView coordinateToProjectedPoint:markerPosition].x, [mapView coordinateToProjectedPoint:markerPosition].y); - - RMAnnotation *annotation = [RMAnnotation annotationWithMapView:mapView coordinate:markerPosition andTitle:[NSString stringWithFormat:@"%4.1f", markerPosition.longitude]]; - - if ((markerPosition.longitude < -180) || (markerPosition.longitude > 0)) - { - annotation.annotationIcon = redMarkerImage; - annotation.anchorPoint = CGPointMake(0.5, 1.0); - } - else - { - annotation.annotationIcon = blueMarkerImage; - annotation.anchorPoint = CGPointMake(0.5, 1.0); - } - - [mapView addAnnotation:annotation]; - } - - markerPosition.latitude += kSpacing; - } - - RMAnnotation *circleAnnotation = [RMAnnotation annotationWithMapView:mapView coordinate:CLLocationCoordinate2DMake(47.4, 10.0) andTitle:@"A Circle"]; - circleAnnotation.annotationType = kCircleAnnotationType; - [mapView addAnnotation:circleAnnotation]; - - RMAnnotation *draggableAnnotation = [RMAnnotation annotationWithMapView:mapView coordinate:CLLocationCoordinate2DMake(47.72, 10.2) andTitle:@"Drag me! Tap me!"]; - draggableAnnotation.annotationType = kDraggableAnnotationType; - draggableAnnotation.annotationIcon = [UIImage imageNamed:@"marker-blue.png"]; - draggableAnnotation.anchorPoint = CGPointMake(0.5, 1.0); - draggableAnnotation.clusteringEnabled = NO; - draggableAnnotation.userInfo = [NSDictionary dictionaryWithObjectsAndKeys: - [UIColor blueColor],@"foregroundColor", - nil]; - [mapView addAnnotation:draggableAnnotation]; -} - -// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. -- (void)viewDidLoad -{ - [super viewDidLoad]; - - mapView.delegate = self; - mapView.enableClustering = YES; - mapView.positionClusterMarkersAtTheGravityCenter = YES; - -// mapView.adjustTilesForRetinaDisplay = YES; -// mapView.decelerationMode = RMMapDecelerationOff; -// mapView.enableBouncing = NO; -// mapView.enableDragging = YES; -// mapView.debugTiles = YES; -// [mapView setConstraintsSouthWest:CLLocationCoordinate2DMake(47.0, 10.0) northEast:CLLocationCoordinate2DMake(48.0, 11.0)]; -// [mapView addTileSource:[[[RMCoordinateGridSource alloc] init] autorelease]]; - - UIImage *clusterMarkerImage = [UIImage imageNamed:@"marker-blue.png"]; - mapView.clusterMarkerSize = clusterMarkerImage.size; - mapView.clusterAreaSize = CGSizeMake(clusterMarkerImage.size.width * 1.25, clusterMarkerImage.size.height * 1.25); - - center.latitude = 47.5635; - center.longitude = 10.20981; - -// int zoneNumber; -// BOOL isNorthernHemisphere; -// NSString *utmZone; -// double easting, northing; -// -// [RMProjection convertCoordinate:center -// toUTMZoneNumber:&zoneNumber -// utmZoneLetter:&utmZone -// isNorthernHemisphere:&isNorthernHemisphere -// easting:&easting -// northing:&northing]; -// -// NSLog(@"{%f,%f} -> %d%@ %.0f %.0f (north: %@)", center.latitude, center.longitude, zoneNumber, utmZone, easting, northing, isNorthernHemisphere ? @"YES" : @"NO"); -// -// CLLocationCoordinate2D coordinate; -// [RMProjection convertUTMZoneNumber:zoneNumber -// utmZoneLetter:utmZone -// isNorthernHemisphere:isNorthernHemisphere -// easting:easting -// northing:northing -// toCoordinate:&coordinate]; -// -// NSLog(@"-> {%f,%f}", coordinate.latitude, coordinate.longitude); - -// [mapView zoomWithLatitudeLongitudeBoundsSouthWest:CLLocationCoordinate2DMake(47.5, 10.15) northEast:CLLocationCoordinate2DMake(47.6, 10.25) animated:NO]; - - [mapView setZoom:10.0]; - [mapView setCenterCoordinate:center animated:NO]; - mapView.showsUserLocation = YES; - - [self updateInfo]; - [self performSelector:@selector(addMarkers) withObject:nil afterDelay:0.5]; - -// // Tile bounding box -// RMSphericalTrapezium tileBoundingBox = [mapView latitudeLongitudeBoundingBoxForTile:RMTileMake(541, 357, 10)]; -// -// RMAnnotation *annotation = [RMAnnotation annotationWithMapView:mapView coordinate:tileBoundingBox.southWest andTitle:@"bbox SouthWest"]; -// annotation.annotationIcon = [UIImage imageNamed:@"marker-red.png"]; -// annotation.anchorPoint = CGPointMake(0.5, 1.0); -// annotation.clusteringEnabled = NO; -// [mapView addAnnotation:annotation]; -// -// annotation = [RMAnnotation annotationWithMapView:mapView coordinate:tileBoundingBox.northEast andTitle:@"bbox NorthEast"]; -// annotation.annotationIcon = [UIImage imageNamed:@"marker-red.png"]; -// annotation.anchorPoint = CGPointMake(0.5, 1.0); -// annotation.clusteringEnabled = NO; -// [mapView addAnnotation:annotation]; - - // Tile sources -// [mapView setTileSources:@[ -// [[[RMOpenStreetMapSource alloc] init] autorelease], -// [[[RMOpenSeaMapLayer alloc] init] autorelease] -// ]]; - -// double delayInSeconds = 5.0; -// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); -// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { -// [mapView addTileSource:[[[RMCoordinateGridSource alloc] init] autorelease]]; -// -// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); -// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { -// [mapView setHidden:YES forTileSourceAtIndex:1]; -// -// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); -// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { -// [mapView setHidden:NO forTileSourceAtIndex:1]; -// -// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); -// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { -// [mapView removeTileSourceAtIndex:1]; -// }); -// }); -// }); -// }); -} - -- (void)didReceiveMemoryWarning -{ - RMLog(@"didReceiveMemoryWarning %@", self); - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)viewDidAppear:(BOOL)animated -{ - [self updateInfo]; -} - -- (void)viewDidUnload -{ - [self setMppLabel:nil]; - [super viewDidUnload]; -} - -- (void)dealloc -{ - self.infoTextView = nil; - self.mapView = nil; - self.mppLabel = nil; - [super dealloc]; -} - -- (void)updateInfo -{ - CLLocationCoordinate2D mapCenter = [mapView centerCoordinate]; - - [infoTextView setText:[NSString stringWithFormat:@"Longitude : %f\nLatitude : %f\nZoom level : %.2f\nScale : 1:%.0f\n%@", - mapCenter.longitude, - mapCenter.latitude, - mapView.zoom, - mapView.scaleDenominator, - [[mapView tileSource] shortAttribution] - ]]; - - [mppLabel setText:[NSString stringWithFormat:@"%.0f m", mapView.metersPerPixel * mppImage.bounds.size.width]]; -} - -#pragma mark - -#pragma mark Delegate methods - -- (void)afterMapMove:(RMMapView *)map -{ - [self updateInfo]; -} - -- (void)afterMapZoom:(RMMapView *)map -{ - [self updateInfo]; -} - -// Don't use this delegate method for long running tasks since it blocks the main thread - use #afterMapMove or #afterMapZoom instead -- (void)mapViewRegionDidChange:(RMMapView *)mapView -{ - [self updateInfo]; -} - -- (BOOL)mapView:(RMMapView *)map shouldDragAnnotation:(RMAnnotation *)annotation -{ - if ([annotation.annotationType isEqualToString:kDraggableAnnotationType]) - { - NSLog(@"Start dragging marker"); - return YES; - } - - return NO; -} - -- (void)mapView:(RMMapView *)map didDragAnnotation:(RMAnnotation *)annotation withDelta:(CGPoint)delta -{ - CGPoint screenPosition = CGPointMake(annotation.position.x - delta.x, annotation.position.y - delta.y); - - annotation.coordinate = [mapView pixelToCoordinate:screenPosition]; - annotation.position = screenPosition; -} - -- (void)mapView:(RMMapView *)map didEndDragAnnotation:(RMAnnotation *)annotation -{ - RMProjectedPoint projectedPoint = annotation.projectedLocation; - CGPoint screenPoint = annotation.position; - - NSLog(@"Did end dragging marker, screen: {%.0f,%.0f}, projected: {%f,%f}, coordinate: {%f,%f}", screenPoint.x, screenPoint.y, projectedPoint.x, projectedPoint.y, annotation.coordinate.latitude, annotation.coordinate.longitude); -} - -- (void)tapOnLabelForAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map -{ - if ([annotation.annotationType isEqualToString:kDraggableAnnotationType]) - { - NSLog(@"Label <%@> tapped for marker <%@>", ((RMMarker *)annotation.layer).label, (RMMarker *)annotation.layer); - [(RMMarker *)annotation.layer changeLabelUsingText:[NSString stringWithFormat:@"Drag me! Tap me! (%d)", ++tapCount]]; - } -} - -- (void)singleTapOnMap:(RMMapView *)map at:(CGPoint)point -{ - RMProjectedPoint projectedPoint = [map pixelToProjectedPoint:point]; - CLLocationCoordinate2D coordinates = [map pixelToCoordinate:point]; - - NSLog(@"Clicked on Map - Location: x:%lf y:%lf, Projected east:%f north:%f, Coordinate lat:%f lon:%f", point.x, point.y, projectedPoint.x, projectedPoint.y, coordinates.latitude, coordinates.longitude); -} - -- (void)tapOnAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map -{ - if ([annotation.annotationType isEqualToString:kRMClusterAnnotationTypeName]) - { - [map zoomInToNextNativeZoomAt:[map coordinateToPixel:annotation.coordinate] animated:YES]; - } - else if ([annotation.annotationType isEqualToString:kDraggableAnnotationType]) - { - NSLog(@"MARKER TAPPED!"); - - if (!tapped) - { - annotation.annotationIcon = [UIImage imageNamed:@"marker-red.png"]; - [(RMMarker *)annotation.layer replaceUIImage:annotation.annotationIcon anchorPoint:annotation.anchorPoint]; - [(RMMarker *)annotation.layer changeLabelUsingText:@"Hello"]; - tapped = YES; - } - else - { - annotation.annotationIcon = [UIImage imageNamed:@"marker-blue.png"]; - [(RMMarker *)annotation.layer replaceUIImage:annotation.annotationIcon anchorPoint:annotation.anchorPoint]; - [(RMMarker *)annotation.layer changeLabelUsingText:@"World"]; - tapped = NO; - } - } -} - -- (RMMapLayer *)mapView:(RMMapView *)aMapView layerForAnnotation:(RMAnnotation *)annotation -{ - RMMapLayer *marker = nil; - - if ([annotation.annotationType isEqualToString:kRMClusterAnnotationTypeName]) - { - marker = [[[RMMarker alloc] initWithUIImage:[UIImage imageNamed:@"marker-blue.png"] anchorPoint:CGPointMake(0.5, 1.0)] autorelease]; - - if (annotation.title) - [(RMMarker *)marker changeLabelUsingText:annotation.title]; - } - else if ([annotation.annotationType isEqualToString:kCircleAnnotationType]) - { - marker = [[[RMCircle alloc] initWithView:aMapView radiusInMeters:10000.0] autorelease]; - [(RMCircle *)marker setLineWidthInPixels:5.0]; - } - else - { - marker = [[[RMMarker alloc] initWithUIImage:annotation.annotationIcon anchorPoint:annotation.anchorPoint] autorelease]; - - if (annotation.title) - [(RMMarker *)marker changeLabelUsingText:annotation.title]; - - if ([annotation.userInfo objectForKey:@"foregroundColor"]) - [(RMMarker *)marker setTextForegroundColor:[annotation.userInfo objectForKey:@"foregroundColor"]]; - - if ([annotation.annotationType isEqualToString:kDraggableAnnotationType]) - marker.enableDragging = YES; - } - - return marker; -} - -@end diff --git a/samples/MarkerMurder/Classes/MarkerMurderAppDelegate.h b/samples/MarkerMurder/Classes/MarkerMurderAppDelegate.h deleted file mode 100644 index dbb6e8ed6..000000000 --- a/samples/MarkerMurder/Classes/MarkerMurderAppDelegate.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// Sample2AppDelegate.h -// SampleMap : Diagnostic map -// - -#import -#import "RMMapView.h" - -@class RootViewController; - -@interface MarkerMurderAppDelegate : NSObject - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet RootViewController *rootViewController; - -@end diff --git a/samples/MarkerMurder/Classes/MarkerMurderAppDelegate.m b/samples/MarkerMurder/Classes/MarkerMurderAppDelegate.m deleted file mode 100644 index dcb00819c..000000000 --- a/samples/MarkerMurder/Classes/MarkerMurderAppDelegate.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// Sample2AppDelegate.m -// SampleMap : Diagnostic map -// - -#import "MarkerMurderAppDelegate.h" -#import "RootViewController.h" -#import "MainViewController.h" - -@implementation MarkerMurderAppDelegate - -@synthesize window; -@synthesize rootViewController; - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - [window addSubview:[rootViewController view]]; - [window makeKeyAndVisible]; -} - -- (void)dealloc -{ - [rootViewController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/MarkerMurder/Classes/RootViewController.h b/samples/MarkerMurder/Classes/RootViewController.h deleted file mode 100644 index a28cf4e2b..000000000 --- a/samples/MarkerMurder/Classes/RootViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// RootViewController.h -// SampleMap : Diagnostic map -// - -#import - -@class MainViewController; -@class FlipsideViewController; - -@interface RootViewController : UIViewController - -@property (nonatomic, retain) IBOutlet UIButton *infoButton; -@property (nonatomic, retain) MainViewController *mainViewController; -@property (nonatomic, retain) UINavigationBar *flipsideNavigationBar; -@property (nonatomic, retain) FlipsideViewController *flipsideViewController; - -- (IBAction)toggleView; - -@end diff --git a/samples/MarkerMurder/Classes/RootViewController.m b/samples/MarkerMurder/Classes/RootViewController.m deleted file mode 100644 index d9d8373cf..000000000 --- a/samples/MarkerMurder/Classes/RootViewController.m +++ /dev/null @@ -1,101 +0,0 @@ -// -// RootViewController.m -// SampleMap : Diagnostic map -// - -#import "RootViewController.h" -#import "MainViewController.h" -#import "FlipsideViewController.h" - -@implementation RootViewController - -@synthesize infoButton; -@synthesize flipsideNavigationBar; -@synthesize mainViewController; -@synthesize flipsideViewController; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - MainViewController *viewController = [[[MainViewController alloc] initWithNibName:@"MainView" bundle:nil] autorelease]; - self.mainViewController = viewController; - - [self.view insertSubview:mainViewController.view belowSubview:infoButton]; -} - -- (void)loadFlipsideViewController -{ - FlipsideViewController *viewController = [[[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil] autorelease]; - self.flipsideViewController = viewController; - - // Set up the navigation bar - UINavigationBar *aNavigationBar = [[[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)] autorelease]; - aNavigationBar.barStyle = UIBarStyleBlackOpaque; - self.flipsideNavigationBar = aNavigationBar; - - UIBarButtonItem *buttonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(toggleView)] autorelease]; - UINavigationItem *navigationItem = [[[UINavigationItem alloc] initWithTitle:@"SampleMap"] autorelease]; - navigationItem.rightBarButtonItem = buttonItem; - [flipsideNavigationBar pushNavigationItem:navigationItem animated:NO]; -} - -- (IBAction)toggleView -{ - /* - This method is called when the info or Done button is pressed. - It flips the displayed view from the main view to the flipside view and vice-versa. - */ - if (flipsideViewController == nil) - [self loadFlipsideViewController]; - - UIView *mainView = mainViewController.view; - UIView *flipsideView = flipsideViewController.view; - - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:1]; - [UIView setAnimationTransition:([mainView superview] ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES]; - - if ([mainView superview] != nil) - { - [flipsideViewController viewWillAppear:YES]; - [mainViewController viewWillDisappear:YES]; - [mainView removeFromSuperview]; - [infoButton removeFromSuperview]; - [self.view addSubview:flipsideView]; - [self.view insertSubview:flipsideNavigationBar aboveSubview:flipsideView]; - [mainViewController viewDidDisappear:YES]; - [flipsideViewController viewDidAppear:YES]; - } - else - { - [mainViewController viewWillAppear:YES]; - [flipsideViewController viewWillDisappear:YES]; - [flipsideView removeFromSuperview]; - [flipsideNavigationBar removeFromSuperview]; - [self.view addSubview:mainView]; - [self.view insertSubview:infoButton aboveSubview:mainViewController.view]; - [flipsideViewController viewDidDisappear:YES]; - [mainViewController viewDidAppear:YES]; - } - - [UIView commitAnimations]; -} - -- (void)didReceiveMemoryWarning -{ - RMLog(@"didReceiveMemoryWarning %@", self); - [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview - // Release anything that's not essential, such as cached data -} - -- (void)dealloc -{ - self.infoButton = nil; - self.flipsideNavigationBar = nil; - self.mainViewController = nil; - self.flipsideViewController = nil; - [super dealloc]; -} - -@end diff --git a/samples/MarkerMurder/FlipsideView.xib b/samples/MarkerMurder/FlipsideView.xib deleted file mode 100644 index 6390a1d03..000000000 --- a/samples/MarkerMurder/FlipsideView.xib +++ /dev/null @@ -1,591 +0,0 @@ - - - - 528 - 9G55 - 677 - 949.43 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 274 - - YES - - - 292 - {{20, 61}, {175, 21}} - - NO - YES - NO - Map center latitude - - 1 - MCAwIDAAA - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 170}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - 2 - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 95}, {175, 21}} - - NO - YES - NO - Map center longitude - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 136}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 141}, {175, 21}} - - NO - YES - NO - Zoom level - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 204}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 209}, {175, 21}} - - NO - YES - NO - Zoom Minimum - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 90}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 175}, {175, 21}} - - NO - YES - NO - Zoom Maximum - - - 1 - 1.000000e+01 - 2 - - - - 292 - {{203, 58}, {97, 31}} - - NO - NO - 0 - - 3 - - 3 - MAA - - - YES - 1.700000e+01 - - 2 - YES - - - - - 292 - {{20, 304}, {280, 37}} - - NO - NO - 0 - 0 - - Helvetica-Bold - 1.500000e+01 - 16 - - 1 - Clear shared NSURL cache - Clear shared NSURL cache - Clear shared NSURL cache - Clear shared NSURL cache - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - - 292 - {{20, 251}, {280, 37}} - - NO - NO - 0 - 0 - - 1 - Clear RouteMe image cache - Clear RouteMe image cache - Clear RouteMe image cache - Clear RouteMe image cache - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - {320, 460} - - - 1 - MC44Njk1NjUyNSAwLjg2OTU2NTI1IDAuODY5NTY1MjUAA - - NO - - 2 - - - - - - YES - - - view - - - - 41 - - - - centerLatitude - - - - 65 - - - - centerLongitude - - - - 66 - - - - zoomLevel - - - - 67 - - - - maxZoom - - - - 68 - - - - minZoom - - - - 69 - - - - clearMapContentsCachedImages - - - 7 - - 77 - - - - clearSharedNSURLCache - - - 7 - - 78 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - -2 - - - - - 40 - - - YES - - - - - - - - - - - - - - - - - 42 - - - - - 43 - - - - - 44 - - - - - 45 - - - - - 46 - - - - - 47 - - - - - 48 - - - - - 49 - - - - - 50 - - - - - 51 - - - - - 70 - - - - - 76 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 40.CustomClassName - 40.IBEditorWindowLastContentRect - 40.IBPluginDependency - 40.IBUserGuides - 42.IBPluginDependency - 43.IBPluginDependency - 44.IBPluginDependency - 45.IBPluginDependency - 46.IBPluginDependency - 47.IBPluginDependency - 48.IBPluginDependency - 49.IBPluginDependency - 50.IBPluginDependency - 51.IBPluginDependency - 70.IBPluginDependency - 76.IBPluginDependency - - - YES - FlipsideViewController - UIResponder - FlipsideView - {{637, 393}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - YES - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 78 - - - - YES - - FlipsideView - UIView - - IBProjectSource - Classes/FlipsideView.h - - - - FlipsideViewController - UIViewController - - YES - - YES - clearMapContentsCachedImages - clearSharedNSURLCache - - - YES - id - id - - - - YES - - YES - centerLatitude - centerLongitude - maxZoom - minZoom - zoomLevel - - - YES - UITextField - UITextField - UITextField - UITextField - UITextField - - - - IBProjectSource - Classes/FlipsideViewController.h - - - - - 0 - SampleMap.xcodeproj - 3 - - diff --git a/samples/MarkerMurder/Info.plist b/samples/MarkerMurder/Info.plist deleted file mode 100644 index fdf834060..000000000 --- a/samples/MarkerMurder/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/samples/MarkerMurder/MainView.xib b/samples/MarkerMurder/MainView.xib deleted file mode 100644 index 0097127ec..000000000 --- a/samples/MarkerMurder/MainView.xib +++ /dev/null @@ -1,386 +0,0 @@ - - - - 528 - 11E53 - 2809 - 1138.47 - 569.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 1884 - - - YES - IBProxyObject - IBUIImageView - IBUILabel - IBUITextView - IBUIView - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - YES - - - 319 - - YES - - - 282 - {{0, 367}, {320, 93}} - - - - 1 - MC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC4wNDM0NzgyNTEgMC42OTk5OTk5OQA - - NO - YES - YES - IBCocoaTouchFramework - NO - NO - NO - NO - NO - - IBCocoaTouchFramework - - - - 3 - MQA - - - 1 - 17 - - - Helvetica - 17 - 16 - - - - - 292 - {{227, 379}, {91, 21}} - - - _NS:328 - NO - YES - 7 - NO - IBCocoaTouchFramework - - 1 - 10 - Label - - 1 - - - 2 - - - - 265 - {{239, 369}, {65, 11}} - - NO - YES - 4 - YES - IBCocoaTouchFramework - - NSImage - mpp.png - - - - {320, 460} - - - - 3 - MQA - - 2 - - - NO - 1 - YES - IBCocoaTouchFramework - - - {320, 460} - - - 3 - MQA - - - NO - IBCocoaTouchFramework - - - - - YES - - - view - - - - 40 - - - - mapView - - - - 41 - - - - infoTextView - - - - 46 - - - - mppLabel - - - - 51 - - - - mppImage - - - - 52 - - - - - YES - - 0 - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 37 - - - YES - - - - - - 39 - - - YES - - - - - - - - 44 - - - - - 49 - - - - - 48 - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 37.IBPluginDependency - 39.CustomClassName - 39.IBPluginDependency - 44.IBPluginDependency - 48.IBPluginDependency - 49.IBPluginDependency - - - YES - MainViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RMMapView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 52 - - - - YES - - MainViewController - UIViewController - - YES - - YES - infoTextView - mapView - mppImage - mppLabel - - - YES - UITextView - RMMapView - UIImageView - UILabel - - - - YES - - YES - infoTextView - mapView - mppImage - mppLabel - - - YES - - infoTextView - UITextView - - - mapView - RMMapView - - - mppImage - UIImageView - - - mppLabel - UILabel - - - - - IBProjectSource - ./Classes/MainViewController.h - - - - RMMapView - UIView - - IBProjectSource - ./Classes/RMMapView.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - - mpp.png - {55, 11} - - 1884 - - diff --git a/samples/MarkerMurder/MainWindow.xib b/samples/MarkerMurder/MainWindow.xib deleted file mode 100644 index 8e2b3f9d1..000000000 --- a/samples/MarkerMurder/MainWindow.xib +++ /dev/null @@ -1,375 +0,0 @@ - - - - 528 - 11E53 - 2182 - 1138.47 - 569.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 1181 - - - YES - IBUIWindow - IBUICustomObject - IBUIViewController - IBUIButton - IBUIView - IBProxyObject - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - IBCocoaTouchFramework - - - - 1316 - - {320, 480} - - 1 - MCAwIDAAA - - NO - 4 - YES - - IBCocoaTouchFramework - - - - - 274 - - YES - - - 265 - {{274, 414}, {18, 19}} - - - NO - NO - IBCocoaTouchFramework - 0 - 0 - 3 - YES - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - 3 - MAA - - - Helvetica-Bold - Helvetica - 2 - 15 - - - Helvetica-Bold - 15 - 16 - - - - {{0, 20}, {320, 460}} - - - - - 3 - MQA - - 2 - - - NO - 4 - IBCocoaTouchFramework - - - - 1 - 1 - - IBCocoaTouchFramework - NO - - - - - YES - - - delegate - - - - 4 - - - - window - - - - 5 - - - - rootViewController - - - - 10 - - - - infoButton - - - - 20 - - - - toggleView - - - 7 - - 21 - - - - - YES - - 0 - - YES - - - - - - 2 - - - YES - - - - - -1 - - - File's Owner - - - 3 - - - - - 8 - - - YES - - - - - - -2 - - - - - 18 - - - YES - - - - - - 19 - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 18.IBPluginDependency - 19.IBPluginDependency - 2.IBAttributePlaceholdersKey - 2.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - 8.CustomClassName - 8.IBPluginDependency - - - YES - UIApplication - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - YES - - - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MarkerMurderAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - RootViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 21 - - - - YES - - MarkerMurderAppDelegate - NSObject - - YES - - YES - rootViewController - window - - - YES - RootViewController - UIWindow - - - - YES - - YES - rootViewController - window - - - YES - - rootViewController - RootViewController - - - window - UIWindow - - - - - IBProjectSource - ./Classes/MarkerMurderAppDelegate.h - - - - RootViewController - UIViewController - - toggleView - id - - - toggleView - - toggleView - id - - - - infoButton - UIButton - - - infoButton - - infoButton - UIButton - - - - IBProjectSource - ./Classes/RootViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - 1181 - - diff --git a/samples/MarkerMurder/MarkerMurder.xcodeproj/project.pbxproj b/samples/MarkerMurder/MarkerMurder.xcodeproj/project.pbxproj deleted file mode 100755 index 244e8183d..000000000 --- a/samples/MarkerMurder/MarkerMurder.xcodeproj/project.pbxproj +++ /dev/null @@ -1,448 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 16BFBA3714E912DF00F8D07E /* mpp.png in Resources */ = {isa = PBXBuildFile; fileRef = 16BFBA3614E912DF00F8D07E /* mpp.png */; }; - 16FCBD4515B41683005E3A5D /* HeadingAngleSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD3B15B41683005E3A5D /* HeadingAngleSmall.png */; }; - 16FCBD4615B41683005E3A5D /* HeadingAngleSmall@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD3C15B41683005E3A5D /* HeadingAngleSmall@2x.png */; }; - 16FCBD4715B41683005E3A5D /* TrackingDot.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD3D15B41683005E3A5D /* TrackingDot.png */; }; - 16FCBD4815B41683005E3A5D /* TrackingDot@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD3E15B41683005E3A5D /* TrackingDot@2x.png */; }; - 16FCBD4915B41683005E3A5D /* TrackingDotHalo.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD3F15B41683005E3A5D /* TrackingDotHalo.png */; }; - 16FCBD4A15B41683005E3A5D /* TrackingDotHalo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD4015B41683005E3A5D /* TrackingDotHalo@2x.png */; }; - 16FCBD4B15B41683005E3A5D /* TrackingHeading.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD4115B41683005E3A5D /* TrackingHeading.png */; }; - 16FCBD4C15B41683005E3A5D /* TrackingHeading@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD4215B41683005E3A5D /* TrackingHeading@2x.png */; }; - 16FCBD4D15B41683005E3A5D /* TrackingLocation.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD4315B41683005E3A5D /* TrackingLocation.png */; }; - 16FCBD4E15B41683005E3A5D /* TrackingLocation@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 16FCBD4415B41683005E3A5D /* TrackingLocation@2x.png */; }; - 1D3623260D0F684500981E51 /* MarkerMurderAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* MarkerMurderAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754A0DD40C5E005A515E /* FlipsideView.xib */; }; - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754B0DD40C5E005A515E /* MainView.xib */; }; - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754C0DD40C5E005A515E /* MainWindow.xib */; }; - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765580DF743DE002DB57D /* CoreGraphics.framework */; }; - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A30DB2D0840083E9F9 /* FlipsideView.m */; }; - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A50DB2D0840083E9F9 /* MainView.m */; }; - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233A90DB2D0DB0083E9F9 /* MainViewController.m */; }; - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */; }; - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */; }; - 2B12B8680F84ADA5003AE2BF /* marker-red.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B12B8670F84ADA5003AE2BF /* marker-red.png */; }; - 2B2BADDB0FA3B48A00EE37AA /* marker-X.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B2BADDA0FA3B48A00EE37AA /* marker-X.png */; }; - 2B580E4A0F8D236100D495B2 /* marker-blue.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B580E490F8D236100D495B2 /* marker-blue.png */; }; - 2B70CB7A0F856A46002BAF97 /* loading.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B70CB790F856A46002BAF97 /* loading.png */; }; - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */; }; - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E10F649CE100377FFE /* QuartzCore.framework */; }; - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */; }; - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE3697D0F673B95003DC21C /* libMapView.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; - EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 16BFBA3614E912DF00F8D07E /* mpp.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mpp.png; sourceTree = ""; }; - 16FCBD3B15B41683005E3A5D /* HeadingAngleSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HeadingAngleSmall.png; path = ../../MapView/Map/Resources/HeadingAngleSmall.png; sourceTree = ""; }; - 16FCBD3C15B41683005E3A5D /* HeadingAngleSmall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "HeadingAngleSmall@2x.png"; path = "../../MapView/Map/Resources/HeadingAngleSmall@2x.png"; sourceTree = ""; }; - 16FCBD3D15B41683005E3A5D /* TrackingDot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingDot.png; path = ../../MapView/Map/Resources/TrackingDot.png; sourceTree = ""; }; - 16FCBD3E15B41683005E3A5D /* TrackingDot@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingDot@2x.png"; path = "../../MapView/Map/Resources/TrackingDot@2x.png"; sourceTree = ""; }; - 16FCBD3F15B41683005E3A5D /* TrackingDotHalo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingDotHalo.png; path = ../../MapView/Map/Resources/TrackingDotHalo.png; sourceTree = ""; }; - 16FCBD4015B41683005E3A5D /* TrackingDotHalo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingDotHalo@2x.png"; path = "../../MapView/Map/Resources/TrackingDotHalo@2x.png"; sourceTree = ""; }; - 16FCBD4115B41683005E3A5D /* TrackingHeading.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingHeading.png; path = ../../MapView/Map/Resources/TrackingHeading.png; sourceTree = ""; }; - 16FCBD4215B41683005E3A5D /* TrackingHeading@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingHeading@2x.png"; path = "../../MapView/Map/Resources/TrackingHeading@2x.png"; sourceTree = ""; }; - 16FCBD4315B41683005E3A5D /* TrackingLocation.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TrackingLocation.png; path = ../../MapView/Map/Resources/TrackingLocation.png; sourceTree = ""; }; - 16FCBD4415B41683005E3A5D /* TrackingLocation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TrackingLocation@2x.png"; path = "../../MapView/Map/Resources/TrackingLocation@2x.png"; sourceTree = ""; }; - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* MarkerMurderAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkerMurderAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* MarkerMurderAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MarkerMurderAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* MarkerMurder.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MarkerMurder.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 280E754A0DD40C5E005A515E /* FlipsideView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FlipsideView.xib; sourceTree = ""; }; - 280E754B0DD40C5E005A515E /* MainView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainView.xib; sourceTree = ""; }; - 280E754C0DD40C5E005A515E /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 288765580DF743DE002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 289233A20DB2D0840083E9F9 /* FlipsideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideView.h; path = Classes/FlipsideView.h; sourceTree = ""; }; - 289233A30DB2D0840083E9F9 /* FlipsideView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideView.m; path = Classes/FlipsideView.m; sourceTree = ""; }; - 289233A40DB2D0840083E9F9 /* MainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainView.h; path = Classes/MainView.h; sourceTree = ""; }; - 289233A50DB2D0840083E9F9 /* MainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainView.m; path = Classes/MainView.m; sourceTree = ""; }; - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = ""; }; - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = ""; }; - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlipsideViewController.h; path = Classes/FlipsideViewController.h; sourceTree = ""; }; - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlipsideViewController.m; path = Classes/FlipsideViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2B12B8670F84ADA5003AE2BF /* marker-red.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "marker-red.png"; sourceTree = ""; }; - 2B2BADDA0FA3B48A00EE37AA /* marker-X.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "marker-X.png"; sourceTree = ""; }; - 2B580E490F8D236100D495B2 /* marker-blue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "marker-blue.png"; sourceTree = ""; }; - 2B70CB790F856A46002BAF97 /* loading.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = loading.png; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* MarkerMurder_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkerMurder_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765590DF743DE002DB57D /* CoreGraphics.framework in Frameworks */, - EBDDE0E00F649CE100377FFE /* CoreLocation.framework in Frameworks */, - EBDDE0E20F649CE100377FFE /* QuartzCore.framework in Frameworks */, - EBDDE0E40F649CE100377FFE /* libsqlite3.dylib in Frameworks */, - EBE3697E0F673B9A003DC21C /* libMapView.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Application Controllers */ = { - isa = PBXGroup; - children = ( - 289233AA0DB2D0DB0083E9F9 /* RootViewController.h */, - 289233AB0DB2D0DB0083E9F9 /* RootViewController.m */, - 1D3623240D0F684500981E51 /* MarkerMurderAppDelegate.h */, - 1D3623250D0F684500981E51 /* MarkerMurderAppDelegate.m */, - ); - name = "Application Controllers"; - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* MarkerMurder.app */, - ); - name = Products; - sourceTree = ""; - }; - 281C6CD70DB2D82200F60ACC /* Flipside View */ = { - isa = PBXGroup; - children = ( - 289233A20DB2D0840083E9F9 /* FlipsideView.h */, - 289233A30DB2D0840083E9F9 /* FlipsideView.m */, - 289233AC0DB2D0DB0083E9F9 /* FlipsideViewController.h */, - 289233AD0DB2D0DB0083E9F9 /* FlipsideViewController.m */, - ); - name = "Flipside View"; - sourceTree = ""; - }; - 289233A00DB2D0730083E9F9 /* Main View */ = { - isa = PBXGroup; - children = ( - 289233A40DB2D0840083E9F9 /* MainView.h */, - 289233A50DB2D0840083E9F9 /* MainView.m */, - 289233A80DB2D0DB0083E9F9 /* MainViewController.h */, - 289233A90DB2D0DB0083E9F9 /* MainViewController.m */, - ); - name = "Main View"; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - EBE3696D0F673B95003DC21C /* MapView.xcodeproj */, - 289233A00DB2D0730083E9F9 /* Main View */, - 281C6CD70DB2D82200F60ACC /* Flipside View */, - 080E96DDFE201D6D7F000001 /* Application Controllers */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* MarkerMurder_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 2B2BADDA0FA3B48A00EE37AA /* marker-X.png */, - 2B12B8670F84ADA5003AE2BF /* marker-red.png */, - 2B580E490F8D236100D495B2 /* marker-blue.png */, - 2B70CB790F856A46002BAF97 /* loading.png */, - 16BFBA3614E912DF00F8D07E /* mpp.png */, - 280E754A0DD40C5E005A515E /* FlipsideView.xib */, - 280E754B0DD40C5E005A515E /* MainView.xib */, - 280E754C0DD40C5E005A515E /* MainWindow.xib */, - 16FCBD3B15B41683005E3A5D /* HeadingAngleSmall.png */, - 16FCBD3C15B41683005E3A5D /* HeadingAngleSmall@2x.png */, - 16FCBD3D15B41683005E3A5D /* TrackingDot.png */, - 16FCBD3E15B41683005E3A5D /* TrackingDot@2x.png */, - 16FCBD3F15B41683005E3A5D /* TrackingDotHalo.png */, - 16FCBD4015B41683005E3A5D /* TrackingDotHalo@2x.png */, - 16FCBD4115B41683005E3A5D /* TrackingHeading.png */, - 16FCBD4215B41683005E3A5D /* TrackingHeading@2x.png */, - 16FCBD4315B41683005E3A5D /* TrackingLocation.png */, - 16FCBD4415B41683005E3A5D /* TrackingLocation@2x.png */, - 8D1107310486CEB800E47090 /* Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 288765580DF743DE002DB57D /* CoreGraphics.framework */, - EBDDE0DF0F649CE100377FFE /* CoreLocation.framework */, - EBDDE0E10F649CE100377FFE /* QuartzCore.framework */, - EBDDE0E30F649CE100377FFE /* libsqlite3.dylib */, - ); - name = Frameworks; - sourceTree = ""; - }; - EBE3696E0F673B95003DC21C /* Products */ = { - isa = PBXGroup; - children = ( - EBE3697D0F673B95003DC21C /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* Sample */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Sample" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BB42BEF0F678951009967BB /* PBXTargetDependency */, - ); - name = Sample; - productName = Sample2; - productReference = 1D6058910D05DD3D006BFB54 /* MarkerMurder.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MarkerMurder" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - en, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = EBE3696E0F673B95003DC21C /* Products */; - ProjectRef = EBE3696D0F673B95003DC21C /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* Sample */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - EBE3697D0F673B95003DC21C /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = EBE3697C0F673B95003DC21C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 280E754D0DD40C5E005A515E /* FlipsideView.xib in Resources */, - 280E754E0DD40C5E005A515E /* MainView.xib in Resources */, - 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */, - 2B12B8680F84ADA5003AE2BF /* marker-red.png in Resources */, - 2B70CB7A0F856A46002BAF97 /* loading.png in Resources */, - 2B580E4A0F8D236100D495B2 /* marker-blue.png in Resources */, - 2B2BADDB0FA3B48A00EE37AA /* marker-X.png in Resources */, - 16BFBA3714E912DF00F8D07E /* mpp.png in Resources */, - 16FCBD4515B41683005E3A5D /* HeadingAngleSmall.png in Resources */, - 16FCBD4615B41683005E3A5D /* HeadingAngleSmall@2x.png in Resources */, - 16FCBD4715B41683005E3A5D /* TrackingDot.png in Resources */, - 16FCBD4815B41683005E3A5D /* TrackingDot@2x.png in Resources */, - 16FCBD4915B41683005E3A5D /* TrackingDotHalo.png in Resources */, - 16FCBD4A15B41683005E3A5D /* TrackingDotHalo@2x.png in Resources */, - 16FCBD4B15B41683005E3A5D /* TrackingHeading.png in Resources */, - 16FCBD4C15B41683005E3A5D /* TrackingHeading@2x.png in Resources */, - 16FCBD4D15B41683005E3A5D /* TrackingLocation.png in Resources */, - 16FCBD4E15B41683005E3A5D /* TrackingLocation@2x.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* MarkerMurderAppDelegate.m in Sources */, - 289233A60DB2D0840083E9F9 /* FlipsideView.m in Sources */, - 289233A70DB2D0840083E9F9 /* MainView.m in Sources */, - 289233AE0DB2D0DB0083E9F9 /* MainViewController.m in Sources */, - 289233AF0DB2D0DB0083E9F9 /* RootViewController.m in Sources */, - 289233B00DB2D0DB0083E9F9 /* FlipsideViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BB42BEF0F678951009967BB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BB42BEE0F678951009967BB /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MarkerMurder_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = MarkerMurder; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = MarkerMurder_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ""; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = MarkerMurder; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEPLOYMENT_POSTPROCESSING = NO; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SEPARATE_STRIP = YES; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEPLOYMENT_POSTPROCESSING = NO; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - SDKROOT = iphoneos; - SEPARATE_STRIP = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Sample" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MarkerMurder" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/MarkerMurder/MarkerMurder_Prefix.pch b/samples/MarkerMurder/MarkerMurder_Prefix.pch deleted file mode 100644 index c832118e6..000000000 --- a/samples/MarkerMurder/MarkerMurder_Prefix.pch +++ /dev/null @@ -1,20 +0,0 @@ -// -// Prefix header for all source files of the 'SampleApp' target in the 'SampleApp' project -// - -#ifdef __OBJC__ - #import - #import - -#if DEBUG - -#define RMLog(args...) NSLog( @"%@", [NSString stringWithFormat: args]) -#define LogMethod() NSLog(@"%s logged method call: -[%@ %s] (line %d)", _cmd, self, _cmd, __LINE__) - -#else - -#define RMLog(args...) // do nothing. -#define LogMethod() -#endif - -#endif diff --git a/samples/MarkerMurder/loading.png b/samples/MarkerMurder/loading.png deleted file mode 100644 index 93cafb0f5..000000000 Binary files a/samples/MarkerMurder/loading.png and /dev/null differ diff --git a/samples/MarkerMurder/main.m b/samples/MarkerMurder/main.m deleted file mode 100644 index 20862db6e..000000000 --- a/samples/MarkerMurder/main.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// main.m -// SampleMap : Diagnostic map -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/MarkerMurder/marker-X.png b/samples/MarkerMurder/marker-X.png deleted file mode 100644 index e35f589bf..000000000 Binary files a/samples/MarkerMurder/marker-X.png and /dev/null differ diff --git a/samples/MarkerMurder/marker-blue.png b/samples/MarkerMurder/marker-blue.png deleted file mode 100644 index 8a3970fe5..000000000 Binary files a/samples/MarkerMurder/marker-blue.png and /dev/null differ diff --git a/samples/MarkerMurder/marker-red.png b/samples/MarkerMurder/marker-red.png deleted file mode 100644 index 8c7488ab8..000000000 Binary files a/samples/MarkerMurder/marker-red.png and /dev/null differ diff --git a/samples/MarkerMurder/mpp.png b/samples/MarkerMurder/mpp.png deleted file mode 100755 index d1c24819f..000000000 Binary files a/samples/MarkerMurder/mpp.png and /dev/null differ diff --git a/samples/ProgrammaticMap/Classes/ProgrammaticMapAppDelegate.h b/samples/ProgrammaticMap/Classes/ProgrammaticMapAppDelegate.h deleted file mode 100644 index a30775a7b..000000000 --- a/samples/ProgrammaticMap/Classes/ProgrammaticMapAppDelegate.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// ProgrammaticMapAppDelegate.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -@class ProgrammaticMapViewController; - -@interface ProgrammaticMapAppDelegate : NSObject - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet ProgrammaticMapViewController *viewController; - -@end - diff --git a/samples/ProgrammaticMap/Classes/ProgrammaticMapAppDelegate.m b/samples/ProgrammaticMap/Classes/ProgrammaticMapAppDelegate.m deleted file mode 100644 index c824925c2..000000000 --- a/samples/ProgrammaticMap/Classes/ProgrammaticMapAppDelegate.m +++ /dev/null @@ -1,31 +0,0 @@ -// -// ProgrammaticMapAppDelegate.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "ProgrammaticMapAppDelegate.h" -#import "ProgrammaticMapViewController.h" - -@implementation ProgrammaticMapAppDelegate - -@synthesize window; -@synthesize viewController; - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - // Override point for customization after app launch - [window addSubview:viewController.view]; - [window makeKeyAndVisible]; -} - -- (void)dealloc -{ - [viewController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/samples/ProgrammaticMap/Classes/ProgrammaticMapViewController.h b/samples/ProgrammaticMap/Classes/ProgrammaticMapViewController.h deleted file mode 100644 index 530bb05fd..000000000 --- a/samples/ProgrammaticMap/Classes/ProgrammaticMapViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// ProgrammaticMapViewController.h -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import -#import "RMMapView.h" - -@interface ProgrammaticMapViewController : UIViewController - -@property (nonatomic, retain) RMMapView *mapView; - -- (IBAction)doTheTest:(id)sender; -- (IBAction)takeSnapshot:(id)sender; - -@end - diff --git a/samples/ProgrammaticMap/Classes/ProgrammaticMapViewController.m b/samples/ProgrammaticMap/Classes/ProgrammaticMapViewController.m deleted file mode 100644 index fe8a41a9e..000000000 --- a/samples/ProgrammaticMap/Classes/ProgrammaticMapViewController.m +++ /dev/null @@ -1,53 +0,0 @@ -// -// ProgrammaticMapViewController.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import "ProgrammaticMapViewController.h" -#import "RMMapView.h" - -@implementation ProgrammaticMapViewController - -@synthesize mapView; - -- (void)viewDidLoad -{ - NSLog(@"viewDidLoad"); - [super viewDidLoad]; - - CLLocationCoordinate2D firstLocation; - firstLocation.latitude = 51.2795; - firstLocation.longitude = 1.082; - - self.mapView = [[[RMMapView alloc] initWithFrame:CGRectMake(10, 20, 300, 340)] autorelease]; - self.mapView.adjustTilesForRetinaDisplay = NO; - [self.mapView setBackgroundColor:[UIColor greenColor]]; - [[self view] addSubview:mapView]; - [[self view] sendSubviewToBack:mapView]; -} - -- (void)dealloc -{ - [mapView removeFromSuperview]; - self.mapView = nil; - [super dealloc]; -} - -- (IBAction)doTheTest:(id)sender -{ - CLLocationCoordinate2D secondLocation; - secondLocation.latitude = -43.50; - secondLocation.longitude = 172.56; - [self.mapView setCenterCoordinate:secondLocation]; -} - -- (IBAction)takeSnapshot:(id)sender -{ - UIImage *snapshot = [self.mapView takeSnapshot]; - [UIImagePNGRepresentation(snapshot) writeToFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"snap.png"] atomically:YES]; -} - -@end diff --git a/samples/ProgrammaticMap/Info.plist b/samples/ProgrammaticMap/Info.plist deleted file mode 100644 index 62bd89184..000000000 --- a/samples/ProgrammaticMap/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.mobilegeographics.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSMainNibFile - MainWindow - - diff --git a/samples/ProgrammaticMap/MainWindow.xib b/samples/ProgrammaticMap/MainWindow.xib deleted file mode 100644 index b411a1d09..000000000 --- a/samples/ProgrammaticMap/MainWindow.xib +++ /dev/null @@ -1,206 +0,0 @@ - - - - 528 - 9E17 - 672 - 949.33 - 352.00 - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - ProgrammaticMapViewController - - - - - 292 - {320, 480} - - 1 - MSAxIDEAA - - NO - NO - - - - - - YES - - - delegate - - - - 4 - - - - viewController - - - - 11 - - - - window - - - - 14 - - - - - YES - - 0 - - YES - - - - - - -1 - - - RmlsZSdzIE93bmVyA - - - 3 - - - ProgrammaticMap App Delegate - - - -2 - - - - - 10 - - - - - 12 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 10.CustomClassName - 10.IBEditorWindowLastContentRect - 10.IBPluginDependency - 12.IBEditorWindowLastContentRect - 12.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - - - YES - UIApplication - UIResponder - ProgrammaticMapViewController - {{512, 351}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{525, 346}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - ProgrammaticMapAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 14 - - - - YES - - ProgrammaticMapAppDelegate - NSObject - - YES - - YES - viewController - window - - - YES - ProgrammaticMapViewController - UIWindow - - - - IBProjectSource - Classes/ProgrammaticMapAppDelegate.h - - - - ProgrammaticMapAppDelegate - NSObject - - IBUserSource - - - - - ProgrammaticMapViewController - UIViewController - - IBProjectSource - Classes/ProgrammaticMapViewController.h - - - - - 0 - ProgrammaticMap.xcodeproj - 3 - - diff --git a/samples/ProgrammaticMap/ProgrammaticMap.xcodeproj/project.pbxproj b/samples/ProgrammaticMap/ProgrammaticMap.xcodeproj/project.pbxproj deleted file mode 100755 index 3d10fe5cb..000000000 --- a/samples/ProgrammaticMap/ProgrammaticMap.xcodeproj/project.pbxproj +++ /dev/null @@ -1,332 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 16F357341585DB08003A3AD9 /* mpp.png in Resources */ = {isa = PBXBuildFile; fileRef = 16F357331585DB08003A3AD9 /* mpp.png */; }; - 1D3623260D0F684500981E51 /* ProgrammaticMapAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; - 2899E5220DE3E06400AC0155 /* ProgrammaticMapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */; }; - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; - 28D7ACF80DDB3853001CB0EB /* ProgrammaticMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */; }; - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */; }; - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */; }; - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */; }; - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B8C974590E8A19B2007D16AD; - remoteInfo = MapView; - }; - 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = B8C974130E8A19B2007D16AD; - remoteInfo = MapView; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 16F357331585DB08003A3AD9 /* mpp.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = mpp.png; path = ../MarkerMurder/mpp.png; sourceTree = ""; }; - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* ProgrammaticMapAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticMapAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticMapAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* ProgrammaticMap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProgrammaticMap.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ProgrammaticMapViewController.xib; sourceTree = ""; }; - 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 28D7ACF60DDB3853001CB0EB /* ProgrammaticMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticMapViewController.h; sourceTree = ""; }; - 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticMapViewController.m; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MapView.xcodeproj; path = ../../MapView/MapView.xcodeproj; sourceTree = ""; }; - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 32CA4F630368D1EE00C91783 /* ProgrammaticMap_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticMap_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, - 2BE5B4F60F7AF4BF00EF8CC6 /* libMapView.a in Frameworks */, - 2BE5B5040F7AF56F00EF8CC6 /* QuartzCore.framework in Frameworks */, - 2BE5B5080F7AF58000EF8CC6 /* libsqlite3.dylib in Frameworks */, - 2BE5B50A0F7AF58900EF8CC6 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - 1D3623240D0F684500981E51 /* ProgrammaticMapAppDelegate.h */, - 1D3623250D0F684500981E51 /* ProgrammaticMapAppDelegate.m */, - 28D7ACF60DDB3853001CB0EB /* ProgrammaticMapViewController.h */, - 28D7ACF70DDB3853001CB0EB /* ProgrammaticMapViewController.m */, - ); - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* ProgrammaticMap.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */, - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* ProgrammaticMap_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 2899E5210DE3E06400AC0155 /* ProgrammaticMapViewController.xib */, - 28AD733E0D9D9553002E5188 /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - 16F357331585DB08003A3AD9 /* mpp.png */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2BE5B5030F7AF56F00EF8CC6 /* QuartzCore.framework */, - 2BE5B5070F7AF58000EF8CC6 /* libsqlite3.dylib */, - 2BE5B5090F7AF58900EF8CC6 /* CoreFoundation.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765A40DF7441C002DB57D /* CoreGraphics.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */ = { - isa = PBXGroup; - children = ( - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* ProgrammaticMap */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ProgrammaticMap" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */, - ); - name = ProgrammaticMap; - productName = ProgrammaticMap; - productReference = 1D6058910D05DD3D006BFB54 /* ProgrammaticMap.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProgrammaticMap" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 2BE5B4EF0F7AF4AE00EF8CC6 /* Products */; - ProjectRef = 2BE5B4E50F7AF4AE00EF8CC6 /* MapView.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* ProgrammaticMap */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 2BE5B4F50F7AF4AE00EF8CC6 /* libMapView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libMapView.a; - remoteRef = 2BE5B4F40F7AF4AE00EF8CC6 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, - 2899E5220DE3E06400AC0155 /* ProgrammaticMapViewController.xib in Resources */, - 16F357341585DB08003A3AD9 /* mpp.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* ProgrammaticMapAppDelegate.m in Sources */, - 28D7ACF80DDB3853001CB0EB /* ProgrammaticMapViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 2BE5B4FD0F7AF4D200EF8CC6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MapView; - targetProxy = 2BE5B4FC0F7AF4D200EF8CC6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ProgrammaticMap_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - PRODUCT_NAME = ProgrammaticMap; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ProgrammaticMap_Prefix.pch; - HEADER_SEARCH_PATHS = "../../MapView/**"; - INFOPLIST_FILE = Info.plist; - PRODUCT_NAME = ProgrammaticMap; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - SDKROOT = iphoneos; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ProgrammaticMap" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProgrammaticMap" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/samples/ProgrammaticMap/ProgrammaticMapViewController.xib b/samples/ProgrammaticMap/ProgrammaticMapViewController.xib deleted file mode 100644 index 4d0318916..000000000 --- a/samples/ProgrammaticMap/ProgrammaticMapViewController.xib +++ /dev/null @@ -1,305 +0,0 @@ - - - - 528 - 11E53 - 2182 - 1138.47 - 569.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 1181 - - - YES - IBProxyObject - IBUIView - IBUIButton - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - YES - - - 292 - {{40, 403}, {100, 37}} - - - - NO - NO - IBCocoaTouchFramework - 0 - 0 - 1 - Move - Move - Move - Move - - 1 - MSAxIDEAA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - 3 - MAA - - - Helvetica-Bold - Helvetica - 2 - 15 - - - Helvetica-Bold - 15 - 16 - - - - - 292 - {{180, 403}, {100, 37}} - - - - NO - IBCocoaTouchFramework - 0 - 0 - 1 - Snapshot - - 3 - MQA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - 3 - MC41AA - - - 2 - 15 - - - - - {{0, 20}, {320, 460}} - - - - - 3 - MC43NQA - - 2 - - - NO - - IBCocoaTouchFramework - - - - - YES - - - view - - - - 7 - - - - doTheTest: - - - 7 - - 9 - - - - takeSnapshot: - - - 7 - - 11 - - - - - YES - - 0 - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 6 - - - YES - - - - - - - 8 - - - - - 10 - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 10.IBPluginDependency - 6.IBPluginDependency - 8.IBPluginDependency - - - YES - ProgrammaticMapViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 12 - - - - YES - - ProgrammaticMapViewController - UIViewController - - YES - - YES - doTheTest: - takeSnapshot: - - - YES - id - id - - - - YES - - YES - doTheTest: - takeSnapshot: - - - YES - - doTheTest: - id - - - takeSnapshot: - id - - - - - IBProjectSource - ./Classes/ProgrammaticMapViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - 1181 - - diff --git a/samples/ProgrammaticMap/ProgrammaticMap_Prefix.pch b/samples/ProgrammaticMap/ProgrammaticMap_Prefix.pch deleted file mode 100644 index 092c26b68..000000000 --- a/samples/ProgrammaticMap/ProgrammaticMap_Prefix.pch +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'ProgrammaticMap' target in the 'ProgrammaticMap' project -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/samples/ProgrammaticMap/main.m b/samples/ProgrammaticMap/main.m deleted file mode 100644 index a02a4c0df..000000000 --- a/samples/ProgrammaticMap/main.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// main.m -// ProgrammaticMap -// -// Created by Hal Mueller on 3/25/09. -// Copyright Route-Me Contributors 2009. All rights reserved. -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} diff --git a/samples/ReadmeSamples.txt b/samples/ReadmeSamples.txt deleted file mode 100644 index 8defd30ae..000000000 --- a/samples/ReadmeSamples.txt +++ /dev/null @@ -1,21 +0,0 @@ -This "samples" directory contains both sample code and engineering -test cases. - -MarkerMurder is a straightforward example of the Route-me library in -action, using the Open Street Map project's map tiles, and retrieving -data from their server. Developers: please don't check in any code -that breaks this project. - -MapTestbed is similar, but is meant as a starting point -for writing test cases. Developers are encouraged to clone the -MapTestbed project when testing new features or when trying to -duplicate bugs. If you make changes to MapTestbed to exercise a new -Route-me features, please check in your revised version under a new -name. - -ProgrammaticMap demonstrates creating a map without using a Nib. - -MapTestbedTwoMaps shows two different map sources in the same app. - -MapTestbedFlipMaps shows two different kinds of marker tap/drag -response behavior, using two different RMMarker delegate classes.