From ca54c740e3b15042c184d38f0c2f4474829b1651 Mon Sep 17 00:00:00 2001 From: Jerrad Thramer Date: Wed, 8 Nov 2017 15:23:25 -0700 Subject: [PATCH 1/3] Adding support for `NSCopying` protocol. --- MapboxDirections/MBRouteOptions.swift | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/MapboxDirections/MBRouteOptions.swift b/MapboxDirections/MBRouteOptions.swift index 62245cc62..2d8a3edce 100644 --- a/MapboxDirections/MBRouteOptions.swift +++ b/MapboxDirections/MBRouteOptions.swift @@ -149,7 +149,7 @@ public enum MeasurementSystem: UInt, CustomStringConvertible { Pass an instance of this class into the `Directions.calculate(_:completionHandler:)` method. */ @objc(MBRouteOptions) -open class RouteOptions: NSObject, NSSecureCoding { +open class RouteOptions: NSObject, NSSecureCoding, NSCopying{ // MARK: Creating a Route Options Object /** @@ -458,6 +458,26 @@ open class RouteOptions: NSObject, NSSecureCoding { } return (waypoints, routes) } + + // MARK: NSCopying + /** + Returns a copy of the object. + - parameter zone: an NSZone to use in the copy operation. + - returns: A copy of the object. + */ + open func copy(with zone: NSZone? = nil) -> Any { + let copy = RouteOptions(waypoints: waypoints, profileIdentifier: profileIdentifier) + copy.allowsUTurnAtWaypoint = allowsUTurnAtWaypoint + copy.includesAlternativeRoutes = includesAlternativeRoutes + copy.includesSteps = includesSteps + copy.shapeFormat = shapeFormat + copy.routeShapeResolution = routeShapeResolution + copy.attributeOptions = attributeOptions + copy.includesExitRoundaboutManeuver = includesExitRoundaboutManeuver + copy.locale = locale + copy.includesSpokenInstructions = includesSpokenInstructions + return copy + } } // MARK: Support for Directions API v4 From 70a74fbe9e15911bf2bf4f8c516c512dde4c4d9e Mon Sep 17 00:00:00 2001 From: Jerrad Thramer Date: Wed, 8 Nov 2017 16:20:29 -0700 Subject: [PATCH 2/3] Adding NSEquality conformance and Unit Tests. --- MapboxDirections/MBRouteOptions.swift | 27 +++++++++--- MapboxDirectionsTests/RouteOptionsTests.swift | 42 +++++++++++++++---- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/MapboxDirections/MBRouteOptions.swift b/MapboxDirections/MBRouteOptions.swift index 2d8a3edce..f03258f01 100644 --- a/MapboxDirections/MBRouteOptions.swift +++ b/MapboxDirections/MBRouteOptions.swift @@ -460,11 +460,6 @@ open class RouteOptions: NSObject, NSSecureCoding, NSCopying{ } // MARK: NSCopying - /** - Returns a copy of the object. - - parameter zone: an NSZone to use in the copy operation. - - returns: A copy of the object. - */ open func copy(with zone: NSZone? = nil) -> Any { let copy = RouteOptions(waypoints: waypoints, profileIdentifier: profileIdentifier) copy.allowsUTurnAtWaypoint = allowsUTurnAtWaypoint @@ -478,6 +473,28 @@ open class RouteOptions: NSObject, NSSecureCoding, NSCopying{ copy.includesSpokenInstructions = includesSpokenInstructions return copy } + + //MARK: - OBJ-C Equality + open override func isEqual(_ object: Any?) -> Bool { + guard let opts = object as? RouteOptions else { return false } + return isEqual(to: opts) + } + + @objc(isEqualToRouteOptions:) + open func isEqual(to routeOptions: RouteOptions?) -> Bool { + guard let other = routeOptions else { return false } + guard waypoints == other.waypoints, + profileIdentifier == other.profileIdentifier, + allowsUTurnAtWaypoint == other.allowsUTurnAtWaypoint, + includesSteps == other.includesSteps, + shapeFormat == other.shapeFormat, + routeShapeResolution == other.routeShapeResolution, + attributeOptions == other.attributeOptions, + includesExitRoundaboutManeuver == other.includesExitRoundaboutManeuver, + locale == other.locale, + includesSpokenInstructions == other.includesSpokenInstructions else { return false } + return true + } } // MARK: Support for Directions API v4 diff --git a/MapboxDirectionsTests/RouteOptionsTests.swift b/MapboxDirectionsTests/RouteOptionsTests.swift index 684490ed2..c7b2f6f8c 100644 --- a/MapboxDirectionsTests/RouteOptionsTests.swift +++ b/MapboxDirectionsTests/RouteOptionsTests.swift @@ -3,15 +3,8 @@ import XCTest class RouteOptionsTests: XCTestCase { func testCoding() { - let coordinates = [ - CLLocationCoordinate2D(latitude: 52.5109, longitude: 13.4301), - CLLocationCoordinate2D(latitude: 52.5080, longitude: 13.4265), - CLLocationCoordinate2D(latitude: 52.5021, longitude: 13.4316), - ] - - let options = RouteOptions(coordinates: coordinates, profileIdentifier: .automobileAvoidingTraffic) - options.locale = Locale(identifier: "en") - + + let options = RouteOptions.testInstance let encodedData = NSMutableData() let keyedArchiver = NSKeyedArchiver(forWritingWith: encodedData) keyedArchiver.requiresSecureCoding = true @@ -25,6 +18,7 @@ class RouteOptionsTests: XCTestCase { XCTAssertNotNil(unarchivedOptions) + let coordinates = RouteOptions.testCoordinates let unarchivedWaypoints = unarchivedOptions.waypoints XCTAssertEqual(unarchivedWaypoints.count, coordinates.count) XCTAssertEqual(unarchivedWaypoints[0].coordinate.latitude, coordinates[0].latitude) @@ -39,4 +33,34 @@ class RouteOptionsTests: XCTestCase { XCTAssertEqual(unarchivedOptions.includesSpokenInstructions, options.includesSpokenInstructions) XCTAssertEqual(unarchivedOptions.distanceMeasurementSystem, options.distanceMeasurementSystem) } + func testCopying() { + let testInstance = RouteOptions.testInstance + guard let copy = testInstance.copy() as? RouteOptions else { return XCTFail("RouteOptions copy method should an object of same type") } + XCTAssertNotNil(copy, "Copy should not be nil.") + XCTAssertTrue(testInstance == copy, "Test Instance and copy should be semantically equivalent.") + XCTAssertFalse(testInstance === copy, "Test Instance and copy should not be identical.") + + } +} + +private extension RouteOptions { + static var testCoordinates: [CLLocationCoordinate2D] { + return [ + CLLocationCoordinate2D(latitude: 52.5109, longitude: 13.4301), + CLLocationCoordinate2D(latitude: 52.5080, longitude: 13.4265), + CLLocationCoordinate2D(latitude: 52.5021, longitude: 13.4316), + ] + } + static var testInstance: RouteOptions { + let opts = RouteOptions(coordinates: self.testCoordinates, profileIdentifier: .automobileAvoidingTraffic) + opts.locale = Locale(identifier: "en_US") + opts.allowsUTurnAtWaypoint = true + opts.shapeFormat = .polyline + opts.routeShapeResolution = .full + opts.attributeOptions = [.congestionLevel] + opts.includesExitRoundaboutManeuver = true + opts.includesSpokenInstructions = true + + return opts + } } From 0232a6f1b7dae6ccea41745ef5a2ab32f5697edc Mon Sep 17 00:00:00 2001 From: Jerrad Thramer Date: Wed, 8 Nov 2017 16:21:25 -0700 Subject: [PATCH 3/3] Adding missing critical properties to appropriate NSCoding/NSCopying/isEqual methods. --- MapboxDirections/MBRouteOptions.swift | 10 +++++++++- MapboxDirectionsTests/RouteOptionsTests.swift | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/MapboxDirections/MBRouteOptions.swift b/MapboxDirections/MBRouteOptions.swift index f03258f01..a44aafcfc 100644 --- a/MapboxDirections/MBRouteOptions.swift +++ b/MapboxDirections/MBRouteOptions.swift @@ -228,6 +228,11 @@ open class RouteOptions: NSObject, NSSecureCoding, NSCopying{ locale = decoder.decodeObject(of: NSLocale.self, forKey: "locale") as Locale? includesSpokenInstructions = decoder.decodeBool(forKey: "includesSpokenInstructions") + + guard let distanceMeasurementSystem = MeasurementSystem(description: decoder.decodeObject(of: NSString.self, forKey: "distanceMeasurementSystem") as String? ?? "") else { + return nil + } + self.distanceMeasurementSystem = distanceMeasurementSystem } open static var supportsSecureCoding = true @@ -244,6 +249,7 @@ open class RouteOptions: NSObject, NSSecureCoding, NSCopying{ coder.encode(includesExitRoundaboutManeuver, forKey: "includesExitRoundaboutManeuver") coder.encode(locale, forKey: "locale") coder.encode(includesSpokenInstructions, forKey: "includesSpokenInstructions") + coder.encode(distanceMeasurementSystem.description, forKey: "distanceMeasurementSystem") } // MARK: Specifying the Path of the Route @@ -471,6 +477,7 @@ open class RouteOptions: NSObject, NSSecureCoding, NSCopying{ copy.includesExitRoundaboutManeuver = includesExitRoundaboutManeuver copy.locale = locale copy.includesSpokenInstructions = includesSpokenInstructions + copy.distanceMeasurementSystem = distanceMeasurementSystem return copy } @@ -492,7 +499,8 @@ open class RouteOptions: NSObject, NSSecureCoding, NSCopying{ attributeOptions == other.attributeOptions, includesExitRoundaboutManeuver == other.includesExitRoundaboutManeuver, locale == other.locale, - includesSpokenInstructions == other.includesSpokenInstructions else { return false } + includesSpokenInstructions == other.includesSpokenInstructions, + distanceMeasurementSystem == other.distanceMeasurementSystem else { return false } return true } } diff --git a/MapboxDirectionsTests/RouteOptionsTests.swift b/MapboxDirectionsTests/RouteOptionsTests.swift index c7b2f6f8c..8ea568d4a 100644 --- a/MapboxDirectionsTests/RouteOptionsTests.swift +++ b/MapboxDirectionsTests/RouteOptionsTests.swift @@ -60,6 +60,7 @@ private extension RouteOptions { opts.attributeOptions = [.congestionLevel] opts.includesExitRoundaboutManeuver = true opts.includesSpokenInstructions = true + opts.distanceMeasurementSystem = .metric return opts }