-
Notifications
You must be signed in to change notification settings - Fork 318
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
General outline #3
Conversation
@@ -0,0 +1,155 @@ | |||
// | |||
// MBNavigation.swift |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename this file to MBNavigationController.swift for consistency. (You can drop MB from the file names if you want. The file names don't actually matter.)
// MapboxNavigation | ||
// | ||
// Created by Bobby Sudekum on 11/16/16. | ||
// Copyright © 2016 Mapbox. All rights reserved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally we don't include header blocks in our public code. If you do, make sure to change "All rights reserved" to something more appropriate when we decide on a license.
import CoreLocation | ||
import MapboxDirections | ||
|
||
open class NavigationController: NSObject { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every public symbol will eventually need a documentation comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every public class or enum needs an @objc(…)
attribute that prefixes the class name with MB. Otherwise we'll pollute the class namespace in Objective-C.
|
||
locationManager.delegate = self | ||
if CLLocationManager.authorizationStatus() == .notDetermined { | ||
locationManager.requestWhenInUseAuthorization() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the user has to manually press Accept in this case, the location manager calls a delegate method asynchronously when permission is given. Implement that method; otherwise, this library will do nothing in the case where the user hasn't already given permissions by the time NavigationController is initialized.
} | ||
|
||
guard userIsOnRoute(location) else { | ||
NotificationCenter.default.post(name: NavigationControllerNotification.rerouted, object: self, userInfo: [NavigationControllerNotification.rerouted : "rerouted"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the point of this "rerouted" key in the user info dictionary? It doesn't provide any additional information, so remove it.
import Foundation | ||
import CoreLocation | ||
|
||
public let NavigationControllerProgressDidChangeNotificationProgressKey = "progress" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These keys should be of type NavigationControllerNotificationUserInfoKey, which would be a new typedef of String.
public let NavigationControllerMaximumAllowedDegreeOffsetForTurnCompletion: Double = 30 | ||
|
||
// Alert distances | ||
public let NavigationControllerMediumAlertNumberOfSeconds: Double = 70 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These constants should be of type TimeInterval and "NumberOfSeconds" should become "Interval".
class ViewController: UIViewController, MGLMapViewDelegate, AVSpeechSynthesizerDelegate { | ||
|
||
var destination: CLLocationCoordinate2D? | ||
var directions = Directions(accessToken: "pk.eyJ1IjoiYm9iYnlzdWQiLCJhIjoiTi16MElIUSJ9.Clrqck--7WmHeqqvtFdYig") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace this string literal with a placeholder token. See the example project in MapboxDirections.swift for an example.
options.routeShapeResolution = .full | ||
|
||
_ = directions.calculate(options) { [weak self] (waypoints, routes, error) in | ||
if let route = routes?.first { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a guard statement.
} | ||
|
||
func getRoute() { | ||
let options = RouteOptions(coordinates: [mapView.userLocation!.coordinate, destination!]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the automobileAvoidingTraffic
profile identifier.
In order to distribute this framework via CocoaPods, you'll need to add a podspec to the root of the repository. See MapboxDirections.swift for an example. Note that this podspec will directly require MapboxDirections but not Polyline (which would be a transitive dependency). |
Good first step here, going to merge this and begin documentation. |
The method is part of the public SDK API, and there are no guarantees that it will be called in a thread-safe manner. The fact current implementation isn't thread-safe was proofed by running a test with Thread Sanitizer (TSan) enabled (see the log at the end). - UnimplementedLogging.logUnimplemented reimplemented so that it is safe to use from multiple threads. - Adds a test to verify that the new implementation is safe. - Adds a test to catch performance regressions in implementation. Below is a log from TSan when run for old implementation: ``` WARNING: ThreadSanitizer: Swift access race (pid=14419) Modifying access of Swift variable at 0x00010a65a7a0 by thread T2: #0 UnimplementedLogging.logUnimplemented(protocolType:level:function:) <null>:12416464 (MapboxCoreNavigationTests:arm64+0x3a7464) #1 func1() in UnimplementedClass #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:9 (MapboxCoreNavigationTests:arm64+0xb26f4) #2 closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:24 (MapboxCoreNavigationTests:arm64+0xb1e9c) #3 partial apply for closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() <compiler-generated> (MapboxCoreNavigationTests:arm64+0xb1f34) #4 partial apply for thunk for @callee_guaranteed (@unowned Int) -> () <null>:12416464 (libswiftDispatch.dylib:arm64+0x5030) #5 _dispatch_client_callout2 <null>:12416464 (libdispatch.dylib:arm64+0x3d80) Previous read of size 8 at 0x00010a65a7a0 by thread T4: #0 UnimplementedLogging.logUnimplemented(protocolType:level:function:) <null>:12416464 (MapboxCoreNavigationTests:arm64+0x3a6f9c) #1 func1() in UnimplementedClass #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:9 (MapboxCoreNavigationTests:arm64+0xb26f4) #2 closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:24 (MapboxCoreNavigationTests:arm64+0xb1e9c) #3 partial apply for closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() <compiler-generated> (MapboxCoreNavigationTests:arm64+0xb1f34) #4 partial apply for thunk for @callee_guaranteed (@unowned Int) -> () <null>:12416464 (libswiftDispatch.dylib:arm64+0x5030) #5 _dispatch_client_callout2 <null>:12416464 (libdispatch.dylib:arm64+0x3d80) Location is global 'warned' at 0x00010a65a7a0 (MapboxCoreNavigationTests+0x000000e3a7a0) Thread T2 (tid=3981887, running) is a GCD worker thread Thread T4 (tid=3981890, running) is a GCD worker thread SUMMARY: ThreadSanitizer: Swift access race (MapboxCoreNavigationTests:arm64+0x3a7464) in UnimplementedLogging.logUnimplemented(protocolType:level:function:)+0x770 ```
The method is part of the public SDK API, and there are no guarantees that it will be called in a thread-safe manner. The fact current implementation isn't thread-safe was proofed by running a test with Thread Sanitizer (TSan) enabled (see the log at the end). - UnimplementedLogging.logUnimplemented reimplemented so that it is safe to use from multiple threads. - Adds a test to verify that the new implementation is safe. - Adds a test to catch performance regressions in implementation. Below is a log from TSan when run for old implementation: ``` WARNING: ThreadSanitizer: Swift access race (pid=14419) Modifying access of Swift variable at 0x00010a65a7a0 by thread T2: #0 UnimplementedLogging.logUnimplemented(protocolType:level:function:) <null>:12416464 (MapboxCoreNavigationTests:arm64+0x3a7464) #1 func1() in UnimplementedClass #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:9 (MapboxCoreNavigationTests:arm64+0xb26f4) #2 closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:24 (MapboxCoreNavigationTests:arm64+0xb1e9c) #3 partial apply for closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() <compiler-generated> (MapboxCoreNavigationTests:arm64+0xb1f34) #4 partial apply for thunk for @callee_guaranteed (@unowned Int) -> () <null>:12416464 (libswiftDispatch.dylib:arm64+0x5030) #5 _dispatch_client_callout2 <null>:12416464 (libdispatch.dylib:arm64+0x3d80) Previous read of size 8 at 0x00010a65a7a0 by thread T4: #0 UnimplementedLogging.logUnimplemented(protocolType:level:function:) <null>:12416464 (MapboxCoreNavigationTests:arm64+0x3a6f9c) #1 func1() in UnimplementedClass #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:9 (MapboxCoreNavigationTests:arm64+0xb26f4) #2 closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:24 (MapboxCoreNavigationTests:arm64+0xb1e9c) #3 partial apply for closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() <compiler-generated> (MapboxCoreNavigationTests:arm64+0xb1f34) #4 partial apply for thunk for @callee_guaranteed (@unowned Int) -> () <null>:12416464 (libswiftDispatch.dylib:arm64+0x5030) #5 _dispatch_client_callout2 <null>:12416464 (libdispatch.dylib:arm64+0x3d80) Location is global 'warned' at 0x00010a65a7a0 (MapboxCoreNavigationTests+0x000000e3a7a0) Thread T2 (tid=3981887, running) is a GCD worker thread Thread T4 (tid=3981890, running) is a GCD worker thread SUMMARY: ThreadSanitizer: Swift access race (MapboxCoreNavigationTests:arm64+0x3a7464) in UnimplementedLogging.logUnimplemented(protocolType:level:function:)+0x770 ```
The method is part of the public SDK API, and there are no guarantees that it will be called in a thread-safe manner. The fact current implementation isn't thread-safe was proofed by running a test with Thread Sanitizer (TSan) enabled (see the log at the end). - UnimplementedLogging.logUnimplemented reimplemented so that it is safe to use from multiple threads. - Adds a test to verify that the new implementation is safe. - Adds a test to catch performance regressions in implementation. Below is a log from TSan when run for old implementation: ``` WARNING: ThreadSanitizer: Swift access race (pid=14419) Modifying access of Swift variable at 0x00010a65a7a0 by thread T2: #0 UnimplementedLogging.logUnimplemented(protocolType:level:function:) <null>:12416464 (MapboxCoreNavigationTests:arm64+0x3a7464) #1 func1() in UnimplementedClass #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:9 (MapboxCoreNavigationTests:arm64+0xb26f4) #2 closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:24 (MapboxCoreNavigationTests:arm64+0xb1e9c) #3 partial apply for closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() <compiler-generated> (MapboxCoreNavigationTests:arm64+0xb1f34) #4 partial apply for thunk for @callee_guaranteed (@unowned Int) -> () <null>:12416464 (libswiftDispatch.dylib:arm64+0x5030) #5 _dispatch_client_callout2 <null>:12416464 (libdispatch.dylib:arm64+0x3d80) Previous read of size 8 at 0x00010a65a7a0 by thread T4: #0 UnimplementedLogging.logUnimplemented(protocolType:level:function:) <null>:12416464 (MapboxCoreNavigationTests:arm64+0x3a6f9c) #1 func1() in UnimplementedClass #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:9 (MapboxCoreNavigationTests:arm64+0xb26f4) #2 closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() UnimplementedLoggingTests.swift:24 (MapboxCoreNavigationTests:arm64+0xb1e9c) #3 partial apply for closure #1 in UnimplementedLoggingTests.testUnimplementedLoggingMultithreaded() <compiler-generated> (MapboxCoreNavigationTests:arm64+0xb1f34) #4 partial apply for thunk for @callee_guaranteed (@unowned Int) -> () <null>:12416464 (libswiftDispatch.dylib:arm64+0x5030) #5 _dispatch_client_callout2 <null>:12416464 (libdispatch.dylib:arm64+0x3d80) Location is global 'warned' at 0x00010a65a7a0 (MapboxCoreNavigationTests+0x000000e3a7a0) Thread T2 (tid=3981887, running) is a GCD worker thread Thread T4 (tid=3981890, running) is a GCD worker thread SUMMARY: ThreadSanitizer: Swift access race (MapboxCoreNavigationTests:arm64+0x3a7464) in UnimplementedLogging.logUnimplemented(protocolType:level:function:)+0x770 ```
@1ec5 okay this is a general working outline. Some notes on how the API will work:
todo:
/cc @pveugen