From 80c9a615a8e8f5691bf464cc50c41df01b2d0b12 Mon Sep 17 00:00:00 2001 From: Ana Paula Date: Wed, 28 Sep 2016 15:02:47 -0300 Subject: [PATCH] Swift 3.0 compatibility --- Compass.xcodeproj/project.pbxproj | 6 ++++++ Sources/Compass.swift | 20 +++++++++--------- Sources/Router.swift | 12 +++++------ Sources/String+Extensions.swift | 34 +++++++++++++++---------------- Sources/TypeAlias.swift | 8 ++++---- Tests/Compass/CompassTests.swift | 34 +++++++++++++++---------------- Tests/Compass/Helpers.swift | 16 +++++++-------- 7 files changed, 68 insertions(+), 62 deletions(-) diff --git a/Compass.xcodeproj/project.pbxproj b/Compass.xcodeproj/project.pbxproj index cd7a1c6..9f0d6bb 100644 --- a/Compass.xcodeproj/project.pbxproj +++ b/Compass.xcodeproj/project.pbxproj @@ -263,9 +263,11 @@ TargetAttributes = { D5B2E89E1C3A780C00C0327D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0810; }; D5B2E8A81C3A780C00C0327D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0810; }; D5C6293F1C3A7FAA007F7B7C = { CreatedOnToolsVersion = 7.2; @@ -495,6 +497,7 @@ PRODUCT_NAME = Compass; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -514,6 +517,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Compass-iOS"; PRODUCT_NAME = Compass; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -527,6 +531,7 @@ PRODUCT_BUNDLE_IDENTIFIER = no.hyper.CompassTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -539,6 +544,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.CompassTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Sources/Compass.swift b/Sources/Compass.swift index 743296c..100b62b 100644 --- a/Sources/Compass.swift +++ b/Sources/Compass.swift @@ -8,7 +8,7 @@ public struct Compass { concreteMatchCount: Int, wildcardMatchCount: Int) - private static var internalScheme = "" + fileprivate static var internalScheme = "" public static var delimiter: String = ":" public static var scheme: String { @@ -18,16 +18,16 @@ public struct Compass { public static var routes = [String]() - public static func parse(url: NSURL, payload: Any? = nil) -> Location? { - let path = url.absoluteString.substringFromIndex(scheme.endIndex) + public static func parse(_ url: URL, payload: Any? = nil) -> Location? { + let path = url.absoluteString.substring(from: scheme.endIndex) - guard !(path.containsString("?") || path.containsString("#")) else { + guard !(path.contains("?") || path.contains("#")) else { return parseAsURL(url, payload: payload) } let results: [Result] = routes.flatMap { return findMatch($0, pathString: path) - }.sort { (r1: Result, r2: Result) in + }.sorted { (r1: Result, r2: Result) in if r1.concreteMatchCount == r2.concreteMatchCount { return r1.wildcardMatchCount > r2.wildcardMatchCount } @@ -42,10 +42,10 @@ public struct Compass { return nil } - static func parseAsURL(url: NSURL, payload: Any? = nil) -> Location? { + static func parseAsURL(_ url: URL, payload: Any? = nil) -> Location? { guard let route = url.host else { return nil } - let urlComponents = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) + let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) var arguments = [String : String]() urlComponents?.queryItems?.forEach { queryItem in @@ -59,7 +59,7 @@ public struct Compass { return Location(path: route, arguments: arguments, payload: payload) } - static func findMatch(routeString: String, pathString: String) -> Result? { + static func findMatch(_ routeString: String, pathString: String) -> Result? { let routes = routeString.split(delimiter) let paths = pathString.split(delimiter) @@ -94,8 +94,8 @@ public struct Compass { extension Compass { - public static func navigate(urn: String, scheme: String = Compass.scheme) { - guard let url = NSURL(string: "\(scheme)\(urn)") else { return } + public static func navigate(_ urn: String, scheme: String = Compass.scheme) { + guard let url = URL(string: "\(scheme)\(urn)") else { return } openURL(url) } } diff --git a/Sources/Router.swift b/Sources/Router.swift index 94891a2..127fce0 100644 --- a/Sources/Router.swift +++ b/Sources/Router.swift @@ -1,7 +1,7 @@ -public enum RouteError: ErrorType { - case NotFound - case InvalidArguments(Location) - case InvalidPayload(Location) +public enum RouteError: Error { + case notFound + case invalidArguments(Location) + case invalidPayload(Location) } public protocol Routable { @@ -11,7 +11,7 @@ public protocol Routable { public protocol ErrorRoutable { - func handle(routeError: ErrorType, from currentController: Controller) + func handle(_ routeError: Error, from currentController: Controller) } public struct Router: Routable { @@ -23,7 +23,7 @@ public struct Router: Routable { public func navigate(to location: Location, from currentController: Controller) { guard let route = routes[location.path] else { - errorRoute?.handle(RouteError.NotFound, from: currentController) + errorRoute?.handle(RouteError.notFound, from: currentController) return } diff --git a/Sources/String+Extensions.swift b/Sources/String+Extensions.swift index eacc3e9..4009156 100644 --- a/Sources/String+Extensions.swift +++ b/Sources/String+Extensions.swift @@ -1,31 +1,31 @@ import Foundation extension String { - - func split(delimiter: String) -> [String] { - let components = componentsSeparatedByString(delimiter) + + func split(_ delimiter: String) -> [String] { + let components = self.components(separatedBy: delimiter) return components != [""] ? components : [] } - - func replace(string: String, with withString: String) -> String { - return stringByReplacingOccurrencesOfString(string, withString: withString) + + func replace(_ string: String, with withString: String) -> String { + return replacingOccurrences(of: string, with: withString) } - + func queryParameters() -> [String: String] { var parameters = [String: String]() - - let separatorCharacters = NSCharacterSet(charactersInString: "&;") - self.componentsSeparatedByCharactersInSet(separatorCharacters).forEach { (pair) in - - if let equalSeparator = pair.rangeOfString("=") { - let name = pair.substringToIndex(equalSeparator.startIndex) - let value = pair.substringFromIndex(equalSeparator.startIndex.advancedBy(1)) - let cleaned = value.stringByRemovingPercentEncoding ?? value - + + let separatorCharacters = CharacterSet(charactersIn: "&;") + self.components(separatedBy: separatorCharacters).forEach { (pair) in + + if let equalSeparator = pair.range(of: "=") { + let name = pair.substring(to: equalSeparator.lowerBound) + let value = pair.substring(from: pair.index(equalSeparator.lowerBound, offsetBy: 1)) + let cleaned = value.removingPercentEncoding ?? value + parameters[name] = cleaned } } - + return parameters } } diff --git a/Sources/TypeAlias.swift b/Sources/TypeAlias.swift index 2fcabf7..96e5bfd 100644 --- a/Sources/TypeAlias.swift +++ b/Sources/TypeAlias.swift @@ -6,14 +6,14 @@ #if os(OSX) public typealias Controller = NSViewController - + func openURL(URL: NSURL) { NSWorkspace.sharedWorkspace().openURL(URL) } #else public typealias Controller = UIViewController - - func openURL(URL: NSURL) { - UIApplication.sharedApplication().openURL(URL) + + func openURL(_ URL: Foundation.URL) { + UIApplication.shared.openURL(URL) } #endif diff --git a/Tests/Compass/CompassTests.swift b/Tests/Compass/CompassTests.swift index 21a3fe0..b66cb9b 100644 --- a/Tests/Compass/CompassTests.swift +++ b/Tests/Compass/CompassTests.swift @@ -27,7 +27,7 @@ class CompassTests: XCTestCase { } func testParseArguments() { - let url = NSURL(string: "compassTests://profile:testUser")! + let url = URL(string: "compassTests://profile:testUser")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -39,7 +39,7 @@ class CompassTests: XCTestCase { } func testParsePayload() { - let url = NSURL(string: "compassTests://profile:testUser")! + let url = URL(string: "compassTests://profile:testUser")! typealias Payload = (firstName: String, lastName: String) @@ -55,7 +55,7 @@ class CompassTests: XCTestCase { } func testParseRouteConcreateMatchCount() { - let url = NSURL(string: "compassTests://profile:admin")! + let url = URL(string: "compassTests://profile:admin")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -67,7 +67,7 @@ class CompassTests: XCTestCase { } func testParseRouteWildcardMatchCount() { - let url = NSURL(string: "compassTests://profile:jack")! + let url = URL(string: "compassTests://profile:jack")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -79,7 +79,7 @@ class CompassTests: XCTestCase { } func testParseRouteSamePrefix() { - let url = NSURL(string: "compassTests://user:list")! + let url = URL(string: "compassTests://user:list")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -91,7 +91,7 @@ class CompassTests: XCTestCase { } func testParseMultipleArguments() { - let url = NSURL(string: "compassTests://user:list:1:admin")! + let url = URL(string: "compassTests://user:list:1:admin")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -104,7 +104,7 @@ class CompassTests: XCTestCase { } func testParseMultipleArgumentsWithFirstWildcard() { - let url = NSURL(string: "compassTests://12:user:list:1:admin")! + let url = URL(string: "compassTests://12:user:list:1:admin")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -118,7 +118,7 @@ class CompassTests: XCTestCase { } func testParseWithoutArguments() { - let url = NSURL(string: "compassTests://login")! + let url = URL(string: "compassTests://login")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -130,7 +130,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithFragments() { - let url = NSURL(string: "compassTests://callback/#access_token=IjvcgrkQk1p7TyJxKa26rzM1wBMFZW6XoHK4t5Gkt1xQLTN8l7ppR0H3EZXpoP0uLAN49oCDqTHsvnEV&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback/#access_token=IjvcgrkQk1p7TyJxKa26rzM1wBMFZW6XoHK4t5Gkt1xQLTN8l7ppR0H3EZXpoP0uLAN49oCDqTHsvnEV&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -145,7 +145,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithFragmentsAndGoogleOAuth2AccessToken() { - let url = NSURL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -160,7 +160,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithFragmentsAndAlternativeAccessToken() { - let url = NSURL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -175,7 +175,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithSlashQuery() { - let url = NSURL(string: "compassTests://callback/?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback/?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -190,7 +190,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithSlashQueryAndGoogleOAuth2AccessToken() { - let url = NSURL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -205,7 +205,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithSlashQueryAndAlternativeAccessToken() { - let url = NSURL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -220,7 +220,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithQuery() { - let url = NSURL(string: "compassTests://callback?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -235,7 +235,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithQueryAndGoogleOAuth2AccessToken() { - let url = NSURL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") @@ -250,7 +250,7 @@ class CompassTests: XCTestCase { } func testParseRegularURLWithQueryAndAlternativeAccessToken() { - let url = NSURL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! + let url = URL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! guard let location = Compass.parse(url) else { XCTFail("Compass parsing failed") diff --git a/Tests/Compass/Helpers.swift b/Tests/Compass/Helpers.swift index 68e7061..2130e74 100644 --- a/Tests/Compass/Helpers.swift +++ b/Tests/Compass/Helpers.swift @@ -14,36 +14,36 @@ class TestRoute: Routable { class ThrowableRoute: Routable { - enum Error: ErrorType { - case Unknown + enum Error: Error { + case unknown } func navigate(to location: Location, from currentController: Controller) throws { - throw Error.Unknown + throw Error.unknown } } class ErrorRoute: ErrorRoutable { - var error: ErrorType? + var error: Error? - func handle(routeError: ErrorType, from currentController: Controller) { + func handle(_ routeError: Error, from currentController: Controller) { error = routeError } } // MARK: - Shuffle -extension CollectionType { +extension Collection { /// Return a copy of `self` with its elements shuffled - func shuffle() -> [Generator.Element] { + func shuffle() -> [Iterator.Element] { var list = Array(self) list.shuffleInPlace() return list } } -extension MutableCollectionType where Index == Int { +extension MutableCollection where Index == Int { /// Shuffle the elements of `self` in-place. mutating func shuffleInPlace() { // empty and single-element collections don't shuffle