Skip to content
This repository has been archived by the owner on Jun 14, 2024. It is now read-only.

Add change worldview boundaries example #382

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
3EC92DB71E78C431001D0503 /* metro-line.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 3EC92DB61E78C431001D0503 /* metro-line.geojson */; };
3ED403411E006B5200230C95 /* CameraFlyToExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ED403401E006B5200230C95 /* CameraFlyToExample.swift */; };
3ED403481E006BE800230C95 /* CameraFlyToExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 3ED403471E006BE800230C95 /* CameraFlyToExample.m */; };
583C02ED23A0B305005393D8 /* ChangeWorldviewBoundariesExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583C02EC23A0B305005393D8 /* ChangeWorldviewBoundariesExample.swift */; };
583C02EF23A0B3E5005393D8 /* ChangeWorldviewBoundaries.m in Sources */ = {isa = PBXBuildFile; fileRef = 583C02EE23A0B3E5005393D8 /* ChangeWorldviewBoundaries.m */; };
60E0DCA0CEED683C3A4F18F2 /* Pods_Examples.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EC12D8F1A97963D68BFA871 /* Pods_Examples.framework */; };
646B62971DEF6DAF000AA523 /* ShowHideLayerExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 646B62961DEF6DAF000AA523 /* ShowHideLayerExample.swift */; };
646B629C1DEF6DF1000AA523 /* ShowHideLayerExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 646B629B1DEF6DF1000AA523 /* ShowHideLayerExample.m */; };
Expand Down Expand Up @@ -269,6 +271,9 @@
3ED403461E006BE800230C95 /* CameraFlyToExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CameraFlyToExample.h; sourceTree = "<group>"; };
3ED403471E006BE800230C95 /* CameraFlyToExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraFlyToExample.m; sourceTree = "<group>"; };
532FB53EE0142E4DAC3FB49B /* Pods-Shared-Examples.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shared-Examples.release.xcconfig"; path = "Pods/Target Support Files/Pods-Shared-Examples/Pods-Shared-Examples.release.xcconfig"; sourceTree = "<group>"; };
583C02EC23A0B305005393D8 /* ChangeWorldviewBoundariesExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeWorldviewBoundariesExample.swift; sourceTree = "<group>"; };
583C02EE23A0B3E5005393D8 /* ChangeWorldviewBoundaries.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChangeWorldviewBoundaries.m; sourceTree = "<group>"; };
583C02F023A0B6E0005393D8 /* ChangeWorldviewBoundaries.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChangeWorldviewBoundaries.h; sourceTree = "<group>"; };
589ABF8859560819F8B431C7 /* Pods-ExamplesTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExamplesTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ExamplesTests/Pods-ExamplesTests.debug.xcconfig"; sourceTree = "<group>"; };
646B62961DEF6DAF000AA523 /* ShowHideLayerExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShowHideLayerExample.swift; sourceTree = "<group>"; };
646B629B1DEF6DF1000AA523 /* ShowHideLayerExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowHideLayerExample.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -451,6 +456,7 @@
05536CB4200F9EEB00657097 /* SwitchStylesExample.swift */,
64CF970F1DF224E400C3C27B /* ThirdPartyVectorStyleExample.swift */,
1F070160225556FA0045E061 /* MissingIconsExample.swift */,
583C02EC23A0B305005393D8 /* ChangeWorldviewBoundariesExample.swift */,
);
name = "Map styles";
sourceTree = "<group>";
Expand Down Expand Up @@ -545,6 +551,7 @@
9691AAA21C5AAD8F006A58C6 /* StudioStyleExample.m */,
05536CB1200F9B0900657097 /* SwitchStylesExample.m */,
05FA53951FE2F9FE001F3D7D /* ThirdPartyVectorStyleExample.m */,
583C02EE23A0B3E5005393D8 /* ChangeWorldviewBoundaries.m */,
);
name = "Map styles";
sourceTree = "<group>";
Expand Down Expand Up @@ -810,6 +817,7 @@
3E18060E1EAA800A004DB131 /* UserLocationAnnotationExample.h */,
969E7FDB1D25C31700663F84 /* UserTrackingModesExample.h */,
64BBDAFB1DF24DD700BB705D /* WebAPIDataExample.h */,
583C02F023A0B6E0005393D8 /* ChangeWorldviewBoundaries.h */,
);
path = Headers;
sourceTree = "<group>";
Expand Down Expand Up @@ -1354,6 +1362,7 @@
3ED403481E006BE800230C95 /* CameraFlyToExample.m in Sources */,
3EBCD71D1DC28240001E342F /* StudioClassicStyleExample.swift in Sources */,
646B62B01DEF7161000AA523 /* AnimatedLineExample.swift in Sources */,
583C02ED23A0B305005393D8 /* ChangeWorldviewBoundariesExample.swift in Sources */,
3E52ACD31EE8D8AF0056242C /* LiveDataExample.m in Sources */,
3EA5AA041FAD2EC7007073C0 /* StaticSnapshotExample.swift in Sources */,
05FA53A91FE2FB46001F3D7D /* CustomCalloutView.m in Sources */,
Expand Down Expand Up @@ -1394,6 +1403,7 @@
A42F4A5122EF9ACD005097F3 /* CacheManagementExample.swift in Sources */,
05FA53A11FE2FA1E001F3D7D /* PolygonPatternExample.m in Sources */,
0774A77423394B750038264E /* ShapeAnnotationsExample.m in Sources */,
583C02EF23A0B3E5005393D8 /* ChangeWorldviewBoundaries.m in Sources */,
3E3FB66E1F0588B3004512C6 /* BuildingLightExample.m in Sources */,
968247271C5C1DC700494AB8 /* CameraAnimationExample.m in Sources */,
CA39B2BF209B881300D37037 /* BuildingLightExample+UITesting.m in Sources */,
Expand Down
1 change: 1 addition & 0 deletions Examples/Examples.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extern NSString *const MBXExampleBlockingGesturesDelegate;
extern NSString *const MBXExampleBuildingLight;
extern NSString *const MBXExampleCameraAnimation;
extern NSString *const MBXExampleCameraFlyTo;
extern NSString *const MBXExampleChangeWorldviewBoundaries;
extern NSString *const MBXExampleClustering;
extern NSString *const MBXExampleClusteringWithImages;
extern NSString *const MBXExampleCustomCalloutView;
Expand Down
2 changes: 2 additions & 0 deletions Examples/Examples.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ + (NSArray *)groups {
@{@"className": MBXExampleThirdPartyVectorStyle, @"title": @"Use third-party vector tiles"},
@{@"className": MBXExampleSwitchStyles, @"title": @"Switch between map styles"},
@{@"className": MBXExampleCameraFlyTo, @"title": @"Camera fly to"},
@{@"className": MBXExampleChangeWorldviewBoundaries, @"title": @"Adjust administrative boundaries"},

]
},
@{
Expand Down
95 changes: 95 additions & 0 deletions Examples/ObjectiveC/ChangeWorldviewBoundaries.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#import "ChangeWorldviewBoundaries.h"

@import Mapbox;

NSString *const MBXExampleChangeWorldviewBoundaries = @"ChangeWorldviewBoundariesExample";

@interface ChangeWorldviewBoundariesExample ()

@property (nonatomic) MGLMapView *mapView;
@property MGLLineStyleLayer *layer;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change


@end

@implementation ChangeWorldviewBoundariesExample

- (void)viewDidLoad {
[super viewDidLoad];

self.mapView = [[MGLMapView alloc] initWithFrame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

// Set the map's initial style, center coordinate, and zoom level
self.mapView.styleURL = [MGLStyle lightStyleURL];
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(25.251, 95.69)
zoomLevel:3
animated:NO];
[self.view addSubview:self.mapView];

// Create a UISegmentedControl to toggle between map styles
UISegmentedControl *styleToggle =[[UISegmentedControl alloc] initWithItems:@[@" US ", @" CN ", @" IN ", @" All "]];
styleToggle.translatesAutoresizingMaskIntoConstraints = NO;
styleToggle.tintColor = [UIColor colorWithRed:0.976f green:0.843f blue:0.831f alpha:1];
styleToggle.backgroundColor = [UIColor colorWithRed:0.721f green:0.804f blue:0.831f alpha:1];
styleToggle.layer.cornerRadius = 4;
styleToggle.clipsToBounds = YES;
[self.view insertSubview:styleToggle aboveSubview:self.mapView];
[styleToggle addTarget:self action:@selector(changeStyle:) forControlEvents:UIControlEventValueChanged];

// Configure autolayout constraints for the UISegmentedControl to align
// at the bottom of the map view and above the Mapbox logo and attribution
NSMutableArray *constraints = [NSMutableArray array];

[constraints addObject:[NSLayoutConstraint constraintWithItem:styleToggle attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.mapView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:1.0]];
[constraints addObject:[NSLayoutConstraint constraintWithItem:styleToggle attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.mapView.logoView attribute:NSLayoutAttributeTop multiplier:1 constant:-20]];

[self.view addConstraints:constraints];
}

// Change the map style based on the selected index of the UISegmentedControl
- (void)changeStyle:(UISegmentedControl *)sender {

MGLStyle *style = self.mapView.style;

MGLVectorTileSource *source = [[MGLVectorTileSource alloc] initWithIdentifier:@"admin-bounds" configurationURL: [NSURL URLWithString:@"mapbox://mapbox.mapbox-streets-v8"]];

if ([_layer.identifier isEqual: @"admin"]) {
printf("source already exists");
[style removeLayer:_layer];

} else {
_layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"admin" source:source];
[style addSource:source];
}
_layer.sourceLayerIdentifier = @"admin";
_layer.lineColor = [NSExpression expressionForConstantValue: UIColor.lightGrayColor];

switch(sender.selectedSegmentIndex){
case 0:
printf("US");
_layer.predicate = [ NSPredicate predicateWithFormat: @"CAST(worldview, 'NSString') == 'US'"];
[style addLayer:_layer];
break;
case 1:
printf("CN");
_layer.predicate = [ NSPredicate predicateWithFormat: @"CAST(worldview, 'NSString') == 'CN'"];
[style addLayer:_layer];
break;
case 2:
printf("IN");
_layer.predicate = [ NSPredicate predicateWithFormat: @"CAST(worldview, 'NSString') == 'IN'"];
[style addLayer:_layer];
break;
case 3:
printf("All");
_layer.predicate = [ NSPredicate predicateWithFormat: @"CAST(worldview, 'NSString') == 'all'"];
[style addLayer:_layer];
break;
default:
[style addLayer:_layer];
break;
}
}

@end
14 changes: 14 additions & 0 deletions Examples/ObjectiveC/Headers/ChangeWorldviewBoundaries.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// ChangeWorldviewBoundaries.h
// Examples
//
// Created by ZiZi Miles on 12/11/19.
// Copyright © 2019 Mapbox. All rights reserved.
//

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default we remove these comments for new files.

#import <UIKit/UIKit.h>

@interface ChangeWorldviewBoundariesExample : UIViewController

@end

76 changes: 76 additions & 0 deletions Examples/Swift/ChangeWorldviewBoundariesExample.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import UIKit
import Mapbox

@objc(ChangeWorldviewBoundariesExample_Swift)

class ChangeWorldviewBoundariesExample: UIViewController, MGLMapViewDelegate {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The view controller is conforming to the MGLMapViewDelegate protocol but is not using any of its associated delegate methods (yet).


let mapView = MGLMapView()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can take care of the map view's initialization and style setting in one shot with this initializer:

MGLMapView(frame: CGRect, styleURL: MGLStyleURL)

I recommend doing this in viewDidLoad.

let source = MGLVectorTileSource(identifier: "admin-bounds", configurationURL: NSURL(string: "mapbox://mapbox.mapbox-streets-v8")! as URL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this source is already included in Mapbox Light by default, you can access it instead with MGLStyle.source(identifier: String), which returns an optional MGLSource, instead of declaring a new source.

var adminLayers = [String]()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adminLayers is declared here but not used.

var layer: MGLLineStyleLayer?
override func viewDidLoad() {
super.viewDidLoad()

mapView.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can assign this to self.view.frame instead of using the entire CGRect constructor.

mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

// Set the map's initial style, center coordinate, and zoom level
mapView.styleURL = MGLStyle.lightStyleURL
mapView.setCenter(CLLocationCoordinate2D(latitude: 25.251, longitude: 95.69), zoomLevel: 3, animated: false)

view.addSubview(mapView)

// Create a UISegmentedControl to toggle between map styles
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map style -> map worldviews

The style itself isn't changing, we're just toggling source visibility.

let styleToggle = UISegmentedControl(items: [" US ", " CN ", " IN "," All "])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we're not actually changing the style, you may want to consider renaming this to worldViewToggle.

styleToggle.translatesAutoresizingMaskIntoConstraints = false
styleToggle.tintColor = UIColor(red: 0.976, green: 0.843, blue: 0.831, alpha: 1)
styleToggle.backgroundColor = UIColor(red: 184/255, green: 205/255, blue: 212/255, alpha: 1)
styleToggle.layer.cornerRadius = 4
styleToggle.clipsToBounds = true
// styleToggle.selectedSegmentIndex = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you want to uncomment this?

view.insertSubview(styleToggle, aboveSubview: mapView)
styleToggle.addTarget(self, action: #selector(changeStyle(sender:)), for: .valueChanged)

// Configure autolayout constraints for the UISegmentedControl to align
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

autolayout -> Auto Layout

// at the bottom of the map view and above the Mapbox logo and attribution
NSLayoutConstraint.activate([NSLayoutConstraint(item: styleToggle, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: mapView, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1.0, constant: 0.0)])
NSLayoutConstraint.activate([NSLayoutConstraint(item: styleToggle, attribute: .bottom, relatedBy: .equal, toItem: mapView.logoView, attribute: .top, multiplier: 1, constant: -20)])

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An easier (and less lengthy) way to write constraints is to use the NSLayoutAnchor-based API to create constraints. Here's an example of writing one of your existing constraints this way:

Before:

NSLayoutConstraint(item: styleToggle, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: mapView, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1.0, constant: 0.0)

After, using NSLayoutAnchor syntax:

styleToggle.centerX.constraint(equalTo: mapView.centerX)

I recommend having a look at this blog post for more context!

You can also put all of your constraints into one NSLayoutConstraint.activate([...]) call, since that accepts an array of NSLayoutConstraints.

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep viewDidLoad light, I recommend moving all of the toggle setup code to its own function like setupToggle() and then calling that at the end of viewDidLoad.


// Change the map style based on the selected index of the UISegmentedControl
@objc func changeStyle(sender: UISegmentedControl) {

guard let style = self.mapView.style else {return}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{return} -> { return }
(add spacing around to be consistent with the other examples)

However, I think you could refactor this to not require accessing MGLStyle here at all if you instead access Mapbox Light's built-in admin layer.


if layer?.identifier == "admin" {
print("source already exists")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to remove this :)

style.removeLayer(layer!)
} else {
layer = MGLLineStyleLayer(identifier: "admin", source: source)
style.addSource(source)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

layer = MGLLineStyleLayer(identifier: "admin", source: source)
style.addSource(source)

This only happens the first time a user selects a segment. I don't think this code is necessary, since it appears that Mapbox Light already includes admin boundary style layers. That layer just needs to be accessed with MGLStyle.layer(withIdentifier: String), so we can avoid creating a new source and style layer for this.

layer?.sourceLayerIdentifier = "admin"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The layer identifier has already been defined in MGLLineStyleLayer(identifier: "admin", source: source) - I don't think it needs to be assigned again here? But also, this won't be needed if you address the comment above.

layer?.lineColor = NSExpression(forConstantValue: UIColor.lightGray)

switch sender.selectedSegmentIndex {
case 0:

layer?.predicate = NSPredicate(format: "CAST(worldview, 'NSString') == 'US'")
style.addLayer(layer!)
Copy link
Contributor

@captainbarbosa captainbarbosa Dec 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you refactor this to use the built-in admin layer, you can remove all instances of addLayer in this switch statement.

case 1:
layer?.predicate = NSPredicate(format: "CAST(worldview, 'NSString') == 'CN'")
style.addLayer(layer!)
case 2:
layer?.predicate = NSPredicate(format: "CAST(worldview, 'NSString') == 'IN'")
style.addLayer(layer!)
case 3:
layer?.predicate = NSPredicate(format: "CAST(worldview, 'NSString') == 'all'")
style.addLayer(layer!)
default:
style.addLayer(layer!)

}
}
}