summaryrefslogtreecommitdiff
path: root/platform/ios/demo/Examples/ObjectiveC
diff options
context:
space:
mode:
authorjmkiley <jordan.kiley@mapbox.com>2017-06-13 15:21:50 -0700
committerjmkiley <jordan.kiley@mapbox.com>2017-06-13 15:21:50 -0700
commit04a0c64482c045bd622a8d1c4ad6ca1baace2c34 (patch)
tree9c978aa3e4850f71fa26fb033f2cb3c81c58b555 /platform/ios/demo/Examples/ObjectiveC
parent17ccd0100ceff3ab7d4dd6eb58e3345745dff117 (diff)
downloadqtlocation-mapboxgl-04a0c64482c045bd622a8d1c4ad6ca1baace2c34.tar.gz
[ios] added demo projectupstream/jk-nb-pod-try
Diffstat (limited to 'platform/ios/demo/Examples/ObjectiveC')
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.m109
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.m119
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.m64
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.m84
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.m40
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.h14
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.m39
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/ClusteringExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/ClusteringExample.m143
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.m122
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModels.h29
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.h14
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.m158
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.m63
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.m20
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.m27
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.m66
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.m97
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.m27
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.m143
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.m67
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.m80
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.m48
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.m77
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.m56
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.m113
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/PointConversionExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/PointConversionExample.m64
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.m94
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.m181
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.m77
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.m216
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.m92
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.m28
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.m71
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.m68
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.m23
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.m58
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.m24
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.h13
-rw-r--r--platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.m25
71 files changed, 3269 insertions, 0 deletions
diff --git a/platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.h b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.h
new file mode 100644
index 0000000000..104b203926
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.h
@@ -0,0 +1,13 @@
+//
+// AnnotationViewExample.h
+// Examples
+//
+// Created by Jason Wray on 6/23/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AnnotationViewExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.m b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.m
new file mode 100644
index 0000000000..18d309ed7b
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewExample.m
@@ -0,0 +1,109 @@
+#import "AnnotationViewExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleAnnotationView = @"AnnotationViewExample";
+
+// MGLAnnotationView subclass
+@interface CustomAnnotationView : MGLAnnotationView
+@end
+
+@implementation CustomAnnotationView
+
+- (void)layoutSubviews {
+ [super layoutSubviews];
+
+ // Force the annotation view to maintain a constant size when the map is tilted.
+ self.scalesWithViewingDistance = false;
+
+ // Use CALayer’s corner radius to turn this view into a circle.
+ self.layer.cornerRadius = self.frame.size.width / 2;
+ self.layer.borderWidth = 2;
+ self.layer.borderColor = [UIColor whiteColor].CGColor;
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+ [super setSelected:selected animated:animated];
+
+ // Animate the border width in/out, creating an iris effect.
+ CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"borderWidth"];
+ animation.duration = 0.1;
+ self.layer.borderWidth = selected ? self.frame.size.width / 4 : 2;
+ [self.layer addAnimation:animation forKey:@"borderWidth"];
+}
+
+@end
+
+
+//
+// Example view controller
+@interface AnnotationViewExample () <MGLMapViewDelegate>
+@end
+
+@implementation AnnotationViewExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.styleURL = [MGLStyle darkStyleURLWithVersion:9];
+ mapView.tintColor = [UIColor lightGrayColor];
+ mapView.centerCoordinate = CLLocationCoordinate2DMake(0, 66);
+ mapView.zoomLevel = 2;
+ mapView.delegate = self;
+ [self.view addSubview:mapView];
+
+ // Specify coordinates for our annotations.
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(0, 33),
+ CLLocationCoordinate2DMake(0, 66),
+ CLLocationCoordinate2DMake(0, 99),
+ };
+ NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
+
+ // Fill an array with point annotations and add it to the map.
+ NSMutableArray *pointAnnotations = [NSMutableArray arrayWithCapacity:numberOfCoordinates];
+ for (NSUInteger i = 0; i < numberOfCoordinates; i++) {
+ CLLocationCoordinate2D coordinate = coordinates[i];
+ MGLPointAnnotation *point = [[MGLPointAnnotation alloc] init];
+ point.coordinate = coordinate;
+ point.title = [NSString stringWithFormat:@"%.f, %.f", coordinate.latitude, coordinate.longitude];
+ [pointAnnotations addObject:point];
+ }
+
+ [mapView addAnnotations:pointAnnotations];
+}
+
+#pragma mark - MGLMapViewDelegate methods
+
+// This delegate method is where you tell the map to load a view for a specific annotation. To load a static MGLAnnotationImage, you would use `-mapView:imageForAnnotation:`.
+- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id <MGLAnnotation>)annotation {
+ // This example is only concerned with point annotations.
+ if (![annotation isKindOfClass:[MGLPointAnnotation class]]) {
+ return nil;
+ }
+
+ // Use the point annotation’s longitude value (as a string) as the reuse identifier for its view.
+ NSString *reuseIdentifier = [NSString stringWithFormat:@"%f", annotation.coordinate.longitude];
+
+ // For better performance, always try to reuse existing annotations.
+ CustomAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseIdentifier];
+
+ // If there’s no reusable annotation view available, initialize a new one.
+ if (!annotationView) {
+ annotationView = [[CustomAnnotationView alloc] initWithReuseIdentifier:reuseIdentifier];
+ annotationView.frame = CGRectMake(0, 0, 40, 40);
+
+ // Set the annotation view’s background color to a value determined by its longitude.
+ CGFloat hue = (CGFloat)annotation.coordinate.longitude / 100;
+ annotationView.backgroundColor = [UIColor colorWithHue:hue saturation:0.5 brightness:1 alpha:1];
+ }
+
+ return annotationView;
+}
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id<MGLAnnotation>)annotation {
+ return YES;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.h b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.h
new file mode 100644
index 0000000000..2e2d32ab18
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.h
@@ -0,0 +1,13 @@
+//
+// AnnotationViewMultipleExample.h
+// Examples
+//
+// Created by Nadia Barbosa on 12/13/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AnnotationViewMultipleExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.m b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.m
new file mode 100644
index 0000000000..ee6622fd4e
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/AnnotationViewMultipleExample.m
@@ -0,0 +1,119 @@
+#import "AnnotationViewMultipleExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleAnnotationViewMultiple = @"AnnotationViewMultipleExample";
+
+// MGLPointAnnotation subclass
+@interface MyCustomPointAnnotation : MGLPointAnnotation
+@property (nonatomic, assign) BOOL willUseImage;
+@end
+
+@implementation MyCustomPointAnnotation
+@end
+// end MGLPointAnnotation subclass
+
+@interface AnnotationViewMultipleExample () <MGLMapViewDelegate>
+@end
+
+@implementation AnnotationViewMultipleExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Create a new map view using the Mapbox Light style.
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds
+ styleURL:[MGLStyle lightStyleURLWithVersion:9]];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map's center coordinate and zoom level.
+ mapView.centerCoordinate = CLLocationCoordinate2DMake(36.54,-116.97);
+ mapView.zoomLevel = 9;
+ mapView.delegate = self;
+ [self.view addSubview:mapView];
+
+ // Create four new point annotations with specified coordinates and titles.
+ MyCustomPointAnnotation *pointA = [[MyCustomPointAnnotation alloc] init];
+ pointA.title = @"Stovepipe Wells";
+ pointA.coordinate = CLLocationCoordinate2DMake(36.4623,-116.8656);
+ pointA.willUseImage = YES;
+
+ MyCustomPointAnnotation *pointB = [[MyCustomPointAnnotation alloc] init];
+ pointB.title = @"Furnace Creek";
+ pointB.coordinate = CLLocationCoordinate2DMake(36.6071,-117.1458);
+ pointB.willUseImage = YES;
+
+ MyCustomPointAnnotation *pointC = [[MyCustomPointAnnotation alloc] init];
+ pointC.title = @"Zabriskie Point";
+ pointC.coordinate = CLLocationCoordinate2DMake(36.4208,-116.8101);
+
+ MyCustomPointAnnotation *pointD = [[MyCustomPointAnnotation alloc] init];
+ pointD.title = @"Mesquite Flat Sand Dunes";
+ pointD.coordinate = CLLocationCoordinate2DMake(36.6836,-117.1005);
+
+ // Fill an array with four point annotations.
+ NSArray *myPlaces = @[pointA, pointB, pointC, pointD];
+
+ // Add all annotations to the map all at once, instead of individually.
+ [mapView addAnnotations:myPlaces];
+}
+
+// This delegate method is where you tell the map to load a view for a specific annotation based on the willUseImage property of the custom subclass.
+- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id <MGLAnnotation>)annotation {
+ if ([annotation isKindOfClass:[MyCustomPointAnnotation class]]) {
+ MyCustomPointAnnotation *castAnnotation = (MyCustomPointAnnotation *)annotation;
+
+ if (castAnnotation.willUseImage) {
+ return nil;
+ }
+ }
+
+ // Assign a reuse identifier to be used by both of the annotation views, taking advantage of their similarities.
+ NSString *reuseIdentifier = @"reusableDotView";
+
+ // For better performance, always try to reuse existing annotations.
+ MGLAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseIdentifier];
+
+ // If there’s no reusable annotation view available, initialize a new one.
+ if (!annotationView) {
+ annotationView = [[MGLAnnotationView alloc] initWithReuseIdentifier:reuseIdentifier];
+ annotationView.frame = CGRectMake(0, 0, 30, 30);
+ annotationView.layer.cornerRadius = annotationView.frame.size.width / 2;
+ annotationView.layer.borderColor = [UIColor whiteColor].CGColor;
+ annotationView.layer.borderWidth = 4.0;
+ annotationView.backgroundColor = [UIColor colorWithRed:0.03 green:0.80 blue:0.69 alpha:1.0];
+ }
+
+ return annotationView;
+}
+
+// This delegate method is where you tell the map to load an image for a specific annotation based on the willUseImage property of the custom subclass.
+- (MGLAnnotationImage *)mapView:(MGLMapView *)mapView imageForAnnotation:(id <MGLAnnotation>)annotation {
+
+ if ([annotation isKindOfClass:[MyCustomPointAnnotation class]]) {
+ MyCustomPointAnnotation *castAnnotation = (MyCustomPointAnnotation *)annotation;
+
+ if (!castAnnotation.willUseImage) {
+ return nil;
+ }
+ }
+
+ // For better performance, always try to reuse existing annotations.
+ MGLAnnotationImage *annotationImage = [mapView dequeueReusableAnnotationImageWithIdentifier:@"camera"];
+
+ // If there is no reusable annotation image available, initialize a new one.
+ if (!annotationImage) {
+ UIImage *image = [UIImage imageNamed:@"camera"];
+ image = [image imageWithAlignmentRectInsets:UIEdgeInsetsMake(0, 0, image.size.height/2, 0)];
+ annotationImage = [MGLAnnotationImage annotationImageWithImage:image reuseIdentifier:@"camera"];
+ }
+
+ return annotationImage;
+}
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id<MGLAnnotation>)annotation {
+ // Always allow callouts to popup when annotations are tapped.
+ return YES;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.h b/platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.h
new file mode 100644
index 0000000000..27f4ff4d72
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.h
@@ -0,0 +1,13 @@
+//
+// BlockingGesturesDelegateExample.h
+// Examples
+//
+// Created by Fabian Guerra Soto on 2/14/17.
+// Copyright © 2017 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface BlockingGesturesDelegateExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.m b/platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.m
new file mode 100644
index 0000000000..2ac90fdc67
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/BlockingGesturesDelegateExample.m
@@ -0,0 +1,64 @@
+#import "BlockingGesturesDelegateExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleBlockingGesturesDelegate = @"BlockingGesturesDelegateExample";
+
+@interface BlockingGesturesDelegateExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLCoordinateBounds colorado;
+@end
+
+@implementation BlockingGesturesDelegateExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.delegate = self;
+ mapView.styleURL = [MGLStyle outdoorsStyleURLWithVersion:9];
+
+ // Denver, Colorado
+ CLLocationCoordinate2D center = CLLocationCoordinate2DMake(39.748947, -104.995882);
+
+ // Starting point
+ [mapView setCenterCoordinate:center zoomLevel:10 direction:0 animated:NO];
+
+ // Colorado's bounds
+ CLLocationCoordinate2D ne = CLLocationCoordinate2DMake(40.989329, -102.062592);
+ CLLocationCoordinate2D sw = CLLocationCoordinate2DMake(36.986207, -109.049896);
+ self.colorado = MGLCoordinateBoundsMake(sw, ne);
+
+ [self.view addSubview:mapView];
+}
+
+// This example uses Colorado's boundaries to restrict
+// the camera movement.
+
+- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera
+{
+ // Get the current camera to restore it after
+ MGLMapCamera *currentCamera = mapView.camera;
+
+ // From the new camera obtain the center to test
+ // if it's inside the boundaries
+ CLLocationCoordinate2D newCameraCenter = newCamera.centerCoordinate;
+
+
+ // Set mapView to newCamera to project the
+ // new boundaries
+ mapView.camera = newCamera;
+ MGLCoordinateBounds newVisibleCoordinates = mapView.visibleCoordinateBounds;
+
+ // Revert the camera
+ mapView.camera = currentCamera;
+
+ // Test if the newCameraCenter and newVisibleCoordinates
+ // are inside self.colorado
+ BOOL inside = MGLCoordinateInCoordinateBounds(newCameraCenter, self.colorado);
+ BOOL intersects = MGLCoordinateInCoordinateBounds(newVisibleCoordinates.ne, self.colorado) && MGLCoordinateInCoordinateBounds(newVisibleCoordinates.sw, self.colorado);
+
+ return inside && intersects;
+
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.h b/platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.h
new file mode 100644
index 0000000000..a10c402c9e
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.h
@@ -0,0 +1,13 @@
+//
+// CalloutDelegateUsageExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface CalloutDelegateUsageExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.m b/platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.m
new file mode 100644
index 0000000000..ed7e54e080
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CalloutDelegateUsageExample.m
@@ -0,0 +1,84 @@
+#import "CalloutDelegateUsageExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleCalloutDelegateUsage = @"CalloutDelegateUsageExample";
+
+@interface CalloutDelegateUsageExample () <MGLMapViewDelegate>
+@property MGLMapView *mapView;
+@end
+
+@implementation CalloutDelegateUsageExample
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ [self.view addSubview:self.mapView];
+
+ // Remember to set the delegate.
+ self.mapView.delegate = self;
+
+ [self addAnnotation];
+}
+
+- (void)addAnnotation
+{
+ MGLPointAnnotation *annotation = [[MGLPointAnnotation alloc] init];
+ annotation.coordinate = CLLocationCoordinate2DMake(35.03946, 135.72956);
+ annotation.title = @"Kinkaku-ji";
+ annotation.subtitle = [NSString stringWithFormat:@"%.5f, %.5f", annotation.coordinate.latitude, annotation.coordinate.longitude];
+
+ [self.mapView addAnnotation:annotation];
+
+ // Center the map on the annotation.
+ [self.mapView setCenterCoordinate:annotation.coordinate zoomLevel:17 animated:NO];
+
+ // Pop-up the callout view.
+ [self.mapView selectAnnotation:annotation animated:YES];
+}
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id<MGLAnnotation>)annotation
+{
+ return true;
+}
+
+- (UIView *)mapView:(MGLMapView *)mapView leftCalloutAccessoryViewForAnnotation:(id<MGLAnnotation>)annotation
+{
+ if ([annotation.title isEqualToString:@"Kinkaku-ji"])
+ {
+ // Callout height is fixed; width expands to fit its content.
+ UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 60.f, 50.f)];
+ label.textAlignment = NSTextAlignmentRight;
+ label.textColor = [UIColor colorWithRed:0.81f green:0.71f blue:0.23f alpha:1.f];
+ label.text = @"金閣寺";
+
+ return label;
+ }
+
+ return nil;
+}
+
+- (UIView *)mapView:(MGLMapView *)mapView rightCalloutAccessoryViewForAnnotation:(id<MGLAnnotation>)annotation
+{
+ return [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
+}
+
+- (void)mapView:(MGLMapView *)mapView annotation:(id<MGLAnnotation>)annotation calloutAccessoryControlTapped:(UIControl *)control
+{
+ // Hide the callout view.
+ [self.mapView deselectAnnotation:annotation animated:NO];
+
+ // Show an alert containing the annotation's details
+ UIAlertController *alert = [UIAlertController alertControllerWithTitle:annotation.title
+ message:@"A lovely (if touristy) place."
+ preferredStyle:UIAlertControllerStyleAlert];
+
+ [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+
+ [self presentViewController:alert animated:YES completion:nil];
+
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.h b/platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.h
new file mode 100644
index 0000000000..45b0ab9732
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.h
@@ -0,0 +1,13 @@
+//
+// CameraAnimationExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface CameraAnimationExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.m b/platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.m
new file mode 100644
index 0000000000..2e32826e0b
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CameraAnimationExample.m
@@ -0,0 +1,40 @@
+#import "CameraAnimationExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleCameraAnimation = @"CameraAnimationExample";
+
+@interface CameraAnimationExample () <MGLMapViewDelegate>
+@end
+
+@implementation CameraAnimationExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.delegate = self;
+
+ mapView.styleURL = [MGLStyle outdoorsStyleURLWithVersion:9];
+
+ // Mauna Kea, Hawaii
+ CLLocationCoordinate2D center = CLLocationCoordinate2DMake(19.820689, -155.468038);
+
+ // Optionally set a starting point.
+ [mapView setCenterCoordinate:center zoomLevel:7 direction:0 animated:NO];
+
+ [self.view addSubview:mapView];
+}
+
+-(void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView {
+ // Wait for the map to load before initiating the first camera movement.
+
+ // Create a camera that rotates around the same center point, rotating 180°.
+ // `fromDistance:` is meters above mean sea level that an eye would have to be in order to see what the map view is showing.
+ MGLMapCamera *camera = [MGLMapCamera cameraLookingAtCenterCoordinate:mapView.centerCoordinate fromDistance:4500 pitch:15 heading:180];
+
+ // Animate the camera movement over 5 seconds.
+ [mapView setCamera:camera withDuration:5 animationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.h b/platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.h
new file mode 100644
index 0000000000..b3ceba8b75
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.h
@@ -0,0 +1,14 @@
+//
+// CameraFlyToViewController.h
+// Examples
+//
+// Created by Jordan Kiley on 12/13/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+@import Mapbox;
+
+@interface CameraFlyToExample : UIViewController <MGLMapViewDelegate>
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.m b/platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.m
new file mode 100644
index 0000000000..a97d7058a0
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CameraFlyToExample.m
@@ -0,0 +1,39 @@
+@import Mapbox;
+#import "CameraFlyToExample.h"
+
+NSString const *MBXExampleCameraFlyTo = @"CameraFlyToExample";
+
+@interface CameraFlyToExample ()
+@end
+
+@implementation CameraFlyToExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Sets Honolulu, Hawaii as the camera's starting point.
+ CLLocation *honolulu = [[CLLocation alloc] initWithLatitude:21.3069 longitude:-157.8583];
+ [mapView setCenterCoordinate:honolulu.coordinate
+ zoomLevel:14 animated:NO];
+
+ mapView.delegate = self;
+ [self.view addSubview:mapView];
+}
+
+- (void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView {
+
+ // Waits for the mapView to finish loading before setting up the camera.
+ // Defines the destination camera as Hawaii Island.
+ MGLMapCamera *camera = [MGLMapCamera cameraLookingAtCenterCoordinate:CLLocationCoordinate2DMake(19.784213, -155.784605) fromDistance:35000 pitch:70 heading:90];
+
+ // Goes from Honolulu to destination camera.
+ [mapView flyToCamera:camera withDuration:4.0 peakAltitude:3000 completionHandler:nil];
+ // To use default duration and peak altitudes:
+ // [mapView flyToCamera:camera completionHandler:nil];
+ // To use default peak altitude:
+ // [mapView flyToCamera:camera withDuration:4 completionHandler:nil];
+}
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/ClusteringExample.h b/platform/ios/demo/Examples/ObjectiveC/ClusteringExample.h
new file mode 100644
index 0000000000..5cca378062
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/ClusteringExample.h
@@ -0,0 +1,13 @@
+//
+// ClusteringExample.h
+// Examples
+//
+// Created by Justin R. Miller on 2/22/17.
+// Copyright © 2017 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ClusteringExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/ClusteringExample.m b/platform/ios/demo/Examples/ObjectiveC/ClusteringExample.m
new file mode 100644
index 0000000000..cd2182b2ca
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/ClusteringExample.m
@@ -0,0 +1,143 @@
+#import "ClusteringExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleClustering = @"ClusteringExample";
+
+@interface ClusteringExample () <MGLMapViewDelegate>
+
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) UIImage *icon;
+@property (nonatomic) UILabel *popup;
+
+@end
+
+@implementation ClusteringExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:[MGLStyle lightStyleURLWithVersion:9]];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ self.mapView.tintColor = [UIColor darkGrayColor];
+ self.mapView.delegate = self;
+ [self.view addSubview:self.mapView];
+
+ self.icon = [UIImage imageNamed:@"port"];
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"ports" ofType:@"geojson"]];
+
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"clusteredPorts" URL:url options:@{
+ MGLShapeSourceOptionClustered: @(YES),
+ MGLShapeSourceOptionClusterRadius: @(self.icon.size.width)
+ }];
+ [style addSource:source];
+
+ // Use a template image so that we can tint it with the `iconColor` runtime styling property.
+ [style setImage:[self.icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forName:@"icon"];
+
+ // Show unclustered features as icons. The `cluster` attribute is built into clustering-enabled source features.
+ MGLSymbolStyleLayer *ports = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"ports" source:source];
+ ports.iconImageName = [MGLStyleValue valueWithRawValue:@"icon"];
+ ports.iconColor = [MGLStyleValue valueWithRawValue:[[UIColor darkGrayColor] colorWithAlphaComponent:0.9]];
+ ports.predicate = [NSPredicate predicateWithFormat:@"%K != YES", @"cluster"];
+ [style addLayer:ports];
+
+ // Color clustered features based on clustered point counts.
+ NSDictionary *stops = @{ @20: [MGLStyleValue valueWithRawValue:[UIColor lightGrayColor]],
+ @50: [MGLStyleValue valueWithRawValue:[UIColor orangeColor]],
+ @100: [MGLStyleValue valueWithRawValue:[UIColor redColor]],
+ @200: [MGLStyleValue valueWithRawValue:[UIColor purpleColor]] };
+
+ // Show clustered features as circles. The `point_count` attribute is built into clustering-enabled source features.
+ MGLCircleStyleLayer *circlesLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"clusteredPorts" source:source];
+ circlesLayer.circleRadius = [MGLStyleValue valueWithRawValue:@(self.icon.size.width / 2)];
+ circlesLayer.circleOpacity = [MGLStyleValue valueWithRawValue:@0.75];
+ circlesLayer.circleStrokeColor = [MGLStyleValue valueWithRawValue:[[UIColor whiteColor] colorWithAlphaComponent:0.75]];
+ circlesLayer.circleStrokeWidth = [MGLStyleValue valueWithRawValue:@2];
+ circlesLayer.circleColor = [MGLSourceStyleFunction
+ functionWithInterpolationMode:MGLInterpolationModeInterval
+ stops:stops
+ attributeName:@"point_count"
+ options:nil];
+ circlesLayer.predicate = [NSPredicate predicateWithFormat:@"%K == YES", @"cluster"];
+ [style addLayer:circlesLayer];
+
+ // Label cluster circles with a layer of text indicating feature count. Per text token convention, wrap the attribute in {}.
+ MGLSymbolStyleLayer *numbersLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"clusteredPortsNumbers" source:source];
+ numbersLayer.textColor = [MGLStyleValue valueWithRawValue:[UIColor whiteColor]];
+ numbersLayer.textFontSize = [MGLStyleValue valueWithRawValue:@(self.icon.size.width / 2)];
+ numbersLayer.iconAllowsOverlap = [MGLStyleValue valueWithRawValue:@(YES)];
+ numbersLayer.text = [MGLStyleValue valueWithRawValue:@"{point_count}"];
+ numbersLayer.predicate = [NSPredicate predicateWithFormat:@"%K == YES", @"cluster"];
+ [style addLayer:numbersLayer];
+
+ // Add a tap gesture for zooming in to clusters or showing popups on individual features.
+ [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]];
+}
+
+- (void)mapViewRegionIsChanging:(MGLMapView *)mapView {
+ [self showPopup:NO animated:NO];
+}
+
+- (void)handleTap:(UITapGestureRecognizer *)tap {
+ if (tap.state == UIGestureRecognizerStateEnded) {
+ CGPoint point = [tap locationInView:tap.view];
+ CGFloat width = self.icon.size.width;
+ CGRect rect = CGRectMake(point.x - width / 2, point.y - width / 2, width, width);
+
+ // Find cluster circles and/or individual port icons in a touch-sized region around the tap.
+ // In theory, we should only find either one cluster (since they don't overlap) or one port
+ // (since overlapping ones would be clustered).
+ NSArray *clusters = [self.mapView visibleFeaturesInRect:rect inStyleLayersWithIdentifiers:[NSSet setWithObject:@"clusteredPorts"]];
+ NSArray *ports = [self.mapView visibleFeaturesInRect:rect inStyleLayersWithIdentifiers:[NSSet setWithObject:@"ports"]];
+
+ if (clusters.count) {
+ [self showPopup:NO animated:YES];
+ MGLPointFeature *cluster = (MGLPointFeature *)clusters.firstObject;
+ [self.mapView setCenterCoordinate:cluster.coordinate zoomLevel:(self.mapView.zoomLevel + 1) animated:YES];
+ } else if (ports.count) {
+ MGLPointFeature *port = ((MGLPointFeature *)ports.firstObject);
+
+ if (!self.popup) {
+ self.popup = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
+ self.popup.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9];
+ self.popup.layer.cornerRadius = 4;
+ self.popup.layer.masksToBounds = YES;
+ self.popup.textAlignment = NSTextAlignmentCenter;
+ self.popup.lineBreakMode = NSLineBreakByTruncatingTail;
+ self.popup.font = [UIFont systemFontOfSize:16];
+ self.popup.textColor = [UIColor blackColor];
+ self.popup.alpha = 0;
+ [self.view addSubview:self.popup];
+ }
+
+ self.popup.text = [NSString stringWithFormat:@"%@", [port attributeForKey:@"name"]];
+ CGSize size = [self.popup.text sizeWithAttributes:@{ NSFontAttributeName: self.popup.font }];
+ self.popup.bounds = CGRectInset(CGRectMake(0, 0, size.width, size.height), -10, -10);
+ point = [self.mapView convertCoordinate:port.coordinate toPointToView:self.mapView];
+ self.popup.center = CGPointMake(point.x, point.y - 50);
+
+ if (self.popup.alpha < 1) {
+ [self showPopup:YES animated:YES];
+ }
+ } else {
+ [self showPopup:NO animated:YES];
+ }
+ }
+}
+
+- (void)showPopup:(BOOL)shouldShow animated:(BOOL)animated {
+ CGFloat alpha = (shouldShow ? 1 : 0);
+ if (animated) {
+ __typeof__(self) __weak weakSelf = self;
+ [UIView animateWithDuration:0.25 animations:^{
+ weakSelf.popup.alpha = alpha;
+ }];
+ } else {
+ self.popup.alpha = alpha;
+ }
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.h b/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.h
new file mode 100644
index 0000000000..e2d90f48b6
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.h
@@ -0,0 +1,13 @@
+//
+// CustomAnnotationModelExample.h
+// Examples
+//
+// Created by Jason Wray on 5/20/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface CustomAnnotationModelExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.m b/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.m
new file mode 100644
index 0000000000..5cccaaf0ef
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModelExample.m
@@ -0,0 +1,122 @@
+#import "CustomAnnotationModelExample.h"
+#import "CustomAnnotationModels.h"
+@import Mapbox;
+
+NSString *const MBXExampleCustomAnnotationModel = @"CustomAnnotationModelExample";
+
+@interface CustomAnnotationModelExample () <MGLMapViewDelegate>
+@end
+
+@implementation CustomAnnotationModelExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.styleURL = [MGLStyle lightStyleURLWithVersion:9];
+ mapView.tintColor = [UIColor darkGrayColor];
+ mapView.zoomLevel = 1;
+ mapView.delegate = self;
+ [self.view addSubview:mapView];
+
+ // Polyline
+ // Create a coordinates array with all of the coordinates for our polyline.
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(35, -25),
+ CLLocationCoordinate2DMake(20, -30),
+ CLLocationCoordinate2DMake( 0, -25),
+ CLLocationCoordinate2DMake(-15, 0),
+ CLLocationCoordinate2DMake(-45, 10),
+ CLLocationCoordinate2DMake(-45, 40),
+ };
+ NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
+
+ CustomPolyline *polyline = [CustomPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];//
+ // Set the custom `color` property, later used in the `mapView:strokeColorForShapeAnnotation:` delegate method.
+ polyline.color = [UIColor darkGrayColor];
+
+ // Add the polyline to the map. Note that this method name is singular.
+ [mapView addAnnotation:polyline];
+
+ // Point Annotations
+ // Add a custom point annotation for every coordinate (vertex) in the polyline.
+ NSMutableArray *pointAnnotations = [NSMutableArray arrayWithCapacity:numberOfCoordinates];
+ for (NSUInteger i = 0; i < numberOfCoordinates; i++) {
+ NSUInteger count = pointAnnotations.count + 1;
+ CustomPointAnnotation *point = [[CustomPointAnnotation alloc] init];
+
+ point.coordinate = coordinates[i];
+ point.title = [NSString stringWithFormat:@"Custom Point Annotation %lu", (unsigned long)count];
+
+ // Set the custom `image` and `reuseIdentifier` properties, later used in the `mapView:imageForAnnotation:` delegate method.
+ // Create a unique reuse identifier for each new annotation image.
+ point.reuseIdentifier = [NSString stringWithFormat:@"customAnnotation%lu", (unsigned long)count];
+ // This dot image grows in size as more annotations are added to the array.
+ point.image = [self dotWithSize:(5 * count)];
+
+ // Append each annotation to the array, which will be added to the map all at once.
+ [pointAnnotations addObject:point];
+ }
+
+ // Add the point annotations to the map. This time the method name is plural.
+ // If you have multiple annotations to add, batching their addition to the map is more efficient.
+ [mapView addAnnotations:pointAnnotations];
+}
+
+- (UIImage *)dotWithSize:(NSUInteger)size {
+ size = (CGFloat)size;
+ CGRect rect = CGRectMake(0, 0, size, size);
+ CGFloat strokeWidth = 1;
+
+ UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]);
+
+ UIBezierPath *ovalPath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(rect, strokeWidth, strokeWidth)];
+ [UIColor.darkGrayColor setFill];
+ [ovalPath fill];
+
+ [UIColor.whiteColor setStroke];
+ ovalPath.lineWidth = strokeWidth;
+ [ovalPath stroke];
+
+ UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+
+ return image;
+}
+
+#pragma mark - MGLMapViewDelegate methods
+
+- (MGLAnnotationImage *)mapView:(MGLMapView *)mapView imageForAnnotation:(id<MGLAnnotation>)annotation {
+ if ([annotation isKindOfClass:[CustomPointAnnotation class]]) {
+ CustomPointAnnotation *point = (CustomPointAnnotation *)annotation;
+ MGLAnnotationImage *annotationImage = [mapView dequeueReusableAnnotationImageWithIdentifier:point.reuseIdentifier];
+
+ if (annotationImage) {
+ // The annotatation image has already been cached, just reuse it.
+ return annotationImage;
+ } else if (point.image && point.reuseIdentifier) {
+ // Create a new annotation image.
+ return [MGLAnnotationImage annotationImageWithImage:point.image reuseIdentifier:point.reuseIdentifier];
+ }
+ }
+
+ // Fallback to the default marker image.
+ return nil;
+}
+
+- (UIColor *)mapView:(MGLMapView *)mapView strokeColorForShapeAnnotation:(MGLShape *)annotation {
+ if ([annotation isKindOfClass:[CustomPolyline class]]) {
+ // Return orange if the polyline does not have a custom color.
+ return [(CustomPolyline *)annotation color] ?: [UIColor orangeColor];
+ }
+
+ // Fallback to the default tint color.
+ return mapView.tintColor;
+}
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id<MGLAnnotation>)annotation {
+ return YES;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModels.h b/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModels.h
new file mode 100644
index 0000000000..4c5db3c51e
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomAnnotationModels.h
@@ -0,0 +1,29 @@
+@import Mapbox;
+
+// MGLAnnotation protocol reimplementation
+@interface CustomPointAnnotation : NSObject <MGLAnnotation>
+
+// As a reimplementation of the MGLAnnotation protocol, we have to add mutable coordinate and (sub)title properties ourselves.
+@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
+@property (nonatomic, copy, nullable) NSString *title;
+@property (nonatomic, copy, nullable) NSString *subtitle;
+
+// Custom properties that we will use to customize the annotation's image.
+@property (nonatomic, copy, nonnull) UIImage *image;
+@property (nonatomic, copy, nonnull) NSString *reuseIdentifier;
+
+@end
+@implementation CustomPointAnnotation
+@end
+
+// MGLPolyline subclass
+@interface CustomPolyline : MGLPolyline
+
+// Because this is a subclass of MGLPolyline, there is no need to redeclare its properties.
+
+// Custom property that we will use when drawing the polyline.
+@property (nonatomic, strong, nullable) UIColor *color;
+
+@end
+@implementation CustomPolyline
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.h b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.h
new file mode 100644
index 0000000000..2a5440cdd7
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.h
@@ -0,0 +1,14 @@
+//
+// CustomCalloutView.h
+// Examples
+//
+// Created by Jason Wray on 3/6/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+@import Mapbox;
+
+@interface CustomCalloutView : UIView <MGLCalloutView>
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.m b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.m
new file mode 100644
index 0000000000..07a7033379
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutView.m
@@ -0,0 +1,158 @@
+#import "CustomCalloutView.h"
+
+// Set defaults for custom tip drawing
+static CGFloat const tipHeight = 10.0;
+static CGFloat const tipWidth = 20.0;
+
+@interface CustomCalloutView ()
+@property (strong, nonatomic) UIButton *mainBody;
+@end
+
+@implementation CustomCalloutView {
+ id <MGLAnnotation> _representedObject;
+ __unused UIView *_leftAccessoryView;/* unused */
+ __unused UIView *_rightAccessoryView;/* unused */
+ __weak id <MGLCalloutViewDelegate> _delegate;
+}
+
+@synthesize representedObject = _representedObject;
+@synthesize leftAccessoryView = _leftAccessoryView;/* unused */
+@synthesize rightAccessoryView = _rightAccessoryView;/* unused */
+@synthesize delegate = _delegate;
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self)
+ {
+ self.backgroundColor = [UIColor clearColor];
+
+ // Create and add a subview to hold the callout’s text
+ UIButton *mainBody = [UIButton buttonWithType:UIButtonTypeSystem];
+ mainBody.backgroundColor = [self backgroundColorForCallout];
+ mainBody.tintColor = [UIColor whiteColor];
+ mainBody.contentEdgeInsets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
+ mainBody.layer.cornerRadius = 4.0;
+ self.mainBody = mainBody;
+
+ [self addSubview:self.mainBody];
+ }
+
+ return self;
+}
+
+
+#pragma mark - MGLCalloutView API
+
+- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated
+{
+ // Do not show a callout if there is no title set for the annotation
+ if (![self.representedObject respondsToSelector:@selector(title)])
+ {
+ return;
+ }
+
+ [view addSubview:self];
+
+ // Prepare title label
+ [self.mainBody setTitle:self.representedObject.title forState:UIControlStateNormal];
+ [self.mainBody sizeToFit];
+
+ if ([self isCalloutTappable])
+ {
+ // Handle taps and eventually try to send them to the delegate (usually the map view)
+ [self.mainBody addTarget:self action:@selector(calloutTapped) forControlEvents:UIControlEventTouchUpInside];
+ }
+ else
+ {
+ // Disable tapping and highlighting
+ self.mainBody.userInteractionEnabled = NO;
+ }
+
+ // Prepare our frame, adding extra space at the bottom for the tip
+ CGFloat frameWidth = self.mainBody.bounds.size.width;
+ CGFloat frameHeight = self.mainBody.bounds.size.height + tipHeight;
+ CGFloat frameOriginX = rect.origin.x + (rect.size.width/2.0) - (frameWidth/2.0);
+ CGFloat frameOriginY = rect.origin.y - frameHeight;
+ self.frame = CGRectMake(frameOriginX, frameOriginY,
+ frameWidth, frameHeight);
+
+ if (animated)
+ {
+ self.alpha = 0.0;
+
+ [UIView animateWithDuration:0.2 animations:^{
+ self.alpha = 1.0;
+ }];
+ }
+}
+
+- (void)dismissCalloutAnimated:(BOOL)animated
+{
+ if (self.superview)
+ {
+ if (animated)
+ {
+ [UIView animateWithDuration:0.2 animations:^{
+ self.alpha = 0.0;
+ } completion:^(BOOL finished) {
+ [self removeFromSuperview];
+ }];
+ }
+ else
+ {
+ [self removeFromSuperview];
+ }
+ }
+}
+
+#pragma mark - Callout interaction handlers
+
+- (BOOL)isCalloutTappable
+{
+ if ([self.delegate respondsToSelector:@selector(calloutViewShouldHighlight:)]) {
+ return [self.delegate performSelector:@selector(calloutViewShouldHighlight:) withObject:self];
+ }
+
+ return NO;
+}
+
+- (void)calloutTapped
+{
+ if ([self isCalloutTappable] && [self.delegate respondsToSelector:@selector(calloutViewTapped:)])
+ {
+ [self.delegate performSelector:@selector(calloutViewTapped:) withObject:self];
+ }
+}
+
+#pragma mark - Custom view styling
+
+- (UIColor *)backgroundColorForCallout
+{
+ return [UIColor darkGrayColor];
+}
+
+- (void)drawRect:(CGRect)rect
+{
+ // Draw the pointed tip at the bottom
+ UIColor *fillColor = [self backgroundColorForCallout];
+
+ CGFloat tipLeft = rect.origin.x + (rect.size.width / 2.0) - (tipWidth / 2.0);
+ CGPoint tipBottom = CGPointMake(rect.origin.x + (rect.size.width / 2.0), rect.origin.y + rect.size.height);
+ CGFloat heightWithoutTip = rect.size.height - tipHeight;
+
+ CGContextRef currentContext = UIGraphicsGetCurrentContext();
+
+ CGMutablePathRef tipPath = CGPathCreateMutable();
+ CGPathMoveToPoint(tipPath, NULL, tipLeft, heightWithoutTip);
+ CGPathAddLineToPoint(tipPath, NULL, tipBottom.x, tipBottom.y);
+ CGPathAddLineToPoint(tipPath, NULL, tipLeft + tipWidth, heightWithoutTip);
+ CGPathCloseSubpath(tipPath);
+
+ [fillColor setFill];
+ CGContextAddPath(currentContext, tipPath);
+ CGContextFillPath(currentContext);
+ CGPathRelease(tipPath);
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.h b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.h
new file mode 100644
index 0000000000..ad6501e057
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.h
@@ -0,0 +1,13 @@
+//
+// CustomCalloutViewExample.h
+// Examples
+//
+// Created by Jason Wray on 3/6/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface CustomCalloutViewExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.m b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.m
new file mode 100644
index 0000000000..680c5cc3ea
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomCalloutViewExample.m
@@ -0,0 +1,63 @@
+#import "CustomCalloutViewExample.h"
+#import "CustomCalloutView.h"
+@import Mapbox;
+
+NSString *const MBXExampleCustomCalloutView = @"CustomCalloutViewExample";
+
+@interface CustomCalloutViewExample () <MGLMapViewDelegate>
+@end
+
+@implementation CustomCalloutViewExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:[MGLStyle lightStyleURLWithVersion:9]];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.tintColor = [UIColor darkGrayColor];
+ [self.view addSubview:mapView];
+
+ // Set the map view‘s delegate property
+ mapView.delegate = self;
+
+ // Initialize and add the marker annotation
+ MGLPointAnnotation *marker = [[MGLPointAnnotation alloc] init];
+ marker.coordinate = CLLocationCoordinate2DMake(0, 0);
+ marker.title = @"Hello world!";
+
+ // This custom callout example does not implement subtitles
+ //marker.subtitle = @"Welcome to my marker";
+
+ // Add marker to the map
+ [mapView addAnnotation:marker];
+}
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id <MGLAnnotation>)annotation {
+ // Always allow callouts to popup when annotations are tapped
+ return YES;
+}
+
+- (UIView<MGLCalloutView> *)mapView:(__unused MGLMapView *)mapView calloutViewForAnnotation:(id<MGLAnnotation>)annotation
+{
+ // Only show callouts for `Hello world!` annotation
+ if ([annotation respondsToSelector:@selector(title)]
+ && [annotation.title isEqualToString:@"Hello world!"])
+ {
+ // Instantiate and return our custom callout view
+ CustomCalloutView *calloutView = [[CustomCalloutView alloc] init];
+ calloutView.representedObject = annotation;
+ return calloutView;
+ }
+ return nil;
+}
+
+- (void)mapView:(MGLMapView *)mapView tapOnCalloutForAnnotation:(id<MGLAnnotation>)annotation
+{
+ // Optionally handle taps on the callout
+ NSLog(@"Tapped the callout for: %@", annotation);
+
+ // Hide the callout
+ [mapView deselectAnnotation:annotation animated:YES];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.h b/platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.h
new file mode 100644
index 0000000000..c6dc901abd
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.h
@@ -0,0 +1,13 @@
+//
+// CustomRasterStyleExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface CustomRasterStyleExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.m b/platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.m
new file mode 100644
index 0000000000..5b5be9d3c0
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomRasterStyleExample.m
@@ -0,0 +1,20 @@
+#import "CustomRasterStyleExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleCustomRasterStyle = @"CustomRasterStyleExample";
+
+@implementation CustomRasterStyleExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ NSURL *styleURL = [NSURL URLWithString:@"https://www.mapbox.com/ios-sdk/files/mapbox-raster-v8.json"];
+ // Local paths are also acceptable.
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:styleURL];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [self.view addSubview:mapView];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.h b/platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.h
new file mode 100644
index 0000000000..2eb52122a0
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.h
@@ -0,0 +1,13 @@
+//
+// CustomStyleExample.h
+// Examples
+//
+// Created by Jason Wray on 1/26/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface CustomStyleExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.m b/platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.m
new file mode 100644
index 0000000000..3793ec5797
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/CustomStyleExample.m
@@ -0,0 +1,27 @@
+#import "CustomStyleExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleCustomStyle = @"CustomStyleExample";
+
+@implementation CustomStyleExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Fill in the next line with your style URL from Mapbox Studio.
+ // <#mapbox://styles/userName/styleHash#>
+ NSURL *styleURL = [NSURL URLWithString:@"mapbox://styles/mapbox/outdoors-v9"];
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds
+ styleURL:styleURL];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map’s center coordinate and zoom level.
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.52954, -122.72317)
+ zoomLevel:14
+ animated:NO];
+
+ [self.view addSubview:mapView];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.h b/platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.h
new file mode 100644
index 0000000000..2eba3362fe
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.h
@@ -0,0 +1,13 @@
+//
+// DDSCircleLayerExample.h
+// Examples
+//
+// Created by Nadia Barbosa on 3/9/17.
+// Copyright © 2017 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DDSCircleLayerExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.m b/platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.m
new file mode 100644
index 0000000000..6d946d8571
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DDSCircleLayerExample.m
@@ -0,0 +1,66 @@
+#import "DDSCircleLayerExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleDDSCircleLayer = @"DDSCircleLayerExample";
+
+@interface DDSCircleLayerExample () <MGLMapViewDelegate>
+
+@property (nonatomic) MGLMapView *mapView;
+
+@end
+
+@implementation DDSCircleLayerExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Create a new map view using the Mapbox Light style.
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds
+ styleURL:[MGLStyle lightStyleURLWithVersion:9]];
+
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ self.mapView.tintColor = [UIColor darkGrayColor];
+
+ // Set the map’s center coordinate and zoom level.
+ self.mapView.centerCoordinate = CLLocationCoordinate2DMake(38.897,-77.039);
+ self.mapView.zoomLevel = 10.5;
+
+ self.mapView.delegate = self;
+ [self.view addSubview: self.mapView];
+}
+
+// Wait until the style is loaded before modifying the map style.
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+
+ // "mapbox://examples.2uf7qges" is a map ID referencing a tileset. For more
+ // more information, see mapbox.com/help/define-map-id/
+ MGLSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"trees" configurationURL:[NSURL URLWithString:@"mapbox://examples.2uf7qges"]];
+
+ [self.mapView.style addSource:source];
+
+ MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier: @"tree-style" source:source];
+
+ // The source name from the source's TileJSON metadata: mapbox.com/api-documentation/#retrieve-tilejson-metadata
+ layer.sourceLayerIdentifier = @"yoshino-trees-a0puw5";
+
+ // Stops based on age of tree in years.
+ NSDictionary *stops = @{
+ @0: [MGLStyleValue valueWithRawValue:[UIColor colorWithRed:1.00 green:0.72 blue:0.85 alpha:1.0]],
+ @2: [MGLStyleValue valueWithRawValue:[UIColor colorWithRed:0.69 green:0.48 blue:0.73 alpha:1.0]],
+ @4: [MGLStyleValue valueWithRawValue:[UIColor colorWithRed:0.61 green:0.31 blue:0.47 alpha:1.0]],
+ @7: [MGLStyleValue valueWithRawValue:[UIColor colorWithRed:0.43 green:0.20 blue:0.38 alpha:1.0]],
+ @16: [MGLStyleValue valueWithRawValue:[UIColor colorWithRed:0.33 green:0.17 blue:0.25 alpha:1.0]]
+ };
+
+ // Style the circle layer color based on the above categorical stops.
+ layer.circleColor = [MGLStyleValue valueWithInterpolationMode: MGLInterpolationModeInterval
+ sourceStops: stops
+ attributeName: @"AGE"
+ options: nil];
+
+ layer.circleRadius = [MGLStyleValue valueWithRawValue:@3];
+
+ [self.mapView.style addLayer:layer];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.h b/platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.h
new file mode 100644
index 0000000000..ea87633168
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.h
@@ -0,0 +1,13 @@
+//
+// DDSLayerSelectionExample.h
+// Examples
+//
+// Created by Jordan Kiley on 3/21/17.
+// Copyright © 2017 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DDSLayerSelectionExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.m b/platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.m
new file mode 100644
index 0000000000..d28a47a7f0
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DDSLayerSelectionExample.m
@@ -0,0 +1,97 @@
+
+#import "DDSLayerSelectionExample.h"
+@import Mapbox;
+
+NSString const *MBXExampleDDSLayerSelection = @"DDSLayerSelectionExample";
+
+@interface DDSLayerSelectionExample () <MGLMapViewDelegate, UIGestureRecognizerDelegate>
+
+@property (nonatomic) MGLMapView *mapView;
+
+@end
+
+@implementation DDSLayerSelectionExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.delegate = self;
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(39.23225,-97.91015)];
+
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+ [self.view addSubview:self.mapView];
+
+ // Add a tap gesture recognizer to the map view.
+ UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
+ gesture.delegate = self;
+ gesture.numberOfTapsRequired = 1;
+ [self.mapView addGestureRecognizer:gesture];
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+
+ // Load a tileset containing U.S. states and their population density. For more information about working with tilesets, see: https://www.mapbox.com/help/studio-manual-tilesets/
+ NSURL *url = [NSURL URLWithString:@"mapbox://examples.69ytlgls"];
+
+ MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"state-source" configurationURL:url];
+ [style addSource:source];
+
+ MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"state-layer" source:source];
+
+ // Access the tileset layer.
+ layer.sourceLayerIdentifier = @"stateData_2-dx853g";
+
+ // Create a stops dictionary. This defines the relationship between population density and a UIColor.
+ NSDictionary *stops = @{
+ @0: [MGLStyleValue valueWithRawValue:[UIColor yellowColor]],
+ @600: [MGLStyleValue valueWithRawValue:[UIColor redColor]],
+ @1200: [MGLStyleValue valueWithRawValue:[UIColor blueColor]]
+ };
+
+ // Style the fill color using the stops dictionary, exponential interpolation mode, and the feature attribute name.
+ layer.fillColor = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ sourceStops:stops
+ attributeName:@"density"
+ options:@{MGLStyleFunctionOptionDefaultValue: [MGLStyleValue valueWithRawValue:[UIColor whiteColor]]}];
+
+ // Insert the new layer below the Mapbox Streets layer that contains state border lines. See the layer reference for more information about layer names: https://www.mapbox.com/vector-tiles/mapbox-streets-v7/
+ MGLStyleLayer *symbolLayer = [style layerWithIdentifier:@"admin-3-4-boundaries"];
+
+ [style insertLayer:layer belowLayer:symbolLayer];
+}
+
+- (void)handleTap:(UITapGestureRecognizer *)gesture {
+
+ // Get the CGPoint where the user tapped.
+ CGPoint spot = [gesture locationInView:self.mapView];
+
+ // Access the features at that point within the state layer.
+ NSArray *features = [self.mapView visibleFeaturesAtPoint:spot
+ inStyleLayersWithIdentifiers:[NSSet setWithObject:@"state-layer"]];
+
+ MGLPolygonFeature *feature = features.firstObject;
+
+ // Get the name of the selected state.
+ NSString *state = [feature attributeForKey:@"name"];
+
+ [self changeOpacityBasedOn:state];
+}
+
+- (void)changeOpacityBasedOn:(NSString*)name {
+
+ MGLFillStyleLayer *layer = (MGLFillStyleLayer *)[self.mapView.style layerWithIdentifier:@"state-layer"];
+
+ // Check if a state was selected, then change the opacity of the states that were not selected.
+ if (name.length > 0) {
+ layer.fillOpacity = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeCategorical
+ sourceStops:@{name: [MGLStyleValue valueWithRawValue:@1]}
+ attributeName:@"name"
+ options:@{MGLStyleFunctionOptionDefaultValue: [MGLStyleValue valueWithRawValue:@0]}];
+ } else {
+ // Reset the opacity for all states if the user did not tap on a state.
+ layer.fillOpacity = [MGLStyleValue valueWithRawValue:@1];
+ }
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.h b/platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.h
new file mode 100644
index 0000000000..49af5d7b9c
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.h
@@ -0,0 +1,13 @@
+//
+// DefaultStylesExample.h
+// Examples
+//
+// Created by Jason Wray on 1/28/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DefaultStylesExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.m b/platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.m
new file mode 100644
index 0000000000..e6e5771f94
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DefaultStylesExample.m
@@ -0,0 +1,27 @@
+#import "DefaultStylesExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleDefaultStyles = @"DefaultStylesExample";
+
+@implementation DefaultStylesExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds
+ styleURL:[MGLStyle outdoorsStyleURLWithVersion:9]];
+
+ // Tint the ℹ️ button and the user location annotation.
+ mapView.tintColor = [UIColor darkGrayColor];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map’s center coordinate and zoom level.
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(51.50713, -0.10957)
+ zoomLevel:13
+ animated:NO];
+
+ [self.view addSubview:mapView];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.h b/platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.h
new file mode 100644
index 0000000000..5b0e571ad7
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.h
@@ -0,0 +1,13 @@
+//
+// DraggableAnnotationViewExample.h
+// Examples
+//
+// Created by Jason Wray on 7/11/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DraggableAnnotationViewExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.m b/platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.m
new file mode 100644
index 0000000000..17b2e552a7
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DraggableAnnotationViewExample.m
@@ -0,0 +1,143 @@
+#import "DraggableAnnotationViewExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleDraggableAnnotationView = @"DraggableAnnotationViewExample";
+
+// MGLAnnotationView subclass
+@interface DraggableAnnotationView : MGLAnnotationView
+@end
+@implementation DraggableAnnotationView
+
+- (instancetype)initWithReuseIdentifier:(nullable NSString *)reuseIdentifier size:(CGFloat)size {
+ self = [self initWithReuseIdentifier:reuseIdentifier];
+ if (self)
+ {
+ // `draggable` is a property of MGLAnnotationView, disabled by default.
+ self.draggable = true;
+
+ // This property prevents the annotation from changing size when the map is tilted.
+ self.scalesWithViewingDistance = false;
+
+ // Begin setting up the view.
+ self.frame = CGRectMake(0, 0, size, size);
+
+ self.backgroundColor = [UIColor darkGrayColor];
+
+ // Use CALayer’s corner radius to turn this view into a circle.
+ self.layer.cornerRadius = size / 2;
+ self.layer.borderWidth = 1;
+ self.layer.borderColor = [UIColor whiteColor].CGColor;
+ self.layer.shadowColor = [UIColor blackColor].CGColor;
+ self.layer.shadowOpacity = 0.1;
+ }
+ return self;
+}
+
+- (void)setDragState:(MGLAnnotationViewDragState)dragState animated:(BOOL)animated {
+ [super setDragState:dragState animated:animated];
+
+ switch (dragState) {
+ case MGLAnnotationViewDragStateStarting:
+ printf("Starting");
+ [self startDragging];
+ break;
+
+ case MGLAnnotationViewDragStateDragging:
+ printf(".");
+ break;
+
+ case MGLAnnotationViewDragStateEnding:
+ case MGLAnnotationViewDragStateCanceling:
+ printf("Ending\n");
+ [self endDragging];
+ break;
+
+ case MGLAnnotationViewDragStateNone:
+ return;
+ }
+}
+
+// When the user interacts with an annotation, animate opacity and scale changes.
+- (void)startDragging {
+ [UIView animateWithDuration:0.3 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:0 animations:^{
+ self.layer.opacity = 0.8;
+ self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.5, 1.5);
+ } completion:nil];
+}
+
+- (void)endDragging {
+ self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.5, 1.5);
+ [UIView animateWithDuration:0.3 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:0 animations:^{
+ self.layer.opacity = 1;
+ self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
+ } completion:nil];
+}
+
+@end
+
+
+//
+// Example view controller
+@interface DraggableAnnotationViewExample () <MGLMapViewDelegate>
+@end
+@implementation DraggableAnnotationViewExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.styleURL = [MGLStyle lightStyleURLWithVersion:9];
+ mapView.tintColor = [UIColor darkGrayColor];
+ mapView.zoomLevel = 1;
+ mapView.delegate = self;
+ [self.view addSubview:mapView];
+
+ // Specify coordinates for our annotations.
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(0, -70),
+ CLLocationCoordinate2DMake(0, -35),
+ CLLocationCoordinate2DMake(0, 0),
+ CLLocationCoordinate2DMake(0, 35),
+ CLLocationCoordinate2DMake(0, 70),
+ };
+ NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
+
+ // Fill an array with point annotations and add it to the map.
+ NSMutableArray *pointAnnotations = [NSMutableArray arrayWithCapacity:numberOfCoordinates];
+ for (NSUInteger i = 0; i < numberOfCoordinates; i++) {
+ CLLocationCoordinate2D coordinate = coordinates[i];
+ MGLPointAnnotation *point = [[MGLPointAnnotation alloc] init];
+ point.coordinate = coordinate;
+ point.title = @"To drag this annotation, first tap and hold.";
+ [pointAnnotations addObject:point];
+ }
+
+ [mapView addAnnotations:pointAnnotations];
+}
+
+#pragma mark - MGLMapViewDelegate methods
+
+// This delegate method is where you tell the map to load a view for a specific annotation. To load a static MGLAnnotationImage, you would use `-mapView:imageForAnnotation:`.
+- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id <MGLAnnotation>)annotation {
+ // This example is only concerned with point annotations.
+ if (![annotation isKindOfClass:[MGLPointAnnotation class]]) {
+ return nil;
+ }
+
+ // For better performance, always try to reuse existing annotations. To use multiple different annotation views, change the reuse identifier for each.
+ DraggableAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"draggablePoint"];
+
+ // If there’s no reusable annotation view available, initialize a new one.
+ if (!annotationView) {
+ annotationView = [[DraggableAnnotationView alloc] initWithReuseIdentifier:@"draggablePoint" size:50];
+ }
+
+ return annotationView;
+}
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id<MGLAnnotation>)annotation {
+ return YES;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.h b/platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.h
new file mode 100644
index 0000000000..8a16ca91bb
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.h
@@ -0,0 +1,13 @@
+//
+// DrawingACustomMarkerExample.h
+// Examples
+//
+// Created by Jason Wray on 2/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DrawingACustomMarkerExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.m b/platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.m
new file mode 100644
index 0000000000..ad80b49efc
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingACustomMarkerExample.m
@@ -0,0 +1,67 @@
+#import "DrawingACustomMarkerExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleDrawingACustomMarker = @"DrawingACustomMarkerExample";
+
+@interface DrawingACustomMarkerExample () <MGLMapViewDelegate>
+@end
+
+@implementation DrawingACustomMarkerExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ NSURL *styleURL = [MGLStyle lightStyleURLWithVersion:9];
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:styleURL];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.tintColor = [UIColor darkGrayColor];
+
+ // Set the map‘s bounds to Pisa, Italy.
+ MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(
+ CLLocationCoordinate2DMake(43.7115, 10.3725),
+ CLLocationCoordinate2DMake(43.7318, 10.4222));
+ [mapView setVisibleCoordinateBounds:bounds];
+
+ [self.view addSubview:mapView];
+
+ // Set the map view‘s delegate property.
+ mapView.delegate = self;
+
+ // Initialize and add the point annotation.
+ MGLPointAnnotation *pisa = [[MGLPointAnnotation alloc] init];
+ pisa.coordinate = CLLocationCoordinate2DMake(43.723, 10.396633);
+ pisa.title = @"Leaning Tower of Pisa";
+ [mapView addAnnotation:pisa];
+}
+
+- (MGLAnnotationImage *)mapView:(MGLMapView *)mapView imageForAnnotation:(id <MGLAnnotation>)annotation {
+ // Try to reuse the existing ‘pisa’ annotation image, if it exists.
+ MGLAnnotationImage *annotationImage = [mapView dequeueReusableAnnotationImageWithIdentifier:@"pisa"];
+
+ // If the ‘pisa’ annotation image hasn‘t been set yet, initialize it here.
+ if (!annotationImage) {
+ // Leaning Tower of Pisa by Stefan Spieler from the Noun Project.
+ UIImage *image = [UIImage imageNamed:@"pisavector"];
+
+ // The anchor point of an annotation is currently always the center. To
+ // shift the anchor point to the bottom of the annotation, the image
+ // asset includes transparent bottom padding equal to the original image
+ // height.
+ //
+ // To make this padding non-interactive, we create another image object
+ // with a custom alignment rect that excludes the padding.
+ image = [image imageWithAlignmentRectInsets:UIEdgeInsetsMake(0, 0, image.size.height/2, 0)];
+
+ // Initialize the ‘pisa’ annotation image with the UIImage we just loaded.
+ annotationImage = [MGLAnnotationImage annotationImageWithImage:image reuseIdentifier:@"pisa"];
+ }
+
+ return annotationImage;
+}
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id <MGLAnnotation>)annotation {
+ // Always allow callouts to popup when annotations are tapped.
+ return YES;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.h b/platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.h
new file mode 100644
index 0000000000..afc23b4ee6
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.h
@@ -0,0 +1,13 @@
+//
+// DrawingAGeoJSONLineExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DrawingAGeoJSONLineExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.m b/platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.m
new file mode 100644
index 0000000000..2b6cd88f47
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingAGeoJSONLineExample.m
@@ -0,0 +1,80 @@
+#import "DrawingAGeoJSONLineExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleDrawingAGeoJSONLine = @"DrawingAGeoJSONLineExample";
+
+@interface DrawingAGeoJSONLineExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@end
+
+@implementation DrawingAGeoJSONLineExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map's center coordinate
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.5076, -122.6736)
+ zoomLevel:11
+ animated:NO];
+
+ [self.view addSubview:self.mapView];
+
+ // Set the delegate property of our map view to self after instantiating it.
+ self.mapView.delegate = self;
+
+ [self drawPolyline];
+}
+
+- (void)drawPolyline {
+ // Perform GeoJSON parsing on a background thread
+ dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+ dispatch_async(backgroundQueue, ^(void) {
+ // Get the path for example.geojson in the app's bundle
+ NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"geojson"];
+
+ // Convert the file contents to a shape collection feature object
+ NSData *data = [[NSData alloc] initWithContentsOfFile:jsonPath];
+ MGLShapeCollectionFeature *shapeCollectionFeature = (MGLShapeCollectionFeature *)[MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:NULL];
+
+ MGLPolylineFeature *polyline = (MGLPolylineFeature *)shapeCollectionFeature.shapes.firstObject;
+
+ // Optionally set the title of the polyline, which can be used for:
+ // - Callout view
+ // - Object identification
+ // In this case, set it to the name included in the GeoJSON
+ polyline.title = polyline.attributes[@"name"]; // "Crema to Council Crest"
+
+ // Add the polyline to the map, back on the main thread
+ // Use weak reference to self to prevent retain cycle
+ __weak typeof(self) weakSelf = self;
+ dispatch_async(dispatch_get_main_queue(), ^(void) {
+ [weakSelf.mapView addAnnotation:polyline];
+ });
+ });
+}
+
+- (CGFloat)mapView:(MGLMapView *)mapView alphaForShapeAnnotation:(MGLShape *)annotation {
+ // Set the alpha for all shape annotations to 1 (full opacity)
+ return 1.0f;
+}
+
+- (CGFloat)mapView:(MGLMapView *)mapView lineWidthForPolylineAnnotation:(MGLPolyline *)annotation {
+ // Set the line width for polyline annotations
+ return 2.0f;
+}
+
+- (UIColor *)mapView:(MGLMapView *)mapView strokeColorForShapeAnnotation:(MGLShape *)annotation {
+ // Set the stroke color for shape annotations
+ // ... but give our polyline a unique color by checking for its `title` property
+ if ([annotation.title isEqualToString:@"Crema to Council Crest"]) {
+ // Mapbox cyan
+ return [UIColor colorWithRed:59.0f/255.0f green:178.0f/255.0f blue:208.0f/255.0f alpha:1.0f];
+ } else {
+ return [UIColor redColor];
+ }
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.h b/platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.h
new file mode 100644
index 0000000000..a3c478bab6
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.h
@@ -0,0 +1,13 @@
+//
+// DrawingAMarkerExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DrawingAMarkerExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.m b/platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.m
new file mode 100644
index 0000000000..6aacdf2caa
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingAMarkerExample.m
@@ -0,0 +1,48 @@
+#import "DrawingAMarkerExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleDrawingAMarker = @"DrawingAMarkerExample";
+
+@interface DrawingAMarkerExample () <MGLMapViewDelegate>
+@end
+
+@implementation DrawingAMarkerExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map’s center coordinates and zoom level.
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(40.7326808, -73.9843407)
+ zoomLevel:12
+ animated:NO];
+
+ [self.view addSubview:mapView];
+
+ // Set the delegate property of our map view to `self` after instantiating it.
+ mapView.delegate = self;
+
+ // Declare the marker `hello` and set its coordinates, title, and subtitle.
+ MGLPointAnnotation *hello = [[MGLPointAnnotation alloc] init];
+ hello.coordinate = CLLocationCoordinate2DMake(40.7326808, -73.9843407);
+ hello.title = @"Hello world!";
+ hello.subtitle = @"Welcome to my marker";
+
+ // Add marker `hello` to the map
+ [mapView addAnnotation:hello];
+}
+
+// Use the default marker. See also: our view annotation or custom marker examples.
+- (MGLAnnotationImage *)mapView:(MGLMapView *)mapView viewForAnnotation:(id <MGLAnnotation>)annotation {
+ return nil;
+}
+
+// Allow callout view to appear when an annotation is tapped.
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id <MGLAnnotation>)annotation {
+ return YES;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.h b/platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.h
new file mode 100644
index 0000000000..29487ea8c2
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.h
@@ -0,0 +1,13 @@
+//
+// DrawingAPolygonExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface DrawingAPolygonExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.m b/platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.m
new file mode 100644
index 0000000000..eb304a5c00
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/DrawingAPolygonExample.m
@@ -0,0 +1,77 @@
+#import "DrawingAPolygonExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleDrawingAPolygon = @"DrawingAPolygonExample";
+
+@interface DrawingAPolygonExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@end
+
+@implementation DrawingAPolygonExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map's center coordinate
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.520486, -122.673541)
+ zoomLevel:11
+ animated:NO];
+
+ [self.view addSubview:self.mapView];
+
+ // Set the delegate property of our map view to self after instantiating it
+ self.mapView.delegate = self;
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+
+ // Draw the polygon after the map has initialized
+ [self drawShape];
+}
+
+- (void)drawShape {
+ // Create a coordinates array to hold all of the coordinates for our shape.
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(45.522585, -122.685699),
+ CLLocationCoordinate2DMake(45.534611, -122.708873),
+ CLLocationCoordinate2DMake(45.530883, -122.678833),
+ CLLocationCoordinate2DMake(45.547115, -122.667503),
+ CLLocationCoordinate2DMake(45.530643, -122.660121),
+ CLLocationCoordinate2DMake(45.533529, -122.636260),
+ CLLocationCoordinate2DMake(45.521743, -122.659091),
+ CLLocationCoordinate2DMake(45.510677, -122.648792),
+ CLLocationCoordinate2DMake(45.515008, -122.664070),
+ CLLocationCoordinate2DMake(45.502496, -122.669048),
+ CLLocationCoordinate2DMake(45.515369, -122.678489),
+ CLLocationCoordinate2DMake(45.506346, -122.702007),
+ CLLocationCoordinate2DMake(45.522585, -122.685699),
+ };
+ NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
+
+ // Create our shape with the formatted coordinates array
+ MGLPolygon *shape = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates];
+
+ // Add the shape to the map
+ [self.mapView addAnnotation:shape];
+}
+
+- (CGFloat)mapView:(MGLMapView *)mapView alphaForShapeAnnotation:(MGLShape *)annotation {
+ // Set the alpha for shape annotations to 0.5 (half opacity)
+ return 0.5f;
+}
+
+- (UIColor *)mapView:(MGLMapView *)mapView strokeColorForShapeAnnotation:(MGLShape *)annotation {
+ // Set the stroke color for shape annotations
+ return [UIColor whiteColor];
+}
+
+- (UIColor *)mapView:(MGLMapView *)mapView fillColorForPolygonAnnotation:(MGLPolygon *)annotation {
+ // Mapbox cyan fill color
+ return [UIColor colorWithRed:59.0f/255.0f green:178.0f/255.0f blue:208.0f/255.0f alpha:1.0f];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.h b/platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.h
new file mode 100644
index 0000000000..a7ca638729
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.h
@@ -0,0 +1,13 @@
+//
+// ExtrusionsExample.h
+// Examples
+//
+// Created by Jordan Kiley on 5/11/17.
+// Copyright © 2017 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ExtrusionsExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.m b/platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.m
new file mode 100644
index 0000000000..c87449fb12
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/ExtrusionsExample.m
@@ -0,0 +1,56 @@
+//
+// ExtrusionsExample.m
+// Examples
+//
+// Created by Jordan Kiley on 5/11/17.
+// Copyright © 2017 Mapbox. All rights reserved.
+//
+
+#import "ExtrusionsExample.h"
+
+@import Mapbox;
+
+NSString *const MBXExample3DExtrusions = @"ExtrusionsExample";
+
+@interface ExtrusionsExample () <MGLMapViewDelegate>
+
+@end
+
+@implementation ExtrusionsExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:[MGLStyle lightStyleURLWithVersion:9]];
+
+ // Center the map on the Colosseum in Rome, Italy.
+
+ // Center the map view on the Colosseum in Rome, Italy and set the camera's pitch and distance.
+ mapView.camera = [MGLMapCamera cameraLookingAtCenterCoordinate:CLLocationCoordinate2DMake(41.8902, 12.4922) fromDistance:600 pitch:60 heading:0];
+ mapView.delegate = self;
+
+ [self.view addSubview:mapView];
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+
+ // Access the Mapbox Streets source and use it to create a `MGLFillExtrusionStyleLayer`. The source identifier is `composite`. Use the `sources` property on a style to verify source identifiers.
+ MGLSource *source = [style sourceWithIdentifier:@"composite"];
+ MGLFillExtrusionStyleLayer *layer = [[MGLFillExtrusionStyleLayer alloc] initWithIdentifier:@"buildings" source:source];
+ layer.sourceLayerIdentifier = @"building";
+
+ // Filter out buildings that should not extrude.
+ layer.predicate = [NSPredicate predicateWithFormat:@"extrude == 'true' AND height >= 0"];
+
+ // Set the fill extrusion height to the value for the building height attribute.
+ layer.fillExtrusionHeight = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"height" options:nil];
+ layer.fillExtrusionBase =[MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"min_height" options:nil];
+ layer.fillExtrusionOpacity = [MGLStyleValue valueWithRawValue:@0.75];
+ layer.fillExtrusionColor = [MGLStyleValue valueWithRawValue:[UIColor whiteColor]];
+
+ // Insert the fill extrusion layer below a POI label layer. If you aren’t sure what the layer is called, you can view the style in Mapbox Studio or iterate over the style’s layers property, printing out each layer’s identifier.
+ MGLStyleLayer *symbolLayer = [style layerWithIdentifier:@"poi-scalerank3"];
+ [style insertLayer:layer belowLayer:symbolLayer];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.h b/platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.h
new file mode 100644
index 0000000000..291b7b328f
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.h
@@ -0,0 +1,13 @@
+//
+// OfflinePackExample.h
+// Examples
+//
+// Created by Jason Wray on 3/31/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface OfflinePackExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.m b/platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.m
new file mode 100644
index 0000000000..7640d6439f
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/OfflinePackExample.m
@@ -0,0 +1,113 @@
+#import "OfflinePackExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleOfflinePack = @"OfflinePackExample";
+
+@interface OfflinePackExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) UIProgressView *progressView;
+@end
+
+@implementation OfflinePackExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:[MGLStyle darkStyleURLWithVersion:9]];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ self.mapView.tintColor = [UIColor lightGrayColor];
+ self.mapView.delegate = self;
+ [self.view addSubview:self.mapView];
+
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(22.27933, 114.16281)
+ zoomLevel:13
+ animated:NO];
+
+ // Setup offline pack notification handlers.
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackProgressDidChange:) name:MGLOfflinePackProgressChangedNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackDidReceiveError:) name:MGLOfflinePackErrorNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackDidReceiveMaximumAllowedMapboxTiles:) name:MGLOfflinePackMaximumMapboxTilesReachedNotification object:nil];
+}
+
+- (void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView {
+ // Start downloading tiles and resources for z13-16.
+ [self startOfflinePackDownload];
+}
+
+- (void)dealloc {
+ // Remove offline pack observers.
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)startOfflinePackDownload {
+ // Create a region that includes the current viewport and any tiles needed to view it when zoomed further in.
+ // Because tile count grows exponentially with the maximum zoom level, you should be conservative with your `toZoomLevel` setting.
+ id <MGLOfflineRegion> region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:self.mapView.styleURL bounds:self.mapView.visibleCoordinateBounds fromZoomLevel:self.mapView.zoomLevel toZoomLevel:16];
+
+ // Store some data for identification purposes alongside the downloaded resources.
+ NSDictionary *userInfo = @{ @"name": @"My Offline Pack" };
+ NSData *context = [NSKeyedArchiver archivedDataWithRootObject:userInfo];
+
+ // Create and register an offline pack with the shared offline storage object.
+ [[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack *pack, NSError *error) {
+ if (error != nil) {
+ // The pack couldn’t be created for some reason.
+ NSLog(@"Error: %@", error.localizedFailureReason);
+ } else {
+ // Start downloading.
+ [pack resume];
+ }
+ }];
+}
+
+#pragma mark - MGLOfflinePack notification handlers
+
+- (void)offlinePackProgressDidChange:(NSNotification *)notification {
+ MGLOfflinePack *pack = notification.object;
+
+ // Get the associated user info for the pack; in this case, `name = My Offline Pack`
+ NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
+
+ MGLOfflinePackProgress progress = pack.progress;
+ // or [notification.userInfo[MGLOfflinePackProgressUserInfoKey] MGLOfflinePackProgressValue]
+ uint64_t completedResources = progress.countOfResourcesCompleted;
+ uint64_t expectedResources = progress.countOfResourcesExpected;
+
+ // Calculate current progress percentage.
+ float progressPercentage = (float)completedResources / expectedResources;
+
+ // Setup the progress bar.
+ if (!self.progressView) {
+ self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
+ CGSize frame = self.view.bounds.size;
+ self.progressView.frame = CGRectMake(frame.width / 4, frame.height * 0.75, frame.width / 2, 10);
+ [self.view addSubview:self.progressView];
+ }
+
+ [self.progressView setProgress:progressPercentage animated:YES];
+
+ // If this pack has finished, print its size and resource count.
+ if (completedResources == expectedResources) {
+ NSString *byteCount = [NSByteCountFormatter stringFromByteCount:progress.countOfBytesCompleted countStyle:NSByteCountFormatterCountStyleMemory];
+ NSLog(@"Offline pack “%@” completed: %@, %llu resources", userInfo[@"name"], byteCount, completedResources);
+ } else {
+ // Otherwise, print download/verification progress.
+ NSLog(@"Offline pack “%@” has %llu of %llu resources — %.2f%%.", userInfo[@"name"], completedResources, expectedResources, progressPercentage * 100);
+ }
+}
+
+- (void)offlinePackDidReceiveError:(NSNotification *)notification {
+ MGLOfflinePack *pack = notification.object;
+ NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
+ NSError *error = notification.userInfo[MGLOfflinePackUserInfoKeyError];
+ NSLog(@"Offline pack “%@” received error: %@", userInfo[@"name"], error.localizedFailureReason);
+}
+
+- (void)offlinePackDidReceiveMaximumAllowedMapboxTiles:(NSNotification *)notification {
+ MGLOfflinePack *pack = notification.object;
+ NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
+ uint64_t maximumCount = [notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount] unsignedLongLongValue];
+ NSLog(@"Offline pack “%@” reached limit of %llu tiles.", userInfo[@"name"], maximumCount);
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/PointConversionExample.h b/platform/ios/demo/Examples/ObjectiveC/PointConversionExample.h
new file mode 100644
index 0000000000..1a8cbdf302
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/PointConversionExample.h
@@ -0,0 +1,13 @@
+//
+// PointConversionExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface PointConversionExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/PointConversionExample.m b/platform/ios/demo/Examples/ObjectiveC/PointConversionExample.m
new file mode 100644
index 0000000000..a5156e64fc
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/PointConversionExample.m
@@ -0,0 +1,64 @@
+#import "PointConversionExample.h"
+@import Mapbox;
+
+NSString *const MBXExamplePointConversion = @"PointConversionExample";
+
+@interface PointConversionExample ()
+@property (nonatomic) MGLMapView *mapView;
+@end
+
+@implementation PointConversionExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [self.view addSubview:self.mapView];
+
+ // Double tapping zooms the map, so ensure that can still happen.
+ UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil];
+ doubleTap.numberOfTapsRequired = 2;
+ [self.mapView addGestureRecognizer:doubleTap];
+
+ // Delay single tap recognition until it is clearly not a double.
+ UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
+ [singleTap requireGestureRecognizerToFail:doubleTap];
+ [self.mapView addGestureRecognizer:singleTap];
+
+ // Convert `mapView.centerCoordinate` (CLLocationCoordinate2D)
+ // to screen location (CGPoint).
+ CGPoint centerScreenPoint = [self.mapView convertCoordinate:self.mapView.centerCoordinate
+ toPointToView:self.mapView];
+
+ NSLog(@"Screen center: %@ = %@",
+ NSStringFromCGPoint(centerScreenPoint),
+ NSStringFromCGPoint(self.mapView.center));
+}
+
+- (void)handleSingleTap:(UITapGestureRecognizer *)tap {
+ // Convert tap location (CGPoint)
+ // to geographic coordinates (CLLocationCoordinate2D).
+ CLLocationCoordinate2D location = [self.mapView convertPoint:[tap locationInView:self.mapView]
+ toCoordinateFromView:self.mapView];
+
+ NSLog(@"You tapped at: %.5f, %.5f", location.latitude, location.longitude);
+
+ // Create an array of coordinates for our polyline.
+ CLLocationCoordinate2D coordinates[] = {
+ self.mapView.centerCoordinate,
+ location
+ };
+ NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
+
+ // Remove existing polyline from the map, (re)add polyline with coordinates.
+ if (self.mapView.annotations.count) {
+ [self.mapView removeAnnotations:self.mapView.annotations];
+ }
+ MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates
+ count:numberOfCoordinates];
+ [self.mapView addAnnotation:polyline];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.h b/platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.h
new file mode 100644
index 0000000000..551dc20e8a
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.h
@@ -0,0 +1,13 @@
+//
+// RuntimeAddLineExample.h
+// Examples
+//
+// Created by Eric Wolfe on 11/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface RuntimeAddLineExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.m b/platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.m
new file mode 100644
index 0000000000..6cc80b002e
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeAddLineExample.m
@@ -0,0 +1,94 @@
+#import "RuntimeAddLineExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleRuntimeAddLine = @"RuntimeAddLineExample";
+
+@interface RuntimeAddLineExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@end
+
+@implementation RuntimeAddLineExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.5076, -122.6736)
+ zoomLevel:11
+ animated:NO];
+
+ [self.view addSubview:self.mapView];
+
+ self.mapView.delegate = self;
+}
+
+// Wait until the map is loaded before adding to the map.
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ [self loadGeoJSON];
+}
+
+- (void)loadGeoJSON {
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ NSString *path = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"geojson"];
+ NSData *jsonData = [NSData dataWithContentsOfFile:path];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self drawPolyline:jsonData];
+ });
+ });
+}
+
+- (void)drawPolyline:(NSData *)geoJson {
+ // Add our GeoJSON data to the map as an MGLShapeSource.
+ // We can then reference this data from an MGLStyleLayer.
+ MGLShape *shape = [MGLShape shapeWithData:geoJson encoding:NSUTF8StringEncoding error:nil];
+ MGLSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"polyline" shape:shape options:nil];
+ [self.mapView.style addSource:source];
+
+ // Create new layer for the line
+ MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"polyline" source:source];
+ layer.lineJoin = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinRound]];
+ layer.lineCap = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapRound]];
+ layer.lineColor = [MGLStyleValue valueWithRawValue:[UIColor colorWithRed:59/255.0 green:178/255.0 blue:208/255.0 alpha:1]];
+ // Use a style function to smoothly adjust the line width from 2pt to 20pt between zoom levels 14 and 18. The `interpolationBase` parameter allows the values to interpolate along an exponential curve.
+ layer.lineWidth = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:@{
+ @14: [MGLStyleValue valueWithRawValue:@2],
+ @18: [MGLStyleValue valueWithRawValue:@20]
+ }
+ options:@{MGLStyleFunctionOptionDefaultValue:@1.5}];
+
+ // We can also add a second layer that will draw a stroke around the original line.
+ MGLLineStyleLayer *casingLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"polyline-case" source:source];
+ // Copy these attributes from the main line layer.
+ casingLayer.lineJoin = layer.lineJoin;
+ casingLayer.lineCap = layer.lineCap;
+ // Line gap width represents the space before the outline begins, so should match the main line’s line width exactly.
+ casingLayer.lineGapWidth = layer.lineWidth;
+ // Stroke color slightly darker than the line color.
+ casingLayer.lineColor = [MGLStyleValue valueWithRawValue:[UIColor colorWithRed:41/255.0 green:145/255.0 blue:171/255.0 alpha:1]];
+ // Use a style function to gradually increase the stroke width between zoom levels 14 and 18.
+ casingLayer.lineWidth = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:@{
+ @14: [MGLStyleValue valueWithRawValue:@1],
+ @18: [MGLStyleValue valueWithRawValue:@4]
+ }
+ options:@{MGLStyleFunctionOptionDefaultValue:@1.5}];
+
+ // Just for fun, let’s add another copy of the line with a dash pattern.
+ MGLLineStyleLayer *dashedLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"polyline-dash" source:source];
+ dashedLayer.lineJoin = layer.lineJoin;
+ dashedLayer.lineCap = layer.lineCap;
+ dashedLayer.lineWidth = layer.lineWidth;
+ dashedLayer.lineColor = [MGLStyleValue valueWithRawValue:[UIColor whiteColor]];
+ dashedLayer.lineOpacity = [MGLStyleValue valueWithRawValue:@0.5];
+ // Dash pattern in the format [dash, gap, dash, gap, ...]. You’ll want to adjust these values based on the line cap style.
+ dashedLayer.lineDashPattern = [MGLStyleValue valueWithRawValue:@[@0, @1.5]];
+
+ [self.mapView.style addLayer:layer];
+ [self.mapView.style addLayer:dashedLayer];
+ [self.mapView.style insertLayer:casingLayer belowLayer:layer];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.h b/platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.h
new file mode 100644
index 0000000000..bd55ce2efc
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.h
@@ -0,0 +1,13 @@
+//
+// RuntimeAnimateLineExample.h
+// Examples
+//
+// Created by Eric Wolfe on 11/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface RuntimeAnimateLineExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.m b/platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.m
new file mode 100644
index 0000000000..a9a44a97e7
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeAnimateLineExample.m
@@ -0,0 +1,181 @@
+#import "RuntimeAnimateLineExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleRuntimeAnimateLine = @"RuntimeAnimateLineExample";
+
+@interface RuntimeAnimateLineExample () <MGLMapViewDelegate> {
+ int _currentIndex;
+ NSTimer *_timer;
+}
+
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) MGLShapeSource *polylineSource;
+@property (nonatomic) NSArray<CLLocation *> *locations;
+
+@end
+
+@implementation RuntimeAnimateLineExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.5076, -122.6736)
+ zoomLevel:11
+ animated:NO];
+
+ [self.view addSubview:self.mapView];
+
+ self.mapView.delegate = self;
+}
+
+// Wait until the map is loaded before adding to the map.
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ [self addLayer];
+ [self animatePolyline];
+}
+
+- (void)addLayer {
+ // Add an empty MGLShapeSource, we’ll keep a reference to this and add points to this later.
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"polyline" features:@[] options:nil];
+ [self.mapView.style addSource:source];
+ self.polylineSource = source;
+
+ // Add a layer to style our polyline.
+ MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"polyline" source:source];
+ layer.lineJoin = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinRound]];
+ layer.lineCap = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapRound]];
+ layer.lineColor = [MGLStyleValue valueWithRawValue:[UIColor redColor]];
+ layer.lineWidth = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops: @{
+ @14: [MGLStyleValue valueWithRawValue:@5],
+ @18: [MGLStyleValue valueWithRawValue:@20]
+ }
+ options:@{MGLStyleFunctionOptionDefaultValue:@1.75}];
+
+ [self.mapView.style addLayer:layer];
+}
+
+- (void)animatePolyline {
+ _currentIndex = 1;
+
+ // Start a timer that will simulate adding points to our polyline. This could also represent coordinates being added to our polyline from another source, such as a CLLocationManagerDelegate.
+ _timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(tick) userInfo:nil repeats:YES];
+}
+
+- (void)tick {
+ if (_currentIndex > self.locations.count) {
+ [_timer invalidate];
+ _timer = nil;
+ return;
+ }
+
+ // Create a subarray of locations up to the current index.
+ NSArray *currentLocations = [self.locations subarrayWithRange:NSMakeRange(0, _currentIndex)];
+
+ // Update our MGLShapeSource with the current locations.
+ [self updatePolylineWithLocations:currentLocations];
+
+ _currentIndex++;
+}
+
+- (void)updatePolylineWithLocations:(NSArray<CLLocation *> *)locations {
+ CLLocationCoordinate2D coordinates[locations.count];
+
+ for (NSUInteger i = 0; i < locations.count; i++) {
+ coordinates[i] = locations[i].coordinate;
+ }
+
+ MGLPolylineFeature *polyline = [MGLPolylineFeature polylineWithCoordinates:coordinates count:locations.count];
+
+ // Updating the MGLShapeSource’s shape will have the map redraw our polyline with the current coordinates.
+ self.polylineSource.shape = polyline;
+}
+
+- (NSArray<CLLocation *> *)locations {
+ NSArray *coordinates = @[
+ @[@(-122.63748), @45.52214],
+ @[@(-122.64855), @45.52218],
+ @[@(-122.6545), @45.52219],
+ @[@(-122.65497), @45.52196],
+ @[@(-122.65631), @45.52104],
+ @[@(-122.6578), @45.51935],
+ @[@(-122.65867), @45.51848],
+ @[@(-122.65872), @45.51293],
+ @[@(-122.66576), @45.51295],
+ @[@(-122.66745), @45.51252],
+ @[@(-122.66813), @45.51244],
+ @[@(-122.67359), @45.51385],
+ @[@(-122.67415), @45.51406],
+ @[@(-122.67481), @45.51484],
+ @[@(-122.676), @45.51532],
+ @[@(-122.68106), @45.51668],
+ @[@(-122.68503), @45.50934],
+ @[@(-122.68546), @45.50858],
+ @[@(-122.6852), @45.50783],
+ @[@(-122.68424), @45.50714],
+ @[@(-122.68433), @45.50585],
+ @[@(-122.68429), @45.50521],
+ @[@(-122.68456), @45.50445],
+ @[@(-122.68538), @45.50371],
+ @[@(-122.68653), @45.50311],
+ @[@(-122.68731), @45.50292],
+ @[@(-122.68742), @45.50253],
+ @[@(-122.6867), @45.50239],
+ @[@(-122.68545), @45.5026],
+ @[@(-122.68407), @45.50294],
+ @[@(-122.68357), @45.50271],
+ @[@(-122.68236), @45.50055],
+ @[@(-122.68233), @45.49994],
+ @[@(-122.68267), @45.49955],
+ @[@(-122.68257), @45.49919],
+ @[@(-122.68376), @45.49842],
+ @[@(-122.68428), @45.49821],
+ @[@(-122.68573), @45.49798],
+ @[@(-122.68923), @45.49805],
+ @[@(-122.68926), @45.49857],
+ @[@(-122.68814), @45.49911],
+ @[@(-122.68865), @45.49921],
+ @[@(-122.6897), @45.49905],
+ @[@(-122.69346), @45.49917],
+ @[@(-122.69404), @45.49902],
+ @[@(-122.69438), @45.49796],
+ @[@(-122.69504), @45.49697],
+ @[@(-122.69624), @45.49661],
+ @[@(-122.69781), @45.4955],
+ @[@(-122.69803), @45.49517],
+ @[@(-122.69711), @45.49508],
+ @[@(-122.69688), @45.4948],
+ @[@(-122.69744), @45.49368],
+ @[@(-122.69702), @45.49311],
+ @[@(-122.69665), @45.49294],
+ @[@(-122.69788), @45.49212],
+ @[@(-122.69771), @45.49264],
+ @[@(-122.69835), @45.49332],
+ @[@(-122.7007), @45.49334],
+ @[@(-122.70167), @45.49358],
+ @[@(-122.70215), @45.49401],
+ @[@(-122.70229), @45.49439],
+ @[@(-122.70185), @45.49566],
+ @[@(-122.70215), @45.49635],
+ @[@(-122.70346), @45.49674],
+ @[@(-122.70517), @45.49758],
+ @[@(-122.70614), @45.49736],
+ @[@(-122.70663), @45.49736],
+ @[@(-122.70807), @45.49767],
+ @[@(-122.70807), @45.49798],
+ @[@(-122.70717), @45.49798],
+ @[@(-122.70713), @45.4984],
+ @[@(-122.70774), @45.49893],
+ ];
+
+ NSMutableArray<CLLocation *> *locations = [NSMutableArray array];
+ for (NSArray<NSNumber *> *c in coordinates) {
+ [locations addObject:[[CLLocation alloc] initWithLatitude:[c[1] doubleValue] longitude:[c[0] doubleValue]]];
+ }
+ return locations;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.h b/platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.h
new file mode 100644
index 0000000000..8bf17738ee
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.h
@@ -0,0 +1,13 @@
+//
+// RuntimeCircleStylesExample.h
+// Examples
+//
+// Created by Eric Wolfe on 11/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface RuntimeCircleStylesExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.m b/platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.m
new file mode 100644
index 0000000000..7d01692e6d
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeCircleStylesExample.m
@@ -0,0 +1,77 @@
+#import "RuntimeCircleStylesExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleRuntimeCircleStyles = @"RuntimeCircleStylesExample";
+
+@interface RuntimeCircleStylesExample () <MGLMapViewDelegate>
+
+@property (nonatomic) MGLMapView *mapView;
+
+@end
+
+@implementation RuntimeCircleStylesExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ [self.mapView setStyleURL:[MGLStyle lightStyleURLWithVersion:9]];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ self.mapView.tintColor = [UIColor darkGrayColor];
+
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(37.753574, -122.447303)
+ zoomLevel:10
+ animated:NO];
+
+ [self.view addSubview:self.mapView];
+
+ self.mapView.delegate = self;
+}
+
+// Wait until the style is loaded before modifying the map style.
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ [self addLayer];
+}
+
+- (void)addLayer {
+ MGLSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"population" configurationURL:[NSURL URLWithString:@"mapbox://examples.8fgz4egr"]];
+
+ NSDictionary *ethnicities = @{
+ @"White": [UIColor colorWithRed: 251/255.0 green: 176/255.0 blue: 59/255.0 alpha: 1.0],
+ @"Black": [UIColor colorWithRed: 34/255.0 green: 59/255.0 blue: 83/255.0 alpha: 1.0],
+ @"Hispanic": [UIColor colorWithRed: 229/255.0 green: 94/255.0 blue: 94/255.0 alpha: 1.0],
+ @"Asian": [UIColor colorWithRed: 59/255.0 green: 178/255.0 blue: 208/255.0 alpha: 1.0],
+ @"Other": [UIColor colorWithRed: 204/255.0 green: 204/255.0 blue: 204/255.0 alpha: 1.0],
+ };
+
+
+ [self.mapView.style addSource:source];
+
+ // Create a new layer for each ethnicity/circle color.
+ for (NSString *key in [ethnicities allKeys]) {
+ // Each layer should have a unique identifier.
+ MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:[NSString stringWithFormat:@"population-%@", key] source:source];
+
+ // Specifying the `sourceLayerIdentifier` is required for a vector tile source. This is the json attribute that wraps the data in the source.
+ layer.sourceLayerIdentifier = @"sf2010";
+
+ // Use a style function to smoothly adjust the circle radius from 2pt to 180pt between zoom levels 12 and 22. The `interpolationBase` parameter allows the values to interpolate along an exponential curve.
+ layer.circleRadius = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:@{
+ @12: [MGLStyleValue valueWithRawValue:@2],
+ @22: [MGLStyleValue valueWithRawValue:@180]
+ }
+ options: @{MGLStyleFunctionOptionDefaultValue:@1.75}];
+ layer.circleOpacity = [MGLStyleValue valueWithRawValue:@0.7];
+
+ // Set the circle color to match the ethnicity.
+ layer.circleColor = [MGLStyleValue valueWithRawValue:ethnicities[key]];
+
+ // Use an NSPredicate to filter to just one ethnicity for this layer.
+ layer.predicate = [NSPredicate predicateWithFormat:@"ethnicity == %@", key];
+
+ [self.mapView.style addLayer:layer];
+ }
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.h b/platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.h
new file mode 100644
index 0000000000..306c6f107a
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.h
@@ -0,0 +1,13 @@
+//
+// RuntimeMultipleAnnotationsExample.h
+// Examples
+//
+// Created by Eric Wolfe on 12/2/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface RuntimeMultipleAnnotationsExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.m b/platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.m
new file mode 100644
index 0000000000..4c4308cd3c
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeMultipleAnnotationsExample.m
@@ -0,0 +1,216 @@
+#import "RuntimeMultipleAnnotationsExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleRuntimeMultipleAnnotations = @"RuntimeMultipleAnnotationsExample";
+
+@interface RuntimeMultipleAnnotationsExample ()<MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@end
+
+@implementation RuntimeMultipleAnnotationsExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(37.090240, -95.712891) zoomLevel:2 animated:NO];
+
+ mapView.delegate = self;
+
+ // Add our own gesture recognizer to handle taps on our custom map features.
+ [mapView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapTap:)]];
+
+ [self.view addSubview:mapView];
+
+ self.mapView = mapView;
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ [self fetchPoints:^(NSArray *features) {
+ [self addItemsToMap:features];
+ }];
+}
+
+- (void)addItemsToMap:(NSArray *)features {
+ // You can add custom UIImages to the map style.
+ // These can be referenced by an MGLSymbolStyleLayer’s iconImage property.
+ [self.mapView.style setImage:[UIImage imageNamed:@"lighthouse"] forName:@"lighthouse"];
+
+ // Add the features to the map as a MGLShapeSource.
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"lighthouses" features:features options:nil];
+ [self.mapView.style addSource:source];
+
+ UIColor *lighthouseColor = [UIColor colorWithRed:0.08 green:0.44 blue:0.96 alpha:1.0];
+
+ // Use MGLCircleStyleLayer to represent the points with simple circles.
+ // In this case, we can use style functions to gradually change properties between zoom level 2 and 7: the circle opacity from 50% to 100% and the circle radius from 2pt to 3pt.
+ MGLCircleStyleLayer *circles = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"lighthouse-circles" source:source];
+ circles.circleColor = [MGLStyleValue valueWithRawValue:lighthouseColor];
+ circles.circleOpacity = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:@{
+ @2: [MGLStyleValue valueWithRawValue:@0.5],
+ @7: [MGLStyleValue valueWithRawValue:@1.0]
+ }
+ options:@{MGLStyleFunctionOptionDefaultValue:[MGLStyleValue valueWithRawValue:@0.75]}];
+
+ circles.circleRadius = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeInterval
+ cameraStops:@{
+ @2: [MGLStyleValue valueWithRawValue:@2],
+ @7: [MGLStyleValue valueWithRawValue:@3]
+ }
+ options:@{MGLStyleFunctionOptionDefaultValue:@1}];
+
+ // Use MGLSymbolStyleLayer for more complex styling of points including custom icons and text rendering.
+ MGLSymbolStyleLayer *symbols = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"lighthouse-symbols" source:source];
+ symbols.iconImageName = [MGLStyleValue valueWithRawValue:@"lighthouse"];
+ symbols.iconScale = [MGLStyleValue valueWithRawValue:@0.5];
+ symbols.iconOpacity = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:@{
+ @5.9: [MGLStyleValue valueWithRawValue:@0],
+ @6: [MGLStyleValue valueWithRawValue:@1],
+ }
+ options:nil];
+ symbols.iconHaloColor = [MGLStyleValue valueWithRawValue:[[UIColor whiteColor] colorWithAlphaComponent:0.5]];
+ symbols.iconHaloWidth = [MGLStyleValue valueWithRawValue:@1];
+ // {name} references the "name" key in an MGLPointFeature’s attributes dictionary.
+ symbols.text = [MGLStyleValue valueWithRawValue:@"{name}"];
+ symbols.textColor = symbols.iconColor;
+ symbols.textFontSize = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:@{
+ @10: [MGLStyleValue valueWithRawValue:@10],
+ @16: [MGLStyleValue valueWithRawValue:@16],
+ }
+ options:nil];
+ symbols.textTranslation = [MGLStyleValue valueWithRawValue:[NSValue valueWithCGVector:CGVectorMake(10, 0)]];
+ symbols.textOpacity = symbols.iconOpacity;
+ symbols.textHaloColor = symbols.iconHaloColor;
+ symbols.textHaloWidth = symbols.iconHaloWidth;
+ symbols.textJustification = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLTextJustification:MGLTextJustificationLeft]];
+ symbols.textAnchor = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLTextAnchor:MGLTextAnchorLeft]];
+
+ [self.mapView.style addLayer:circles];
+ [self.mapView.style addLayer:symbols];
+}
+
+#pragma mark - Feature interaction
+
+- (void)handleMapTap:(UITapGestureRecognizer *)sender {
+ if (sender.state == UIGestureRecognizerStateEnded) {
+ // Limit feature selection to just the following layer identifiers.
+ NSArray *layerIdentifiers = @[@"lighthouse-symbols", @"lighthouse-circles"];
+
+ CGPoint point = [sender locationInView:sender.view];
+
+ // Try matching the exact point first
+ for (id f in [self.mapView visibleFeaturesAtPoint:point inStyleLayersWithIdentifiers:[NSSet setWithArray:layerIdentifiers]]) {
+ if ([f isKindOfClass:[MGLPointFeature class]]) {
+ [self showCallout:f];
+ return;
+ }
+ }
+
+ // Otherwise, get first features within a rect the size of a touch (44x44).
+ CGRect pointRect = {point, CGSizeZero};
+ CGRect touchRect = CGRectInset(pointRect, -22.0, -22.0);
+ for (id f in [self.mapView visibleFeaturesInRect:touchRect inStyleLayersWithIdentifiers:[NSSet setWithArray:layerIdentifiers]]) {
+ if ([f isKindOfClass:[MGLPointFeature class]]) {
+ [self showCallout:f];
+ return;
+ }
+ }
+
+ // If no features were found, deselect the selected annotation, if any.
+ [self.mapView deselectAnnotation:[[self.mapView selectedAnnotations] firstObject] animated:YES];
+ }
+}
+
+- (void)showCallout:(MGLPointFeature *)feature {
+ MGLPointFeature *point = [[MGLPointFeature alloc] init];
+ point.title = feature.attributes[@"name"];
+ point.coordinate = feature.coordinate;
+
+ // Selecting an feature that doesn’t already exist on the map will add a new annotation view.
+ // We’ll need to use the map’s delegate methods to add an empty annotation view and remove it when we’re done selecting it.
+ [self.mapView selectAnnotation:point animated:YES];
+}
+
+#pragma mark - MGLMapViewDelegate
+
+- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id <MGLAnnotation>)annotation {
+ return YES;
+}
+
+- (void)mapView:(MGLMapView *)mapView didDeselectAnnotation:(id <MGLAnnotation>)annotation {
+ [mapView removeAnnotation:annotation];
+}
+
+- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id <MGLAnnotation>)annotation {
+ // Create an empty view annotation. Set a frame to offset the callout.
+ return [[MGLAnnotationView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
+}
+
+#pragma mark - Data fetching and parsing
+
+- (void)fetchPoints:(void (^)(NSArray *))completion {
+ // Wikidata query for all lighthouses in the United States: http://tinyurl.com/zrl2jc4
+ NSString *query = @"SELECT DISTINCT ?item "
+ "?itemLabel ?coor ?image "
+ "WHERE "
+ "{ "
+ "?item wdt:P31 wd:Q39715 . "
+ "?item wdt:P17 wd:Q30 . "
+ "?item wdt:P625 ?coor . "
+ "OPTIONAL { ?item wdt:P18 ?image } . "
+ "SERVICE wikibase:label { bd:serviceParam wikibase:language \"en\" } "
+ "} "
+ "ORDER BY ?itemLabel";
+
+ NSMutableCharacterSet *characterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
+ [characterSet removeCharactersInString:@"?"];
+ [characterSet removeCharactersInString:@"&"];
+ [characterSet removeCharactersInString:@":"];
+
+ NSString *encodedQuery = [query stringByAddingPercentEncodingWithAllowedCharacters:characterSet];
+
+ NSString *urlString = [NSString stringWithFormat:@"https://query.wikidata.org/sparql?query=%@&format=json", encodedQuery];
+
+ [[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:urlString] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
+ if (!data) return;
+
+ NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+ NSArray *items = json[@"results"][@"bindings"];
+
+ if (!items) return;
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion([self parseJSONItems:items]);
+ });
+ }] resume];
+}
+
+- (NSArray *)parseJSONItems:(NSArray *)items {
+ NSMutableArray *features = [NSMutableArray array];
+ for (NSDictionary *item in items) {
+ NSString *title = item[@"itemLabel"][@"value"];
+ NSString *point = item[@"coor"][@"value"];
+ if (!item || !point) continue;
+
+ NSString *parsedPoint = [[point stringByReplacingOccurrencesOfString:@"Point(" withString:@""] stringByReplacingOccurrencesOfString:@")" withString:@""];
+ NSArray *pointComponents = [parsedPoint componentsSeparatedByString:@" "];
+
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ feature.coordinate = CLLocationCoordinate2DMake([pointComponents[1] doubleValue], [pointComponents[0] doubleValue]);
+ feature.title = title;
+ // A feature’s attributes can used by runtime styling for things like text labels.
+ feature.attributes = @{
+ @"name": title,
+ };
+ [features addObject:feature];
+ }
+ return features;
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.h b/platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.h
new file mode 100644
index 0000000000..d5b8b61bf9
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.h
@@ -0,0 +1,13 @@
+//
+// RuntimeToggleLayerExample.h
+// Examples
+//
+// Created by Eric Wolfe on 11/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface RuntimeToggleLayerExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.m b/platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.m
new file mode 100644
index 0000000000..9f61c11d7a
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/RuntimeToggleLayerExample.m
@@ -0,0 +1,92 @@
+#import "RuntimeToggleLayerExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleRuntimeToggleLayer = @"RuntimeToggleLayerExample";
+
+@interface RuntimeToggleLayerExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) MGLStyleLayer *contoursLayer;
+@end
+
+@implementation RuntimeToggleLayerExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map's center coordinate
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(37.745395, -119.594421)
+ zoomLevel:11
+ animated:NO];
+
+ [self.view addSubview:self.mapView];
+
+ [self addToggleButton];
+
+ // Set the delegate property of our map view to self after instantiating it
+ self.mapView.delegate = self;
+}
+
+// Wait until the style is loaded before modifying the map style
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ [self addLayer];
+}
+
+- (void)addLayer {
+ MGLSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"contours" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+
+ MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"contours" source:source];
+ layer.sourceLayerIdentifier = @"contour";
+ layer.lineJoin = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinRound]];
+ layer.lineCap = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapRound]];
+ layer.lineColor = [MGLStyleValue valueWithRawValue:[UIColor brownColor]];
+ layer.lineWidth = [MGLStyleValue valueWithRawValue:@1];
+
+ [self.mapView.style addSource:source];
+
+ MGLStyleLayer *waterLayer = [self.mapView.style layerWithIdentifier:@"water"];
+ if (waterLayer != nil) {
+ // You can insert a layer below an existing style layer
+ [self.mapView.style insertLayer:layer belowLayer:waterLayer];
+ } else {
+ // or you can simply add it above all layers
+ [self.mapView.style addLayer:layer];
+ }
+
+ self.contoursLayer = layer;
+
+ [self showContours];
+}
+
+- (void)toggleLayer:(UIButton *)sender {
+ sender.selected = !sender.selected;
+ if (sender.selected) {
+ [self showContours];
+ } else {
+ [self hideContours];
+ }
+}
+
+- (void)showContours {
+ [self.contoursLayer setVisible:YES];
+}
+
+- (void)hideContours {
+ [self.contoursLayer setVisible:NO];
+}
+
+- (void)addToggleButton {
+ UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
+ button.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
+ [button setTitle:@"Toggle Contours" forState:UIControlStateNormal];
+ [button setSelected:YES];
+ [button sizeToFit];
+ button.center = CGPointMake(self.view.center.x, 0);
+ button.frame = CGRectMake(button.frame.origin.x, self.view.frame.size.height - button.frame.size.height - 5, button.frame.size.width, button.frame.size.height);
+ [button addTarget:self action:@selector(toggleLayer:) forControlEvents:UIControlEventTouchUpInside];
+ [self.view addSubview:button];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.h b/platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.h
new file mode 100644
index 0000000000..1aa0390bc8
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.h
@@ -0,0 +1,13 @@
+//
+// SatelliteStyleExample.h
+// Examples
+//
+// Created by Jason Wray on 1/29/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface SatelliteStyleExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.m b/platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.m
new file mode 100644
index 0000000000..dee1b0ab5d
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SatelliteStyleExample.m
@@ -0,0 +1,28 @@
+#import "SatelliteStyleExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleSatelliteStyle = @"SatelliteStyleExample";
+
+@implementation SatelliteStyleExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // A hybrid style with unobtrusive labels is also available via +satelliteStreetsStyleURLWithVersion:.
+ NSURL *styleURL = [MGLStyle satelliteStyleURLWithVersion:9];
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:styleURL];
+
+ // Tint the ℹ️ button.
+ mapView.attributionButton.tintColor = [UIColor whiteColor];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map’s center coordinate and zoom level.
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.5188, -122.6748)
+ zoomLevel:13
+ animated:NO];
+
+ [self.view addSubview:mapView];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.h b/platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.h
new file mode 100644
index 0000000000..b441514711
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.h
@@ -0,0 +1,13 @@
+//
+// SelectFeatureExample.h
+// Examples
+//
+// Created by Eric Wolfe on 12/2/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface SelectFeatureExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.m b/platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.m
new file mode 100644
index 0000000000..c3f5dd971d
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SelectFeatureExample.m
@@ -0,0 +1,71 @@
+#import "SelectFeatureExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleSelectFeature = @"SelectFeatureExample";
+
+@interface SelectFeatureExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) MGLShapeSource *selectedFeaturesSource;
+@end
+
+@implementation SelectFeatureExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.5076, -122.6736)
+ zoomLevel:11
+ animated:NO];
+
+ // Add our own gesture recognizer to handle taps on our custom map features
+ [mapView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapMap:)]];
+
+ mapView.delegate = self;
+
+ [self.view addSubview:mapView];
+
+ self.mapView = mapView;
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ // Create a placeholder MGLShapeSource that will hold copies of any features we’ve selected.
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"selected-features" features:@[] options:nil];
+ [style addSource:source];
+
+ // Keep a reference to the source so we can update it when the map is tapped.
+ self.selectedFeaturesSource = source;
+
+ // Color any selected features red on the map.
+ MGLFillStyleLayer *selectedFeaturesLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"selected-features" source:source];
+ selectedFeaturesLayer.fillColor = [MGLStyleValue valueWithRawValue:[UIColor redColor]];
+
+ [style addLayer:selectedFeaturesLayer];
+}
+
+- (void)didTapMap:(UITapGestureRecognizer *)recognizer {
+ if (recognizer.state == UIGestureRecognizerStateEnded) {
+ // A tap’s center coordinate may not intersect a feature exactly, so let’s make a 44x44 rect that represents a touch and select all features that interesect.
+ CGRect pointRect = { [recognizer locationInView:recognizer.view], CGSizeZero };
+ CGRect touchRect = CGRectInset(pointRect, -22.0, -22.0);
+
+ // Let’s only select parks near the rect. There’s a layer within the Mapbox Streets style with "id" = "park". You can see all of the layers used within the default mapbox styles by creating a new style using Mapbox Studio.
+ NSSet *layerIdentifiers = [NSSet setWithObject:@"park"];
+
+ // Query the current mapview for any features that intersect our rect.
+ NSMutableArray *features = [NSMutableArray array];
+ for (id f in [self.mapView visibleFeaturesInRect:touchRect inStyleLayersWithIdentifiers:layerIdentifiers]) {
+ [features addObject:f];
+ }
+
+ MGLShapeCollectionFeature *shapes = [MGLShapeCollectionFeature shapeCollectionWithShapes:features];
+
+ // Update our MGLShapeSource to match our selected features.
+ self.selectedFeaturesSource.shape = shapes;
+ }
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.h b/platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.h
new file mode 100644
index 0000000000..ea6f9b46c1
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.h
@@ -0,0 +1,13 @@
+//
+// ShapeCollectionFeatureExample.h
+// Examples
+//
+// Created by Nadia Barbosa on 3/7/17.
+// Copyright © 2017 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ShapeCollectionFeatureExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.m b/platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.m
new file mode 100644
index 0000000000..3ca7467f9c
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/ShapeCollectionFeatureExample.m
@@ -0,0 +1,68 @@
+#import "ShapeCollectionFeatureExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleShapeCollectionFeature = @"ShapeCollectionFeatureExample";
+
+@interface ShapeCollectionFeatureExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@end
+
+@implementation ShapeCollectionFeatureExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:[MGLStyle lightStyleURLWithVersion:9]];
+ self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ self.mapView.tintColor = [UIColor darkGrayColor];
+
+ [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(38.897435, -77.039679) zoomLevel:12 animated:NO];
+ self.mapView.delegate = self;
+
+ [self.view addSubview:self.mapView];
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+
+ // Parse the GeoJSON data.
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ NSString *path = [[NSBundle mainBundle] pathForResource:@"metro-line" ofType:@"geojson"];
+
+ NSData *data = [NSData dataWithContentsOfFile:path];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self drawShapeCollection:data];
+ });
+ });
+}
+
+- (void)drawShapeCollection:(NSData *)data {
+
+ // Use [MGLShape shapeWithData:encoding:error:] to create a MGLShapeCollectionFeature from GeoJSON data.
+ MGLShape *feature = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:NULL];
+
+ // Create source and add it to the map style.
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"transit" shape:feature options:nil];
+ [self.mapView.style addSource:source];
+
+ // Create station style layer.
+ MGLCircleStyleLayer *circleLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"stations" source:source];
+ circleLayer.predicate = [NSPredicate predicateWithFormat:@"TYPE = 'Station'"];
+ circleLayer.circleColor = [MGLStyleValue valueWithRawValue:[UIColor redColor]];
+ circleLayer.circleRadius = [MGLStyleValue valueWithRawValue:@6];
+ circleLayer.circleStrokeWidth = [MGLStyleValue valueWithRawValue:@2];
+ circleLayer.circleStrokeColor = [MGLStyleValue valueWithRawValue:[UIColor blackColor]];
+
+ // Create line style layer.
+ MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"rail-line" source: source];
+ lineLayer.predicate = [NSPredicate predicateWithFormat:@"TYPE = 'Rail line'"];
+ lineLayer.lineColor = [MGLStyleValue valueWithRawValue:[UIColor redColor]];
+ lineLayer.lineWidth = [MGLStyleValue valueWithRawValue:@2];
+
+ // Add style layers to the map view's style.
+ [self.mapView.style addLayer:circleLayer];
+ [self.mapView.style insertLayer:lineLayer belowLayer:circleLayer];
+}
+
+@end
+
diff --git a/platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.h b/platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.h
new file mode 100644
index 0000000000..b137216a1c
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.h
@@ -0,0 +1,13 @@
+//
+// SimpleMapViewExample.h
+// Examples
+//
+// Created by Jason Wray on 1/26/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface SimpleMapViewExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.m b/platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.m
new file mode 100644
index 0000000000..9d16978baa
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SimpleMapViewExample.m
@@ -0,0 +1,23 @@
+#import "SimpleMapViewExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleSimpleMapView = @"SimpleMapViewExample";
+
+@implementation SimpleMapViewExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ // Set the map’s center coordinate and zoom level.
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(59.31, 18.06)
+ zoomLevel:9
+ animated:NO];
+
+ [self.view addSubview:mapView];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.h b/platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.h
new file mode 100644
index 0000000000..d82f39a791
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.h
@@ -0,0 +1,13 @@
+//
+// SourceCustomRasterExample.h
+// Examples
+//
+// Created by Eric Wolfe on 12/2/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface SourceCustomRasterExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.m b/platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.m
new file mode 100644
index 0000000000..b17bac3282
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SourceCustomRasterExample.m
@@ -0,0 +1,58 @@
+#import "SourceCustomRasterExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleSourceCustomRaster = @"SourceCustomRasterExample";
+
+@interface SourceCustomRasterExample () <MGLMapViewDelegate>
+@property (nonatomic) MGLRasterStyleLayer *rasterLayer;
+@end
+
+@implementation SourceCustomRasterExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(45.5188, -122.6748)
+ zoomLevel:13
+ animated:NO];
+
+ mapView.delegate = self;
+
+ [self.view addSubview:mapView];
+
+ // Add a UISlider that will control the raster layer’s opacity.
+ [self addSlider];
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ // Add a new raster source and layer.
+ MGLRasterSource *source = [[MGLRasterSource alloc] initWithIdentifier:@"stamen-watercolor"
+ tileURLTemplates:@[@"https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg"]
+ options:@{ MGLTileSourceOptionTileSize: @256}];
+ MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"stamen-watercolor" source:source];
+
+ [mapView.style addSource:source];
+ [mapView.style addLayer:rasterLayer];
+
+ self.rasterLayer = rasterLayer;
+}
+
+- (void)updateLayerOpacity:(UISlider *)sender {
+ [self.rasterLayer setRasterOpacity:[MGLStyleValue valueWithRawValue:@(sender.value)]];
+}
+
+- (void)addSlider {
+ CGFloat padding = 10.0;
+ UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(padding, self.view.frame.size.height - 44 - 30, self.view.frame.size.width - padding * 2, 44)];
+ slider.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
+ slider.minimumValue = 0;
+ slider.maximumValue = 1;
+ slider.value = 1;
+ [slider addTarget:self action:@selector(updateLayerOpacity:) forControlEvents:UIControlEventValueChanged];
+ [self.view addSubview:slider];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.h b/platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.h
new file mode 100644
index 0000000000..26af594a0b
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.h
@@ -0,0 +1,13 @@
+//
+// SourceCustomVectorExample.h
+// Examples
+//
+// Created by Eric Wolfe on 12/2/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface SourceCustomVectorExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.m b/platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.m
new file mode 100644
index 0000000000..069aa4ee26
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/SourceCustomVectorExample.m
@@ -0,0 +1,24 @@
+#import "SourceCustomVectorExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleSourceCustomVector = @"SourceCustomVectorExample";
+
+@implementation SourceCustomVectorExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Third party vector tile sources can be added.
+
+ // In this case we're using custom style JSON (https://www.mapbox.com/mapbox-gl-style-spec/) to add a third party tile source: <https://vector.mapzen.com/osm/all/{z}/{x}/{y}.mvt>
+ NSURL *customStyleURL = [[NSBundle mainBundle] URLForResource:@"third_party_vector_style" withExtension:@"json"];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:customStyleURL];
+
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ mapView.tintColor = [UIColor whiteColor];
+
+ [self.view addSubview:mapView];
+}
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.h b/platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.h
new file mode 100644
index 0000000000..bde94c6a13
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.h
@@ -0,0 +1,13 @@
+//
+// UserTrackingModesExample.h
+// Examples
+//
+// Created by Jason Wray on 6/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UserTrackingModesExample : UIViewController
+
+@end
diff --git a/platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.m b/platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.m
new file mode 100644
index 0000000000..621727128a
--- /dev/null
+++ b/platform/ios/demo/Examples/ObjectiveC/UserTrackingModesExample.m
@@ -0,0 +1,25 @@
+#import "UserTrackingModesExample.h"
+@import Mapbox;
+
+NSString *const MBXExampleUserTrackingModes = @"UserTrackingModesExample";
+
+@implementation UserTrackingModesExample
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:[MGLStyle darkStyleURLWithVersion:9]];
+ mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ mapView.userTrackingMode = MGLUserTrackingModeFollowWithHeading;
+
+ // The user location annotation takes its color from the map view tint.
+ mapView.tintColor = [UIColor redColor];
+
+ // You can set the attribution button tint separately.
+ mapView.attributionButton.tintColor = [UIColor lightGrayColor];
+
+ [self.view addSubview:mapView];
+}
+
+@end