Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MapView][Part 2] Make LocationManager hold LocationOptions directly #344

Merged
merged 1 commit into from
May 14, 2021
Merged
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
4 changes: 1 addition & 3 deletions Apps/DebugApp/DebugApp/DebugViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ public class DebugViewController: UIViewController {
super.viewDidLoad()

mapView = MapView(frame: view.bounds)
mapView.update { (mapOptions) in
mapOptions.location.puckType = .puck2D()
}
mapView.location.options.puckType = .puck2D()

view.addSubview(mapView)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ public class Custom2DPuckExample: UIViewController, ExampleProtocol {

internal func setupExample() {

mapView.update { (mapOptions) in
// Granularly configure the location puck with a `Puck2DConfiguration`
let configuration = Puck2DConfiguration(topImage: UIImage(named: "star"))
mapOptions.location.puckType = .puck2D(configuration)
}
// Granularly configure the location puck with a `Puck2DConfiguration`
let configuration = Puck2DConfiguration(topImage: UIImage(named: "star"))
mapView.location.options.puckType = .puck2D(configuration)

let coordinate = CLLocationCoordinate2D(latitude: 39.085006, longitude: -77.150925)
mapView.camera.setCamera(to: CameraOptions(center: coordinate,
Expand Down
76 changes: 37 additions & 39 deletions Apps/Examples/Examples/All Examples/Custom3DPuckExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,50 +26,48 @@ public class Custom3DPuckExample: UIViewController, ExampleProtocol {

internal func setupExample() {

mapView.update { (mapOptions) in
// Fetch the `gltf` asset
let uri = Bundle.main.url(forResource: "race_car_model",
withExtension: "gltf")
// Fetch the `gltf` asset
let uri = Bundle.main.url(forResource: "race_car_model",
withExtension: "gltf")

// Instantiate the model
let myModel = Model(uri: uri,
position: [-177.150925, 39.085006],
orientation: [0, 0, 0])
// Instantiate the model
let myModel = Model(uri: uri,
position: [-177.150925, 39.085006],
orientation: [0, 0, 0])

// Setting an expression to scale the model based on camera zoom
let scalingExpression = Exp(.interpolate) {
Exp(.linear)
Exp(.zoom)
0
Exp(.literal) {
[256000.0, 256000.0, 256000.0]
}
4
Exp(.literal) {
[40000.0, 40000.0, 40000.0]
}
8
Exp(.literal) {
[2000.0, 2000.0, 2000.0]
}
12
Exp(.literal) {
[100.0, 100.0, 100.0]
}
16
Exp(.literal) {
[7.0, 7.0, 7.0]
}
20
Exp(.literal) {
[1.0, 1.0, 1.0]
}
// Setting an expression to scale the model based on camera zoom
let scalingExpression = Exp(.interpolate) {
Exp(.linear)
Exp(.zoom)
0
Exp(.literal) {
[256000.0, 256000.0, 256000.0]
}
4
Exp(.literal) {
[40000.0, 40000.0, 40000.0]
}
8
Exp(.literal) {
[2000.0, 2000.0, 2000.0]
}
12
Exp(.literal) {
[100.0, 100.0, 100.0]
}
16
Exp(.literal) {
[7.0, 7.0, 7.0]
}
20
Exp(.literal) {
[1.0, 1.0, 1.0]
}

let configuration = Puck3DConfiguration(model: myModel, modelScale: .expression(scalingExpression))
mapOptions.location.puckType = .puck3D(configuration)
}

let configuration = Puck3DConfiguration(model: myModel, modelScale: .expression(scalingExpression))
mapView.location.options.puckType = .puck3D(configuration)

let coordinate = CLLocationCoordinate2D(latitude: 39.085006, longitude: -77.150925)
mapView.camera.setCamera(to: CameraOptions(center: coordinate,
zoom: 14,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ public class TrackingModeExample: UIViewController, ExampleProtocol {
cameraLocationConsumer = CameraLocationConsumer(mapView: mapView)

// Add user position icon to the map with location indicator layer
mapView.update { (mapOptions) in
mapOptions.location.puckType = .puck2D()
}
mapView.location.options.puckType = .puck2D()

// Allows the delegate to receive information about map events.
mapView.mapboxMap.onNext(.mapLoaded) { _ in
Expand Down
42 changes: 17 additions & 25 deletions Sources/MapboxMaps/Location/LocationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,22 @@ public class LocationManager: NSObject {
/// Only created if `showsUserLocation` is `true`
internal var locationPuckManager: LocationPuckManager?

public private(set) var locationOptions: LocationOptions
public var options = LocationOptions() {
didSet {
guard options != oldValue else { return }
locationProvider.locationProviderOptions = options

if options.puckType != oldValue.puckType {
syncUserLocationUpdating()
}

if let puckType = options.puckType, puckType != oldValue.puckType {
locationPuckManager?.changePuckType(to: puckType)
}
}
}

internal init(locationOptions: LocationOptions,
locationSupportableMapView: LocationSupportableMapView) {
/// Sets the local options needed to configure the user location puck
self.locationOptions = locationOptions
internal init(locationSupportableMapView: LocationSupportableMapView) {

/// Allows location updates to be reflected on screen using delegate method
self.locationSupportableMapView = locationSupportableMapView
Expand All @@ -54,7 +64,7 @@ public class LocationManager: NSObject {
/// Sets our default `locationProvider`
locationProvider = AppleLocationProvider()
locationProvider.setDelegate(self)
locationProvider.locationProviderOptions = locationOptions
locationProvider.locationProviderOptions = options

syncUserLocationUpdating()
}
Expand All @@ -80,24 +90,6 @@ public class LocationManager: NSObject {
consumers.remove(consumer)
}

internal func updateLocationOptions(with newOptions: LocationOptions) {

guard newOptions != locationOptions else { return }

// Update the location options
let previousOptions = locationOptions
locationOptions = newOptions
locationProvider.locationProviderOptions = newOptions

if newOptions.puckType != previousOptions.puckType {
syncUserLocationUpdating()
}

if let puckType = newOptions.puckType, puckType != previousOptions.puckType {
locationPuckManager?.changePuckType(to: puckType)
}
}

/// Allows a custom case to request full accuracy
@available(iOS 14.0, *)
public func requestTemporaryFullAccuracyPermissions(withPurposeKey purposeKey: String) {
Expand Down Expand Up @@ -189,7 +181,7 @@ extension LocationManager: LocationProviderDelegate {
// MARK: Private helper functions that only the Location Manager needs access to
private extension LocationManager {
func syncUserLocationUpdating() {
if let puckType = locationOptions.puckType {
if let puckType = options.puckType {
/// Get permissions if needed
if locationProvider.authorizationStatus == .notDetermined {
requestLocationPermissions()
Expand Down
3 changes: 0 additions & 3 deletions Sources/MapboxMaps/MapView/Configuration/MapConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ public struct MapConfig: Equatable {
/// Used to configure the camera of the map
public var camera: MapCameraOptions = MapCameraOptions()

/// Used to configure the location provider
public var location: LocationOptions = LocationOptions()

public var render: RenderOptions = RenderOptions()

public var annotations: AnnotationOptions = AnnotationOptions()
Expand Down
12 changes: 3 additions & 9 deletions Sources/MapboxMaps/MapView/MapView+Managers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension MapView {
setupOrnaments(with: self)

// Initialize/Configure location manager
setupUserLocationManager(with: self, options: mapConfig.location)
setupUserLocationManager(with: self)

// Initialize/Configure annotations manager
setupAnnotationManager(with: self, mapEventsObservable: mapboxMap, style: style, options: mapConfig.annotations)
Expand All @@ -37,7 +37,6 @@ extension MapView {
// Update the managers in order
updateMapView(with: mapConfig.render)
updateCamera(with: mapConfig.camera)
updateUserLocationManager(with: mapConfig.location)
updateAnnotationManager(with: mapConfig.annotations)
}

Expand Down Expand Up @@ -74,14 +73,9 @@ extension MapView {
ornaments = OrnamentsManager(view: view, options: OrnamentOptions())
}

internal func setupUserLocationManager(with locationSupportableMapView: LocationSupportableMapView, options: LocationOptions) {
internal func setupUserLocationManager(with locationSupportableMapView: LocationSupportableMapView) {

location = LocationManager(locationOptions: options,
locationSupportableMapView: locationSupportableMapView)
}

internal func updateUserLocationManager(with options: LocationOptions) {
location.updateLocationOptions(with: mapConfig.location)
location = LocationManager(locationSupportableMapView: locationSupportableMapView)
}

internal func setupAnnotationManager(with annotationSupportableMap: AnnotationSupportableMap, mapEventsObservable: MapEventsObservable, style: Style, options: AnnotationOptions) {
Expand Down
34 changes: 12 additions & 22 deletions Tests/MapboxMapsTests/Location/LocationManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,15 @@ internal class LocationManagerTests: XCTestCase {
func testLocationManagerDefaultInitialization() {
let locationOptions = LocationOptions()

let locationManager = LocationManager(
locationOptions: locationOptions,
locationSupportableMapView: locationSupportableMapView)
let locationManager = LocationManager(locationSupportableMapView: locationSupportableMapView)

XCTAssertEqual(locationManager.locationOptions, locationOptions)
XCTAssertEqual(locationManager.options, locationOptions)
XCTAssertTrue(locationManager.locationSupportableMapView === locationSupportableMapView)
XCTAssertNil(locationManager.delegate)
}

func testAddLocationConsumer() {
let locationManager = LocationManager(
locationOptions: LocationOptions(),
locationSupportableMapView: locationSupportableMapView)
let locationManager = LocationManager(locationSupportableMapView: locationSupportableMapView)
let locationConsumer = LocationConsumerMock()

locationManager.addLocationConsumer(newConsumer: locationConsumer)
Expand All @@ -47,45 +43,39 @@ internal class LocationManagerTests: XCTestCase {
func testUpdateLocationOptionsWithModifiedPuckType() {
var locationOptions = LocationOptions()
locationOptions.puckType = .puck2D(Puck2DConfiguration(scale: .constant(1.0)))
let locationManager = LocationManager(
locationOptions: locationOptions,
locationSupportableMapView: locationSupportableMapView)
let locationManager = LocationManager(locationSupportableMapView: locationSupportableMapView)

var locationOptions2 = LocationOptions()
locationOptions2.puckType = .puck2D(Puck2DConfiguration(scale: .constant(2.0)))
locationManager.updateLocationOptions(with: locationOptions2)
locationManager.options = locationOptions2

XCTAssertEqual(locationManager.locationOptions, locationOptions2)
XCTAssertEqual(locationManager.options, locationOptions2)
XCTAssertEqual(locationManager.locationPuckManager?.puckType, locationOptions2.puckType)
}

func testUpdateLocationOptionsWithPuckTypeSetToNil() {
var locationOptions = LocationOptions()
locationOptions.puckType = .puck2D()
let locationManager = LocationManager(
locationOptions: locationOptions,
locationSupportableMapView: locationSupportableMapView)
let locationManager = LocationManager(locationSupportableMapView: locationSupportableMapView)

var locationOptions2 = LocationOptions()
locationOptions2.puckType = nil
locationManager.updateLocationOptions(with: locationOptions2)
locationManager.options = locationOptions2

XCTAssertEqual(locationManager.locationOptions, locationOptions2)
XCTAssertEqual(locationManager.options, locationOptions2)
XCTAssertNil(locationManager.locationPuckManager)
}

func testUpdateLocationOptionsWithPuckTypeSetToNonNil() {
var locationOptions = LocationOptions()
locationOptions.puckType = nil
let locationManager = LocationManager(
locationOptions: locationOptions,
locationSupportableMapView: locationSupportableMapView)
let locationManager = LocationManager(locationSupportableMapView: locationSupportableMapView)

var locationOptions2 = LocationOptions()
locationOptions2.puckType = .puck2D()
locationManager.updateLocationOptions(with: locationOptions2)
locationManager.options = locationOptions2

XCTAssertEqual(locationManager.locationOptions, locationOptions2)
XCTAssertEqual(locationManager.options, locationOptions2)
XCTAssertEqual(locationManager.locationPuckManager?.puckType, locationOptions2.puckType)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@ final class Puck3DIntegrationTests: XCTestCase {
func testPuck3DDeinitializationDoesNotCrash() {
autoreleasepool {
let mapView = MapView(frame: .zero)
mapView.update { (options) in
options.location.puckType = .puck3D(
Puck3DConfiguration(
model: Model()))
}
mapView.location.options.puckType = .puck3D(Puck3DConfiguration(
model: Model()))
}
// there is no assertion here because this test is
// merely ensuring that Puck3D does not crash when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ internal class LocationManagerIntegrationTestCase: MapViewIntegrationTestCase {
}

private func setupLocationManager(with mapView: MapView) -> LocationManager {
let locationProviderOptions = LocationOptions()

let locationManager = LocationManager(locationOptions: locationProviderOptions,
locationSupportableMapView: mapView)

let locationManager = LocationManager(locationSupportableMapView: mapView)
return locationManager
}

Expand Down
6 changes: 0 additions & 6 deletions Tests/MapboxMapsTests/MapView/OptionsIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,12 @@ internal class OptionsIntegrationTest: MapViewIntegrationTestCase {
}

var newConfig = MapboxMaps.MapConfig()
newConfig.location.puckType = nil
newConfig.location.activityType = .automotiveNavigation
newConfig.camera.animationDuration = 0.1

mapView.update { (options) in
options = newConfig
}
XCTAssertEqual(mapView.camera.mapCameraOptions, newConfig.camera)
XCTAssertEqual(mapView.location.locationOptions, newConfig.location)
let ornaments = mapView.subviews.filter { $0.isKind(of: MapboxCompassOrnamentView.self) || $0.isKind(of: MapboxScaleBarOrnamentView.self) }

XCTAssertEqual(ornaments.count, 2)
XCTAssertEqual(mapView.metalView?.presentsWithTransaction, true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import XCTest
import MapboxMaps
import Turf

// swiftlint:disable force_cast file_length orphaned_doc_comment type_body_length
// swiftlint:disable force_cast file_length orphaned_doc_comment

class MigrationGuideIntegrationTests: IntegrationTestCase {

Expand Down