From da49354aa8c62ffaaf809bcb334c9afbf1954291 Mon Sep 17 00:00:00 2001 From: Fredrik Karlsson Date: Tue, 9 Apr 2019 23:39:40 +0200 Subject: [PATCH] Outline support for Linux --- .circleci/config.yml | 9 ++++ Package.resolved | 6 +-- Package.swift | 2 +- .../Extensions/CLLocationCoordinate2D.swift | 4 +- .../MBComponentRepresentable.swift | 3 +- .../MapboxDirections/MBCoordinateBounds.swift | 3 ++ Sources/MapboxDirections/MBDirections.swift | 5 +- .../MBDirectionsOptions.swift | 31 +++++++----- .../MapboxDirections/MBDirectionsResult.swift | 24 +++++----- Sources/MapboxDirections/MBIntersection.swift | 4 +- Sources/MapboxDirections/MBRoute.swift | 16 +++++-- Sources/MapboxDirections/MBRouteLeg.swift | 8 ++-- Sources/MapboxDirections/MBRouteOptions.swift | 5 +- Sources/MapboxDirections/MBRouteStep.swift | 24 ++++++---- .../MBSpokenInstruction.swift | 4 +- .../MBVisualInstruction.swift | 18 +++---- .../MBVisualInstructionBanner.swift | 12 +++-- .../MBVisualInstructionComponent.swift | 22 +++++---- Sources/MapboxDirections/MBWaypoint.swift | 11 +++-- Sources/MapboxDirections/Match/MBMatch.swift | 3 ++ .../Match/MBMatchOptions.swift | 3 +- .../MapboxDirections/Match/MBTracepoint.swift | 2 + .../MapboxDirections/OfflineDirections.swift | 1 - .../MapboxDirections/SPM/CoreLocation.swift | 47 +++++++++++++++---- 24 files changed, 174 insertions(+), 93 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0fab932ba..01ea5ed5e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -26,6 +26,13 @@ step-library: command: bash <(curl -s https://codecov.io/bash) jobs: + spm-linux-job: + docker: + - image: swift:5.0 + steps: + - checkout + - run: swift build + spm-job: parameters: xcode: @@ -126,3 +133,5 @@ workflows: - spm-job: name: "SPM_build" xcode: "10.2.0" + - spm-linux-job: + name: "SPM_Ubuntu_build" diff --git a/Package.resolved b/Package.resolved index b9a959338..09e49f98c 100644 --- a/Package.resolved +++ b/Package.resolved @@ -3,10 +3,10 @@ "pins": [ { "package": "Polyline", - "repositoryURL": "https://github.com/raphaelmor/Polyline.git", + "repositoryURL": "https://github.com/frederoni/Polyline.git", "state": { - "branch": "master", - "revision": "b5b6dff67db5d692c2253df79d9d6802953316b8", + "branch": "linux", + "revision": "5b189aca4675a442d280b93f0d6c16d76f297e48", "version": null } } diff --git a/Package.swift b/Package.swift index fb6381018..99e2a98f9 100644 --- a/Package.swift +++ b/Package.swift @@ -13,7 +13,7 @@ let package = Package( ], dependencies: [ // Dependencies declare other packages that this package depends on. - .package(url: "https://github.com/raphaelmor/Polyline.git", .branch("master")) + .package(url: "https://github.com/frederoni/Polyline.git", .branch("linux")) ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/MapboxDirections/Extensions/CLLocationCoordinate2D.swift b/Sources/MapboxDirections/Extensions/CLLocationCoordinate2D.swift index 91ac34cca..3e96f34b2 100644 --- a/Sources/MapboxDirections/Extensions/CLLocationCoordinate2D.swift +++ b/Sources/MapboxDirections/Extensions/CLLocationCoordinate2D.swift @@ -1,11 +1,13 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif extension CLLocation { /** Initializes a CLLocation object with the given coordinate pair. */ - internal convenience init(coordinate: CLLocationCoordinate2D) { + internal init(coordinate: CLLocationCoordinate2D) { self.init(latitude: coordinate.latitude, longitude: coordinate.longitude) } } diff --git a/Sources/MapboxDirections/MBComponentRepresentable.swift b/Sources/MapboxDirections/MBComponentRepresentable.swift index 717c6f68e..ade38afe3 100644 --- a/Sources/MapboxDirections/MBComponentRepresentable.swift +++ b/Sources/MapboxDirections/MBComponentRepresentable.swift @@ -3,5 +3,4 @@ import Foundation /** The component representable protocol that comprises what the instruction banner should display. */ -@objc(MBComponentRepresentable) -public protocol ComponentRepresentable: class, NSSecureCoding { } +public protocol ComponentRepresentable: NSObjectProtocol, NSSecureCoding { } diff --git a/Sources/MapboxDirections/MBCoordinateBounds.swift b/Sources/MapboxDirections/MBCoordinateBounds.swift index bd732b1c8..cc8f5ceb6 100644 --- a/Sources/MapboxDirections/MBCoordinateBounds.swift +++ b/Sources/MapboxDirections/MBCoordinateBounds.swift @@ -1,5 +1,8 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif + /** A bounding box represents a geographic region. diff --git a/Sources/MapboxDirections/MBDirections.swift b/Sources/MapboxDirections/MBDirections.swift index dc4d91150..ce336bdc8 100644 --- a/Sources/MapboxDirections/MBDirections.swift +++ b/Sources/MapboxDirections/MBDirections.swift @@ -37,9 +37,12 @@ let userAgent: String = { #elseif os(Linux) system = "Linux" #endif + + #if !os(Linux) // TODO: Linux is missing ProcessInfo.operatingSystemVersion let systemVersion = ProcessInfo().operatingSystemVersion components.append("\(system)/\(systemVersion.majorVersion).\(systemVersion.minorVersion).\(systemVersion.patchVersion)") - + #endif + let chip: String #if arch(x86_64) chip = "x86_64" diff --git a/Sources/MapboxDirections/MBDirectionsOptions.swift b/Sources/MapboxDirections/MBDirectionsOptions.swift index 1fb2b7849..3ff5f6fec 100644 --- a/Sources/MapboxDirections/MBDirectionsOptions.swift +++ b/Sources/MapboxDirections/MBDirectionsOptions.swift @@ -1,6 +1,8 @@ import Foundation import Polyline +#if !os(Linux) import CoreLocation +#endif /** @@ -67,19 +69,24 @@ extension RouteShapeFormat { func coordinates(from geometry: Any?) -> [CLLocationCoordinate2D]? { switch self { case .geoJSON: - if let geometry = geometry as? JSONDictionary { - return CLLocationCoordinate2D.coordinates(geoJSON: geometry) - } + return nil + // TODO: + // if let geometry = geometry as? JSONDictionary { + // return CLLocationCoordinate2D.coordinates(geoJSON: geometry) + // } case .polyline: - if let geometry = geometry as? String { - return decodePolyline(geometry, precision: 1e5)! - } + return nil + // TODO: + // if let geometry = geometry as? String { + // return decodePolyline(geometry, precision: 1e5)! + // } case .polyline6: - if let geometry = geometry as? String { - return decodePolyline(geometry, precision: 1e6)! - } + return nil + // TODO: + // if let geometry = geometry as? String { + // return decodePolyline(geometry, precision: 1e6)! + // } } - return nil } } @@ -222,7 +229,6 @@ public enum InstructionFormat: UInt, CustomStringConvertible { You do not create instances of this class directly. Instead, create instances of `MatchOptions` or `RouteOptions`. */ @objcMembers -@objc(MBDirectionsOptions) open class DirectionsOptions: NSObject, NSSecureCoding, NSCopying { /** @@ -243,7 +249,7 @@ open class DirectionsOptions: NSObject, NSSecureCoding, NSCopying { } // MARK: NSCopying - @objc open func copy(with zone: NSZone? = nil) -> Any { + open func copy(with zone: NSZone? = nil) -> Any { let copy = type(of: self).init(waypoints: waypoints, profileIdentifier: profileIdentifier) copy.includesSteps = includesSteps copy.shapeFormat = shapeFormat @@ -262,7 +268,6 @@ open class DirectionsOptions: NSObject, NSSecureCoding, NSCopying { return isEqual(to: opts) } - @objc(isEqualToDirectionsOptions:) open func isEqual(to directionsOptions: DirectionsOptions?) -> Bool { guard let other = directionsOptions else { return false } guard type(of: self) == type(of: other) else { return false } diff --git a/Sources/MapboxDirections/MBDirectionsResult.swift b/Sources/MapboxDirections/MBDirectionsResult.swift index 5e9f83ec6..a86e48fbd 100644 --- a/Sources/MapboxDirections/MBDirectionsResult.swift +++ b/Sources/MapboxDirections/MBDirectionsResult.swift @@ -1,6 +1,8 @@ import Foundation import Polyline +#if !os(Linux) import CoreLocation +#endif /** @@ -8,12 +10,12 @@ import CoreLocation You do not create instances of this class directly. Instead, you receive `Route` or `Match` objects when you request directions using the `Directions.calculate(_:completionHandler:)` or `Directions.calculateRoutes(matching:completionHandler:)` method. */ -@objc(MBDirectionsResult) +@objcMembers open class DirectionsResult: NSObject, NSSecureCoding { public var json: [String: Any]? - @objc internal init(json: [String: Any]? = nil, legs: [RouteLeg], distance: CLLocationDistance, expectedTravelTime: TimeInterval, coordinates: [CLLocationCoordinate2D]?, speechLocale: Locale?, options: DirectionsOptions) { + internal init(json: [String: Any]? = nil, legs: [RouteLeg], distance: CLLocationDistance, expectedTravelTime: TimeInterval, coordinates: [CLLocationCoordinate2D]?, speechLocale: Locale?, options: DirectionsOptions) { self.json = json self.directionsOptions = options self.legs = legs @@ -23,7 +25,7 @@ open class DirectionsResult: NSObject, NSSecureCoding { self.speechLocale = speechLocale } - @objc public required init?(coder decoder: NSCoder) { + public required init?(coder decoder: NSCoder) { accessToken = decoder.decodeObject(of: NSString.self, forKey: "accessToken") as String? apiEndpoint = decoder.decodeObject(of: NSURL.self, forKey: "apiEndpoint") as URL? @@ -55,7 +57,7 @@ open class DirectionsResult: NSObject, NSSecureCoding { return true } - @objc public func encode(with coder: NSCoder) { + public func encode(with coder: NSCoder) { coder.encode(accessToken, forKey: "accessToken") coder.encode(apiEndpoint, forKey: "apiEndpoint") @@ -80,7 +82,7 @@ open class DirectionsResult: NSObject, NSSecureCoding { Using the [Mapbox Maps SDK for iOS](https://docs.mapbox.com/ios/maps/) or [Mapbox Maps SDK for macOS](https://mapbox.github.io/mapbox-gl-native/macos/), you can create an `MGLPolyline` object using these coordinates to display an overview of the route on an `MGLMapView`. */ - @objc public let coordinates: [CLLocationCoordinate2D]? + public let coordinates: [CLLocationCoordinate2D]? /** The number of coordinates. @@ -89,7 +91,7 @@ open class DirectionsResult: NSObject, NSSecureCoding { - note: This initializer is intended for Objective-C usage. In Swift code, use the `coordinates.count` property. */ - @objc open var coordinateCount: UInt { + open var coordinateCount: UInt { return UInt(coordinates?.count ?? 0) } @@ -106,7 +108,7 @@ open class DirectionsResult: NSObject, NSSecureCoding { - note: This initializer is intended for Objective-C usage. In Swift code, use the `coordinates` property. */ - @objc open func getCoordinates(_ coordinates: UnsafeMutablePointer) { + open func getCoordinates(_ coordinates: UnsafeMutablePointer) { for i in 0..<(self.coordinates?.count ?? 0) { coordinates.advanced(by: i).pointee = self.coordinates![i] } @@ -119,9 +121,9 @@ open class DirectionsResult: NSObject, NSSecureCoding { To determine the name of the route, concatenate the names of the route’s legs. */ - @objc public let legs: [RouteLeg] + public let legs: [RouteLeg] - @objc open override var description: String { + open override var description: String { return legs.map { $0.name }.joined(separator: " – ") } @@ -132,7 +134,7 @@ open class DirectionsResult: NSObject, NSSecureCoding { The value of this property accounts for the distance that the user must travel to traverse the path of the route. It is the sum of the `distance` properties of the route’s legs, not the sum of the direct distances between the route’s waypoints. You should not assume that the user would travel along this distance at a fixed speed. */ - @objc public let distance: CLLocationDistance + public let distance: CLLocationDistance /** The route’s expected travel time, measured in seconds. @@ -141,7 +143,7 @@ open class DirectionsResult: NSObject, NSSecureCoding { Do not assume that the user would travel along the route at a fixed speed. For more granular travel times, use the `RouteLeg.expectedTravelTime` or `RouteStep.expectedTravelTime`. For even more granularity, specify the `AttributeOptions.expectedTravelTime` option and use the `RouteLeg.expectedSegmentTravelTimes` property. */ - @objc public let expectedTravelTime: TimeInterval + public let expectedTravelTime: TimeInterval /** `RouteOptions` used to create the directions request. diff --git a/Sources/MapboxDirections/MBIntersection.swift b/Sources/MapboxDirections/MBIntersection.swift index e80557078..a67288713 100644 --- a/Sources/MapboxDirections/MBIntersection.swift +++ b/Sources/MapboxDirections/MBIntersection.swift @@ -1,11 +1,13 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif /** A single cross street along a step. */ -@objc(MBIntersection) +@objcMembers public class Intersection: NSObject, NSSecureCoding { /** The geographic coordinates at the center of the intersection. diff --git a/Sources/MapboxDirections/MBRoute.swift b/Sources/MapboxDirections/MBRoute.swift index 701ec9489..9f0949973 100644 --- a/Sources/MapboxDirections/MBRoute.swift +++ b/Sources/MapboxDirections/MBRoute.swift @@ -1,5 +1,7 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif import Polyline @@ -8,11 +10,11 @@ import Polyline Typically, you do not create instances of this class directly. Instead, you receive route objects when you request directions using the `Directions.calculate(_:completionHandler:)` method. However, if you use the `Directions.url(forCalculating:)` method instead, you can pass the results of the HTTP request into this class’s initializer. */ -@objc(MBRoute) +@objcMembers open class Route: DirectionsResult { // MARK: Creating a Route - @objc internal override init(json: [String : Any]? = nil, legs: [RouteLeg], distance: CLLocationDistance, expectedTravelTime: TimeInterval, coordinates: [CLLocationCoordinate2D]?, speechLocale: Locale?, options: DirectionsOptions) { + internal override init(json: [String : Any]? = nil, legs: [RouteLeg], distance: CLLocationDistance, expectedTravelTime: TimeInterval, coordinates: [CLLocationCoordinate2D]?, speechLocale: Locale?, options: DirectionsOptions) { super.init(json: json, legs: legs, distance: distance, expectedTravelTime: expectedTravelTime, coordinates: coordinates, speechLocale: speechLocale, options: options) } @@ -25,7 +27,6 @@ open class Route: DirectionsResult { - parameter waypoints: An array of waypoints that the route visits in chronological order. - parameter options: The options used when requesting the route. */ - @objc(initWithJSON:waypoints:routeOptions:) public init(json: [String: Any], waypoints: [Waypoint], options: RouteOptions) { // Associate each leg JSON with a source and destination. The sequence of destinations is offset by one from the sequence of sources. let legInfo = zip(zip(waypoints.prefix(upTo: waypoints.endIndex - 1), waypoints.suffix(from: 1)), @@ -50,7 +51,7 @@ open class Route: DirectionsResult { return super.directionsOptions as! RouteOptions } - @objc public required init?(coder decoder: NSCoder) { + public required init?(coder decoder: NSCoder) { super.init(coder: decoder) } @@ -72,7 +73,12 @@ internal class RouteV4: Route { case let geometry as JSONDictionary: coordinates = CLLocationCoordinate2D.coordinates(geoJSON: geometry) case let geometry as String: - coordinates = decodePolyline(geometry, precision: 1e6)! + //let polylineCoords = decodePolyline(geometry, precision: 1e6)! + // TODO: MapboxDirections.CLLocationCoordinate2D for linux + // TODO: Polyline.CLLocationCoordinate2D + //coordinates = decodePolyline(geometry, precision: 1e6)! + print(geometry) + coordinates = nil default: coordinates = nil } diff --git a/Sources/MapboxDirections/MBRouteLeg.swift b/Sources/MapboxDirections/MBRouteLeg.swift index 2d82396df..d876ef25e 100644 --- a/Sources/MapboxDirections/MBRouteLeg.swift +++ b/Sources/MapboxDirections/MBRouteLeg.swift @@ -1,5 +1,7 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif import Polyline @@ -9,12 +11,11 @@ import Polyline You do not create instances of this class directly. Instead, you receive route leg objects as part of route objects when you request directions using the `Directions.calculate(_:completionHandler:)` method. */ @objcMembers -@objc(MBRouteLeg) open class RouteLeg: NSObject, NSSecureCoding { // MARK: Creating a Leg - @objc internal init(steps: [RouteStep], json: JSONDictionary, source: Waypoint, destination: Waypoint, options: RouteOptions) { + internal init(steps: [RouteStep], json: JSONDictionary, source: Waypoint, destination: Waypoint, options: RouteOptions) { self.source = source self.destination = destination self.profileIdentifier = options.profileIdentifier @@ -61,7 +62,6 @@ open class RouteLeg: NSObject, NSSecureCoding { - parameter destination: The waypoint at the end of the leg. - parameter options: The options used when requesting the route. */ - @objc(initWithJSON:source:destination:options:) public convenience init(json: [String: Any], source: Waypoint, destination: Waypoint, options: RouteOptions) { let steps = (json["steps"] as? [JSONDictionary] ?? []).map { RouteStep(json: $0, options: options) } self.init(steps: steps, json: json, source: source, destination: destination, options: options) @@ -142,7 +142,7 @@ open class RouteLeg: NSObject, NSSecureCoding { This array is empty if the `includesSteps` property of the original `RouteOptions` object is set to `false`. */ - @objc public let steps: [RouteStep] + public let steps: [RouteStep] /** diff --git a/Sources/MapboxDirections/MBRouteOptions.swift b/Sources/MapboxDirections/MBRouteOptions.swift index ec1303ee2..b3a94a857 100644 --- a/Sources/MapboxDirections/MBRouteOptions.swift +++ b/Sources/MapboxDirections/MBRouteOptions.swift @@ -1,5 +1,7 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif #if SWIFT_PACKAGE public enum MBDirectionsProfileIdentifier: String { @@ -16,7 +18,6 @@ public enum MBDirectionsProfileIdentifier: String { Pass an instance of this class into the `Directions.calculate(_:completionHandler:)` method. */ @objcMembers -@objc(MBRouteOptions) open class RouteOptions: DirectionsOptions { /** Initializes a route options object for routes between the given locations and an optional profile identifier. @@ -208,7 +209,6 @@ open class RouteOptions: DirectionsOptions { return isEqual(to: opts) } - @objc(isEqualToRouteOptions:) open func isEqual(to routeOptions: RouteOptions?) -> Bool { guard let other = routeOptions else { return false } guard super.isEqual(to: routeOptions) else { return false } @@ -226,7 +226,6 @@ open class RouteOptions: DirectionsOptions { Pass an instance of this class into the `Directions.calculate(_:completionHandler:)` method. */ @objcMembers -@objc(MBRouteOptionsV4) open class RouteOptionsV4: RouteOptions { // MARK: Specifying the Response Format diff --git a/Sources/MapboxDirections/MBRouteStep.swift b/Sources/MapboxDirections/MBRouteStep.swift index 48e958f58..69e460955 100644 --- a/Sources/MapboxDirections/MBRouteStep.swift +++ b/Sources/MapboxDirections/MBRouteStep.swift @@ -1,13 +1,14 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif import Polyline /** A `TransportType` specifies the mode of transportation used for part of a route. */ -@objc(MBTransportType) -public enum TransportType: Int, CustomStringConvertible { +@objc(MBTransportType) public enum TransportType: Int, CustomStringConvertible { // Possible transport types when the `profileIdentifier` is `MBDirectionsProfileIdentifierAutomobile` or `MBDirectionsProfileIdentifierAutomobileAvoidingTraffic` /** @@ -555,7 +556,7 @@ struct Road { You do not create instances of this class directly. Instead, you receive route step objects as part of route objects when you request directions using the `Directions.calculate(_:completionHandler:)` method, setting the `includesSteps` option to `true` in the `RouteOptions` object that you pass into that method. */ -@objc(MBRouteStep) +@objcMembers open class RouteStep: NSObject, NSSecureCoding { // MARK: Creating a Step @@ -623,7 +624,6 @@ open class RouteStep: NSObject, NSSecureCoding { - parameter json: A JSON object that conforms to the [route step](https://docs.mapbox.com/api/navigation/#route-step-object) format described in the Directions API documentation. */ - @objc(initWithJSON:options:) public convenience init(json: [String: Any], options: RouteOptions) { let maneuver = json["maneuver"] as! JSONDictionary let finalHeading = maneuver["bearing_after"] as? Double @@ -762,7 +762,7 @@ open class RouteStep: NSObject, NSSecureCoding { Using the [Mapbox Maps SDK for iOS](https://docs.mapbox.com/ios/maps/) or [Mapbox Maps SDK for macOS](https://mapbox.github.io/mapbox-gl-native/macos/), you can create an `MGLPolyline` object using these coordinates to display a portion of a route on an `MGLMapView`. */ - @objc public let coordinates: [CLLocationCoordinate2D]? + public let coordinates: [CLLocationCoordinate2D]? /** The number of coordinates. @@ -789,7 +789,7 @@ open class RouteStep: NSObject, NSSecureCoding { - note: This initializer is intended for Objective-C usage. In Swift code, use the `coordinates` property. */ - @objc open func getCoordinates(_ coordinates: UnsafeMutablePointer) -> Bool { + open func getCoordinates(_ coordinates: UnsafeMutablePointer) -> Bool { guard let stepCoordinates = self.coordinates else { return false } @@ -818,7 +818,7 @@ open class RouteStep: NSObject, NSSecureCoding { This property is non-`nil` if the `RouteOptions.includesSpokenInstructions` option is set to `true`. For instructions designed for display, use the `instructions` property. */ - @objc public let instructionsSpokenAlongStep: [SpokenInstruction]? + public let instructionsSpokenAlongStep: [SpokenInstruction]? /** Instructions about the next step’s maneuver, optimized for display in real time. @@ -827,7 +827,7 @@ open class RouteStep: NSObject, NSSecureCoding { This property is non-`nil` if the `RouteOptions.includesVisualInstructions` option is set to `true`. For instructions designed for speech synthesis, use the `instructionsSpokenAlongStep` property. For instructions designed for display in a static list, use the `instructions` property. */ - @objc public let instructionsDisplayedAlongStep: [VisualInstructionBanner]? + public let instructionsDisplayedAlongStep: [VisualInstructionBanner]? @objc open override var description: String { return instructions @@ -863,7 +863,7 @@ open class RouteStep: NSObject, NSSecureCoding { /** The location of the maneuver at the beginning of this step. */ - @objc public let maneuverLocation: CLLocationCoordinate2D + public let maneuverLocation: CLLocationCoordinate2D /** The number of exits from the previous maneuver up to and including this step’s maneuver. @@ -976,7 +976,7 @@ open class RouteStep: NSObject, NSSecureCoding { Each item in the array corresponds to a cross street, starting with the intersection at the maneuver location indicated by the coordinates property and continuing with each cross street along the step. */ - @objc public let intersections: [Intersection]? + public let intersections: [Intersection]? func debugQuickLookObject() -> Any? { if let coordinates = coordinates { @@ -1035,6 +1035,9 @@ internal class RouteStepV4: RouteStep { } func debugQuickLookURL(illustrating coordinates: [CLLocationCoordinate2D], profileIdentifier: MBDirectionsProfileIdentifier = .automobile) -> URL? { + #if os(Linux) + return nil + #else guard let accessToken = defaultAccessToken else { return nil } @@ -1068,4 +1071,5 @@ func debugQuickLookURL(illustrating coordinates: [CLLocationCoordinate2D], profi ] return URL(string: "https://api.mapbox.com\(path)?\(components.percentEncodedQuery!)") + #endif } diff --git a/Sources/MapboxDirections/MBSpokenInstruction.swift b/Sources/MapboxDirections/MBSpokenInstruction.swift index 97ea6f9ff..43960efec 100644 --- a/Sources/MapboxDirections/MBSpokenInstruction.swift +++ b/Sources/MapboxDirections/MBSpokenInstruction.swift @@ -1,5 +1,7 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif /** @@ -9,7 +11,7 @@ import CoreLocation The `distanceAlongStep` property is measured from the beginning of the step associated with this object. By contrast, the `text` and `ssmlText` properties refer to the details in the following step. It is also possible for the instruction to refer to two following steps simultaneously when needed for safe navigation. */ -@objc(MBSpokenInstruction) +@objcMembers open class SpokenInstruction: NSObject, NSSecureCoding { /** diff --git a/Sources/MapboxDirections/MBVisualInstruction.swift b/Sources/MapboxDirections/MBVisualInstruction.swift index 1b3570a32..1abe9e375 100644 --- a/Sources/MapboxDirections/MBVisualInstruction.swift +++ b/Sources/MapboxDirections/MBVisualInstruction.swift @@ -1,11 +1,13 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif /** The contents of a banner that should be displayed as added visual guidance for a route. The banner instructions are children of the steps during which they should be displayed, but they refer to the maneuver in the following step. */ -@objc(MBVisualInstruction) +@objcMembers open class VisualInstruction: NSObject, NSSecureCoding { public static var supportsSecureCoding = true @@ -13,22 +15,22 @@ open class VisualInstruction: NSObject, NSSecureCoding { /** A plain text representation of the instruction. */ - @objc public let text: String? + public let text: String? /** The type of maneuver required for beginning the step described by the visual instruction. */ - @objc public var maneuverType: ManeuverType + public var maneuverType: ManeuverType /** Additional directional information to clarify the maneuver type. */ - @objc public var maneuverDirection: ManeuverDirection + public var maneuverDirection: ManeuverDirection /** A structured representation of the instruction. */ - @objc public let components: [ComponentRepresentable] + public let components: [ComponentRepresentable] /** The heading at which the user exits a roundabout (traffic circle or rotary). @@ -37,12 +39,12 @@ open class VisualInstruction: NSObject, NSSecureCoding { This property is only relevant if the `maneuverType` is any of the following values: `ManeuverType.takeRoundabout`, `ManeuverType.takeRotary`, `ManeuverType.turnAtRoundabout`, `ManeuverType.exitRoundabout`, or `ManeuverType.exitRotary`. */ - @objc public var finalHeading: CLLocationDegrees = 180 + public var finalHeading: CLLocationDegrees = 180 /** Initializes a new visual instruction banner object that displays the given information. */ - @objc public init(text: String?, maneuverType: ManeuverType, maneuverDirection: ManeuverDirection, components: [ComponentRepresentable], degrees: CLLocationDegrees = 180) { + public init(text: String?, maneuverType: ManeuverType, maneuverDirection: ManeuverDirection, components: [ComponentRepresentable], degrees: CLLocationDegrees = 180) { self.text = text self.maneuverType = maneuverType self.maneuverDirection = maneuverDirection @@ -88,7 +90,7 @@ open class VisualInstruction: NSObject, NSSecureCoding { self.init(text: text, maneuverType: maneuverType, maneuverDirection: maneuverDirection, components: components, degrees: degrees) } - @objc public required init?(coder decoder: NSCoder) { + public required init?(coder decoder: NSCoder) { text = decoder.decodeObject(of: NSString.self, forKey: "text") as String? guard let maneuverTypeString = decoder.decodeObject(of: NSString.self, forKey: "maneuverType") as String?, let maneuverType = ManeuverType(description: maneuverTypeString) else { diff --git a/Sources/MapboxDirections/MBVisualInstructionBanner.swift b/Sources/MapboxDirections/MBVisualInstructionBanner.swift index 670f36e55..566dffb2e 100644 --- a/Sources/MapboxDirections/MBVisualInstructionBanner.swift +++ b/Sources/MapboxDirections/MBVisualInstructionBanner.swift @@ -1,11 +1,13 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif /** A visual instruction banner contains all the information necessary for creating a visual cue about a given `RouteStep`. */ -@objc(MBVisualInstructionBanner) +@objcMembers open class VisualInstructionBanner: NSObject, NSSecureCoding { /** @@ -16,19 +18,19 @@ open class VisualInstructionBanner: NSObject, NSSecureCoding { /** The most important information to convey to the user about the `RouteStep`. */ - @objc public let primaryInstruction: VisualInstruction + public let primaryInstruction: VisualInstruction /** Less important details about the `RouteStep`. */ - @objc public let secondaryInstruction: VisualInstruction? + public let secondaryInstruction: VisualInstruction? /** A visual instruction that is presented simultaneously to provide information about an additional maneuver that occurs in rapid succession. This instruction could either contain the visual layout information or the lane information about the upcoming maneuver. */ - @objc public let tertiaryInstruction: VisualInstruction? + public let tertiaryInstruction: VisualInstruction? /** Which side of a bidirectional road the driver should drive on, also known as the rule of the road. @@ -71,7 +73,7 @@ open class VisualInstructionBanner: NSObject, NSSecureCoding { - parameter secondaryInstruction: Less important details about the `RouteStep`. - parameter drivingSide: Which side of a bidirectional road the driver should drive on. */ - @objc public init(distanceAlongStep: CLLocationDistance, primaryInstruction: VisualInstruction, secondaryInstruction: VisualInstruction?, tertiaryInstruction: VisualInstruction?, drivingSide: DrivingSide) { + public init(distanceAlongStep: CLLocationDistance, primaryInstruction: VisualInstruction, secondaryInstruction: VisualInstruction?, tertiaryInstruction: VisualInstruction?, drivingSide: DrivingSide) { self.distanceAlongStep = distanceAlongStep self.primaryInstruction = primaryInstruction self.secondaryInstruction = secondaryInstruction diff --git a/Sources/MapboxDirections/MBVisualInstructionComponent.swift b/Sources/MapboxDirections/MBVisualInstructionComponent.swift index f4dd0b73b..373a69427 100644 --- a/Sources/MapboxDirections/MBVisualInstructionComponent.swift +++ b/Sources/MapboxDirections/MBVisualInstructionComponent.swift @@ -1,15 +1,17 @@ +import Foundation #if os(OSX) import Cocoa #elseif os(watchOS) import WatchKit -#else +#elseif !os(Linux) import UIKit #endif + /** A component of a `VisualInstruction` that represents a single run of similarly formatted text or an image with a textual fallback representation. */ -@objc(MBVisualInstructionComponent) +@objcMembers open class VisualInstructionComponent: NSObject, ComponentRepresentable { /** @@ -17,31 +19,31 @@ open class VisualInstructionComponent: NSObject, ComponentRepresentable { The URL refers to an image that uses the device’s native screen scale. */ - @objc public var imageURL: URL? + public var imageURL: URL? /** An abbreviated representation of the `text` property. */ - @objc public var abbreviation: String? + public var abbreviation: String? /** The priority for which the component should be abbreviated. A component with a lower abbreviation priority value should be abbreviated before a component with a higher abbreviation priority value. */ - @objc public var abbreviationPriority: Int = NSNotFound + public var abbreviationPriority: Int = NSNotFound /** The plain text representation of this component. Use this property if `imageURL` is `nil` or if the URL contained in that property is not yet available. */ - @objc public var text: String? + public var text: String? /** The type of visual instruction component. You can display the component differently depending on its type. */ - @objc public var type: VisualInstructionComponentType + public var type: VisualInstructionComponentType public static var supportsSecureCoding: Bool = true @@ -65,8 +67,10 @@ open class VisualInstructionComponent: NSObject, ComponentRepresentable { scale = NSScreen.main?.backingScaleFactor ?? 1 #elseif os(watchOS) scale = WKInterfaceDevice.current().screenScale - #else + #elseif !os(Linux) scale = UIScreen.main.scale + #else + scale = 2 #endif imageURL = URL(string: "\(baseURL)@\(Int(scale))x.png") } @@ -91,7 +95,7 @@ open class VisualInstructionComponent: NSObject, ComponentRepresentable { self.abbreviationPriority = abbreviationPriority } - @objc public required init?(coder decoder: NSCoder) { + public required init?(coder decoder: NSCoder) { self.text = decoder.decodeObject(of: NSString.self, forKey: "text") as String? guard let typeString = decoder.decodeObject(of: NSString.self, forKey: "type") as String?, let type = VisualInstructionComponentType(description: typeString) else { diff --git a/Sources/MapboxDirections/MBWaypoint.swift b/Sources/MapboxDirections/MBWaypoint.swift index 7c4eb6052..b979bbffb 100644 --- a/Sources/MapboxDirections/MBWaypoint.swift +++ b/Sources/MapboxDirections/MBWaypoint.swift @@ -1,10 +1,13 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif /** A `Waypoint` object indicates a location along a route. It may be the route’s origin or destination, or it may be another location that the route visits. A waypoint object indicates the location’s geographic location along with other optional information, such as a name or the user’s direction approaching the waypoint. You create a `RouteOptions` object using waypoint objects and also receive waypoint objects in the completion handler of the `Directions.calculate(_:completionHandler:)` method. */ +@objcMembers @objc(MBWaypoint) open class Waypoint: NSObject, NSCopying, NSSecureCoding { // MARK: Creating a Waypoint Object @@ -22,7 +25,7 @@ open class Waypoint: NSObject, NSCopying, NSSecureCoding { It is recommended that the value of this parameter be greater than the `horizontalAccuracy` property of a `CLLocation` object obtained from a `CLLocationManager` object. There is a high likelihood that the user may be located some distance away from a navigable road, for instance if the user is currently on a driveway or inside a building. - parameter name: The name of the waypoint. This parameter does not affect the route but may help you to distinguish one waypoint from another. */ - @objc public init(coordinate: CLLocationCoordinate2D, coordinateAccuracy: CLLocationAccuracy = -1, name: String? = nil) { + public init(coordinate: CLLocationCoordinate2D, coordinateAccuracy: CLLocationAccuracy = -1, name: String? = nil) { self.coordinate = coordinate self.coordinateAccuracy = coordinateAccuracy self.name = name @@ -56,7 +59,7 @@ open class Waypoint: NSObject, NSCopying, NSSecureCoding { - parameter heading: A `CLHeading` object representing the direction from which the route must approach the waypoint in order to be considered viable. This initializer respects the `CLHeading` class’s `trueHeading` property or `magneticHeading` property, converting it into the `headingAccuracy` property. - parameter name: The name of the waypoint. This parameter does not affect the route but may help you to distinguish one waypoint from another. */ - @objc public init(location: CLLocation, heading: CLHeading? = nil, name: String? = nil) { + public init(location: CLLocation, heading: CLHeading? = nil, name: String? = nil) { coordinate = location.coordinate coordinateAccuracy = location.horizontalAccuracy if let heading = heading { @@ -131,7 +134,7 @@ open class Waypoint: NSObject, NSCopying, NSSecureCoding { /** The geographic coordinate of the waypoint. */ - @objc public internal(set) var coordinate: CLLocationCoordinate2D + public internal(set) var coordinate: CLLocationCoordinate2D /** The radius of uncertainty for the waypoint, measured in meters. @@ -153,7 +156,7 @@ open class Waypoint: NSObject, NSCopying, NSSecureCoding { This property corresponds to the [`waypoint_targets`](https://docs.mapbox.com/api/navigation/#retrieve-directions) query parameter in the Mapbox Directions and Map Matching APIs. */ - @objc open var targetCoordinate: CLLocationCoordinate2D = kCLLocationCoordinate2DInvalid + open var targetCoordinate: CLLocationCoordinate2D = kCLLocationCoordinate2DInvalid // MARK: Specifying How the User Approaches the Waypoint diff --git a/Sources/MapboxDirections/Match/MBMatch.swift b/Sources/MapboxDirections/Match/MBMatch.swift index 1bc38b628..6e22b5005 100644 --- a/Sources/MapboxDirections/Match/MBMatch.swift +++ b/Sources/MapboxDirections/Match/MBMatch.swift @@ -1,7 +1,10 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif import Polyline + /** A `Match` object defines a single route that was created from a series of points that were matched against a road network. diff --git a/Sources/MapboxDirections/Match/MBMatchOptions.swift b/Sources/MapboxDirections/Match/MBMatchOptions.swift index 9c1babcbb..4d83d11ab 100644 --- a/Sources/MapboxDirections/Match/MBMatchOptions.swift +++ b/Sources/MapboxDirections/Match/MBMatchOptions.swift @@ -1,5 +1,7 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif /** @@ -8,7 +10,6 @@ import CoreLocation Pass an instance of this class into the `Directions.calculate(_:completionHandler:)` method. */ @objcMembers -@objc(MBMatchOptions) open class MatchOptions: DirectionsOptions { /** diff --git a/Sources/MapboxDirections/Match/MBTracepoint.swift b/Sources/MapboxDirections/Match/MBTracepoint.swift index cf281d01f..93756894e 100644 --- a/Sources/MapboxDirections/Match/MBTracepoint.swift +++ b/Sources/MapboxDirections/Match/MBTracepoint.swift @@ -1,5 +1,7 @@ import Foundation +#if !os(Linux) import CoreLocation +#endif /** diff --git a/Sources/MapboxDirections/OfflineDirections.swift b/Sources/MapboxDirections/OfflineDirections.swift index facae81f4..91cd706bc 100644 --- a/Sources/MapboxDirections/OfflineDirections.swift +++ b/Sources/MapboxDirections/OfflineDirections.swift @@ -10,7 +10,6 @@ struct AvailableVersionsResponse: Codable { let availableVersions: [String] } -@objc(MBOfflineDirectionsProtocol) public protocol OfflineDirectionsProtocol { /** diff --git a/Sources/MapboxDirections/SPM/CoreLocation.swift b/Sources/MapboxDirections/SPM/CoreLocation.swift index 7bba1dca6..ce7fc2399 100644 --- a/Sources/MapboxDirections/SPM/CoreLocation.swift +++ b/Sources/MapboxDirections/SPM/CoreLocation.swift @@ -3,6 +3,13 @@ import Foundation #if os(Linux) +public let kCLLocationCoordinate2DInvalid = CLLocationCoordinate2D(latitude: -180, longitude: -180) +public func CLLocationCoordinate2DIsValid(_ coord: CLLocationCoordinate2D) -> Bool { + // TODO: this should probably be within -90,90,-180,180 + return coord.latitude != kCLLocationCoordinate2DInvalid.latitude && + coord.longitude != kCLLocationCoordinate2DInvalid.longitude +} + public typealias CLLocationDegrees = Double public typealias CLLocationSpeed = Double public typealias CLLocationDirection = Double @@ -16,24 +23,46 @@ public struct CLLocationCoordinate2D { public struct CLLocation { public let coordinate: CLLocationCoordinate2D + public let altitude: CLLocationDistance public let horizontalAccuracy: CLLocationAccuracy public let verticalAccuracy: CLLocationAccuracy public let speed: CLLocationSpeed public let course: CLLocationDirection public let timestamp: Date - - public init(coordinate: CLLocationCoordinate2D) { - self.coordinate = coordinate - self.horizontalAccuracy = -1 - self.verticalAccuracy = -1 - self.speed = -1 - self.course = -1 - self.timestamp = Date() - } + + public init(coordinate: CLLocationCoordinate2D, + altitude: CLLocationDistance, + horizontalAccuracy: CLLocationAccuracy, + verticalAccuracy: CLLocationAccuracy, + course: CLLocationDirection, + speed: CLLocationSpeed, + timestamp: Date) { + self.coordinate = coordinate + self.altitude = altitude + self.horizontalAccuracy = horizontalAccuracy + self.verticalAccuracy = verticalAccuracy + self.course = course + self.speed = speed + self.timestamp = timestamp + } public init(latitude: CLLocationDegrees, longitude: CLLocationDegrees) { self.init(coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude)) } } +public class CLHeading: NSObject { + public let magneticHeading: CLLocationDirection + public let trueHeading: CLLocationDirection + public let headingAccuracy: CLLocationDirection + public let timestamp: Date + + public init(magneticHeading: CLLocationDirection, trueHeading: CLLocationDirection, headingAccuracy: CLLocationDirection, timestamp: Date) { + self.magneticHeading = magneticHeading + self.trueHeading = trueHeading + self.headingAccuracy = headingAccuracy + self.timestamp = timestamp + } +} + #endif