The iOS SDK for CartoType allows you to use Swift or Objective C to create applications using CartoType.

A Swift-based sample CartoType project

The iOS sample project includes source code, project files, and data files including a map, style sheet and fonts. This Xcode project allows you to build a full-featured app with fast hardware-accelerated rendering, handling of user gestures for panning, zooming and rotation, routing using different profiles, turn by turn navigation, finding placenames and addresses, night mode, and perspective mode. You can set the start or end of a route using a long press. Other features are available from toolbar buttons.

To build and run the app, open the project in Xcode on a Macintosh and add the CartoType iOS SDK to it. If you are a licensee you can use your licensed CartoType SDK instead of the evaluation version; change the call to the license() function in AppDelegate.swift so that it supplies your license key. You will need to sign the app using your Apple developer certificate.

You can then run it in the simulator or on an iOS device.

Using CartoType with tile-based SDKs

You can use various tile-based SDKs with CartoType. They provide the application front-end, including the user interaction, and you create a tile provider to draw tiles as required. These SDKs always work with the Web Mercator projection, so you'll need to create maps using /project=m with our makemap tool.

Threading issues

In general, tile-based SDKs such as Map Kit, Mapbox and the Google Maps SDK create extra threads to handle tile requests. CartoType is not thread-safe, so you need to do two things to avoid crashes:

1. Put the call to CartoType to get the tile bitmap inside a @synchronized block, synchronizing on the CartoTypeFramework object ('cartotype_framework' in this example):

@synchronized(cartotype_framework) { image_ref = [cartotype_framework getTileBitmapWithSize:256 andZoom:zoom andX:x andY:y]; }

2. Put all calls to CartoType functions which could possibly be executed during tile creation inside a @synchronized block, synchronizing on the same framework object. For example, when creating a route:

@synchronized(cartotype_framework)
   {
   result = [cartotype_framework startNavigationFrom:start_point startCoordType:DegreeCoordType to:end_point endCoordType:DegreeCoordType];
   }

Note that this procedure is not necessary when using CartoType's own tile source system.

Use the Google Maps SDK with CartoType

Here's how to use the Google Maps SDK and draw tiles using CartoType as a custom tile layer. It works extremely well, giving a fast, fluid user experience; it also supports rotation. It's your responsibility to verify that the Google Maps SDK license is compatible with your intended use, whether commercial or non-commercial.

You create an implementation of GMSSyncTileLayer (https://developers.google.com/maps/documentation/ios/reference/interface_g_m_s_sync_tile_layer), like this ('carto' is a pointer to a CartoTypeFramework object, as defined in the CartoType iOS API):

#import "MyCustomTileLayer.h"
@implementation MyCustomTileLayer
- (id)init
{
 NSLog(@"INIT");
 carto = [[CartoTypeFramework alloc] initWithMap:@"santa-cruz-mercator" andStyle:@"osm-style" andFont:@"DejaVuSans" andWidth:400 andHeight:400];
 return self;
}
- (UIImage *)tileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom {
 NSLog(@"%s x: %d y: %d, z: %d", __FUNCTION__, x, y, zoom);
UIImage *img;
@synchronized(carto)
 {
 CGImageRef imgRef = [carto getTileBitmapWithSize:256 andZoom:zoom andX:x andY:y];
 img = [UIImage imageWithCGImage:imgRef];
 NSLog(@"%@";, img);
 }
 return img;
}
@end

and in your view controller, you can do this:

- (void)viewDidLoad
{
 [super viewDidLoad];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:36.974117
 longitude:-122.030796
 zoom:16];
 mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
 mapView.delegate = self;
 mapView.mapType = kGMSTypeNone;
 mapView.myLocationEnabled = YES;
 self.view = mapView;
 
 MyCustomTileLayer *customTileLayer = [MyCustomTileLayer new];
 customTileLayer.map = mapView;
 
}

Using the Mapbox SDK with CartoType

Here's how to use the Mapbox SDK on iOS, using CartoType as a custom tile layer. It's your responsibility to verify that the Mapbox SDK license is compatible with your intended use, whether commercial or non-commercial.

view-controller implementation

#import "CartoTypeViewController.h"
#import "MapBox.h"
#import "CartoTypeTileSource.h"
@implementation CartoTypeViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
 if (self) {
 // Custom initialization
 }
 return self;
}
- (void)viewDidLoad
{
 [super viewDidLoad];
 // Do any additional setup after loading the view. 'sample-map.ctm1' is the CartoType map file; osm-style.xml is the style sheet; DejaVuSans.ttf is the font
 CartoTypeTileSource *s =[[CartoTypeTileSource alloc]initWithMap:@"sample-map" style:@"osm-style" font:@"DejaVuSans"];
 
 RMMapView *mapView = [[RMMapView alloc]initWithFrame:self.view.bounds andTilesource:s];
 mapView.autoresizesSubviews = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
 mapView.debugTiles = YES;
 [self.view addSubview:mapView];
 
 float minlon = -2;
 float minlat = 49;
 float maxlon = 2;
 float maxlat = 51;
 
 [mapView zoomWithLatitudeLongitudeBoundsSouthWest:CLLocationCoordinate2DMake(minlat, maxlon) northEast:CLLocationCoordinate2DMake(maxlat, minlon) animated:NO];
 
}
- (void)didReceiveMemoryWarning
{
 [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated {
 
}

CartoType tile source interface

#import "MapBox.h"
#import <CartoType/CartoType.h>
@interface CartoTypeTileSource : RMAbstractMercatorTileSource
@property (nonatomic,strong)CartoTypeFramework *framework;
-(id)initWithMap:(NSString*)fileName style:(NSString*)styleSheetFileName font:(NSString*)fontFileName;
@end

CartoType tile source implementation


#import "CartoTypeTileSource.h"
@implementation CartoTypeTileSource
- (id)init {
 self = [self initWithMap:nil style:nil font:nil];
 return self;
}
-(id)initWithMap:(NSString*)fileName style:(NSString*)styleSheetFileName font:(NSString*)fontFileName {
 self = [super init];
 if(self) {
 int size = 256;
 self.framework = [[CartoTypeFramework alloc]initWithMap:fileName andStyle:styleSheetFileName andFont:fontFileName andWidth:size andHeight:size];
 self.cacheable = NO;
 }
 return self;
}
- (UIImage *)imageForTile:(RMTile)tile inCache:(RMTileCache *)tileCache {
 CGImageRef tileCGImage = NULL;
 @synchronized(self.framework) {
 tileCGImage = [self.framework getTileBitmapWithSize:256 andZoom:tile.zoom andX:tile.x andY:tile.y];
 CGImageRetain(tileCGImage);
 UIImage *tileImage = [UIImage imageWithCGImage:tileCGImage];
 CGImageRelease(tileCGImage);
 }
 return tileImage;
}
- (NSString *)uniqueTilecacheKey {
 return @"CartoTypeTileSource";
}
- (NSString *)shortName {
 return @"CartoType tile source";
}

- (NSString *)shortAttribution {
 return @"CartoType";
}
@end

Find out more

If you'd like to find out more about using CartoType on iOS, please use the form or e-mail address on the contact page.