From ce06b66f7276dc9ff03108934b183f0eecfd07bd Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 00:25:00 -0400 Subject: [PATCH 01/16] Upgrade xcconfigs for Xcode 9.3 --- Cartfile.private | 2 +- Cartfile.resolved | 2 +- Carthage/Checkouts/xcconfigs | 2 +- OneTimePassword.xcodeproj/project.pbxproj | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cartfile.private b/Cartfile.private index 3269cf46..02927c44 100644 --- a/Cartfile.private +++ b/Cartfile.private @@ -1,3 +1,3 @@ # Configuration for Carthage (https://github.com/Carthage/Carthage) -github "jspahrsummers/xcconfigs" ~> 0.11 +github "jspahrsummers/xcconfigs" ~> 0.12 diff --git a/Cartfile.resolved b/Cartfile.resolved index 0f12af37..aef3ef05 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1,2 @@ -github "jspahrsummers/xcconfigs" "0.11" +github "jspahrsummers/xcconfigs" "0.12" github "mattrubin/Base32" "xcode9" diff --git a/Carthage/Checkouts/xcconfigs b/Carthage/Checkouts/xcconfigs index 40f9bcc6..bb795558 160000 --- a/Carthage/Checkouts/xcconfigs +++ b/Carthage/Checkouts/xcconfigs @@ -1 +1 @@ -Subproject commit 40f9bcc63752cdd95deee267d2fbf9da09a9f6f2 +Subproject commit bb795558a76e5daf3688500055bbcfe243bffa8d diff --git a/OneTimePassword.xcodeproj/project.pbxproj b/OneTimePassword.xcodeproj/project.pbxproj index 33062460..2d9b383a 100644 --- a/OneTimePassword.xcodeproj/project.pbxproj +++ b/OneTimePassword.xcodeproj/project.pbxproj @@ -743,7 +743,6 @@ baseConfigurationReference = C996EC2E1A74D5830076B105 /* Release.xcconfig */; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 8.0; - SWIFT_COMPILATION_MODE = wholemodule; SWIFT_TREAT_WARNINGS_AS_ERRORS = NO; SWIFT_VERSION = 4.0; WATCHOS_DEPLOYMENT_TARGET = 2.0; From 8ef611aa2ab208c1ceb4e50d9e6a047898cf9d18 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 00:20:03 -0400 Subject: [PATCH 02/16] Synthesize Equatable conformance when compiling with Swift 4.1 --- Sources/Generator.swift | 3 +++ Sources/PersistentToken.swift | 3 +++ Sources/Token.swift | 3 +++ 3 files changed, 9 insertions(+) diff --git a/Sources/Generator.swift b/Sources/Generator.swift index 664ca289..22be15c4 100644 --- a/Sources/Generator.swift +++ b/Sources/Generator.swift @@ -192,6 +192,8 @@ public struct Generator: Equatable { } } +#if swift(>=4.1) +#else /// Compares two `Generator`s for equality. public func == (lhs: Generator, rhs: Generator) -> Bool { return (lhs.factor == rhs.factor) @@ -211,6 +213,7 @@ public func == (lhs: Generator.Factor, rhs: Generator.Factor) -> Bool { return false } } +#endif // MARK: - Private diff --git a/Sources/PersistentToken.swift b/Sources/PersistentToken.swift index 2735a4d8..30da61a2 100644 --- a/Sources/PersistentToken.swift +++ b/Sources/PersistentToken.swift @@ -48,8 +48,11 @@ public struct PersistentToken: Equatable, Hashable { } } +#if swift(>=4.1) +#else /// Compares two `PersistentToken`s for equality. public func == (lhs: PersistentToken, rhs: PersistentToken) -> Bool { return (lhs.identifier == rhs.identifier) && (lhs.token == rhs.token) } +#endif diff --git a/Sources/Token.swift b/Sources/Token.swift index 55a4bbb7..3a192788 100644 --- a/Sources/Token.swift +++ b/Sources/Token.swift @@ -70,9 +70,12 @@ public struct Token: Equatable { } } +#if swift(>=4.1) +#else /// Compares two `Token`s for equality. public func == (lhs: Token, rhs: Token) -> Bool { return (lhs.name == rhs.name) && (lhs.issuer == rhs.issuer) && (lhs.generator == rhs.generator) } +#endif From e98205236ae5ec5bc3af3fd7f63d8eef2436b3c8 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 00:36:36 -0400 Subject: [PATCH 03/16] [ci] Attempt to build on CI with both Xcode 9.0 and Xcode 9.3 --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 347f0a3b..f4bfeb5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,9 @@ language: objective-c xcode_workspace: OneTimePassword.xcworkspace xcode_scheme: OneTimePassword (iOS) -osx_image: xcode9 +osx_image: + - xcode9 + - xcode9.3 env: - RUNTIME="iOS 8.1" DEVICE="iPad 2" From a81a94160a61e90b5377dcfbef03e123bcfb9dcd Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 00:39:53 -0400 Subject: [PATCH 04/16] [ci] Attempt to include a single Xcode 9.0 (Swift 4.0) build on CI --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f4bfeb5b..ad748de9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,7 @@ language: objective-c xcode_workspace: OneTimePassword.xcworkspace xcode_scheme: OneTimePassword (iOS) -osx_image: - - xcode9 - - xcode9.3 +osx_image: xcode9.3 env: - RUNTIME="iOS 8.1" DEVICE="iPad 2" @@ -21,6 +19,8 @@ env: # Include builds for watchOS matrix: include: + - osx_image: xcode9 + env: RUNTIME="iOS 11.0" DEVICE="iPhone X" - xcode_scheme: OneTimePassword (watchOS) env: BUILD_ONLY="YES" RUNTIME="watchOS 4.0" DEVICE="Apple Watch Series 3 - 38mm" - xcode_scheme: OneTimePassword (watchOS) From 0758a24368c680ea9ff4f8001d76b4bb835b1197 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 01:38:21 -0400 Subject: [PATCH 05/16] [ci] Try to mitigate xcodebuild failure 65 by using `travis_retry` --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ad748de9..f2ce7fc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ before_script: - if [[ $BUILD_ONLY == YES ]]; then ACTIONS="build"; else ACTIONS="build-for-testing test-without-building"; fi - echo "xcodebuild -workspace \"$TRAVIS_XCODE_WORKSPACE\" -scheme \"$TRAVIS_XCODE_SCHEME\" -destination \"id=$DESTINATION_ID\" $ACTIONS" -script: set -o pipefail && xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" -destination "id=$DESTINATION_ID" $ACTIONS | xcpretty -c +script: set -o pipefail && travis_retry xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" -destination "id=$DESTINATION_ID" $ACTIONS | xcpretty -c after_success: - bash <(curl -s https://codecov.io/bash) From e14797ec059ec7d6853fd5793748fd73f1f2e982 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 12:55:06 -0400 Subject: [PATCH 06/16] [ci] Add a CI test run for iOS 11.3 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f2ce7fc4..15fac624 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,8 @@ env: - RUNTIME="iOS 9.3" DEVICE="iPhone 6s" - RUNTIME="iOS 10.0" DEVICE="iPhone SE" - RUNTIME="iOS 10.3" DEVICE="iPhone 7 Plus" - - RUNTIME="iOS 11.0" DEVICE="iPhone X" + - RUNTIME="iOS 11.0" DEVICE="iPhone 8" + - RUNTIME="iOS 11.3" DEVICE="iPhone X" # Include builds for watchOS matrix: From 24a97f119485181faac826b5fedcb10b28941176 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 12:58:03 -0400 Subject: [PATCH 07/16] [ci] Add a CI job for Xcode 9.2 and iOS 8.4 and remove broken 8.x jobs --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 15fac624..c4c81483 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,6 @@ xcode_scheme: OneTimePassword (iOS) osx_image: xcode9.3 env: - - RUNTIME="iOS 8.1" DEVICE="iPad 2" - - RUNTIME="iOS 8.4" DEVICE="iPhone 4s" - RUNTIME="iOS 9.0" DEVICE="iPhone 5s" - RUNTIME="iOS 9.3" DEVICE="iPhone 6s" - RUNTIME="iOS 10.0" DEVICE="iPhone SE" @@ -20,8 +18,13 @@ env: # Include builds for watchOS matrix: include: + # Include an Xcode 9.0 build to test Swift 4.0 support - osx_image: xcode9 env: RUNTIME="iOS 11.0" DEVICE="iPhone X" + # Include an Xcode 9.2 build to test on iOS 8.x, because Xcode 9.3's iOS 8 simulator fails to launch + - osx_image: xcode9.2 + env: RUNTIME="iOS 8.4" DEVICE="iPhone 4s" + # Include several build-only jobs for watchOS - xcode_scheme: OneTimePassword (watchOS) env: BUILD_ONLY="YES" RUNTIME="watchOS 4.0" DEVICE="Apple Watch Series 3 - 38mm" - xcode_scheme: OneTimePassword (watchOS) From 801c5159e58c14378b3986d412669cab64732de9 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 13:13:44 -0400 Subject: [PATCH 08/16] [ci] Update the watchOS 4 job to use watchOS 4.3 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c4c81483..0384532d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ matrix: env: RUNTIME="iOS 8.4" DEVICE="iPhone 4s" # Include several build-only jobs for watchOS - xcode_scheme: OneTimePassword (watchOS) - env: BUILD_ONLY="YES" RUNTIME="watchOS 4.0" DEVICE="Apple Watch Series 3 - 38mm" + env: BUILD_ONLY="YES" RUNTIME="watchOS 4.3" DEVICE="Apple Watch Series 3 - 38mm" - xcode_scheme: OneTimePassword (watchOS) env: BUILD_ONLY="YES" RUNTIME="watchOS 3.2" DEVICE="Apple Watch Series 2 - 42mm" - xcode_scheme: OneTimePassword (watchOS) From 783ea7194b8c9d238f35ab6fbcaabb42d4203d9f Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 13:16:34 -0400 Subject: [PATCH 09/16] [ci] Reduce the number of CI jobs To reduce time spent waiting for the CI jobs, remove tests against the x.0 version of each major iOS version. --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0384532d..e2b3ad19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,8 @@ xcode_scheme: OneTimePassword (iOS) osx_image: xcode9.3 env: - - RUNTIME="iOS 9.0" DEVICE="iPhone 5s" - RUNTIME="iOS 9.3" DEVICE="iPhone 6s" - - RUNTIME="iOS 10.0" DEVICE="iPhone SE" - RUNTIME="iOS 10.3" DEVICE="iPhone 7 Plus" - - RUNTIME="iOS 11.0" DEVICE="iPhone 8" - RUNTIME="iOS 11.3" DEVICE="iPhone X" # Include builds for watchOS @@ -20,7 +17,7 @@ matrix: include: # Include an Xcode 9.0 build to test Swift 4.0 support - osx_image: xcode9 - env: RUNTIME="iOS 11.0" DEVICE="iPhone X" + env: RUNTIME="iOS 11.0" DEVICE="iPhone 8" # Include an Xcode 9.2 build to test on iOS 8.x, because Xcode 9.3's iOS 8 simulator fails to launch - osx_image: xcode9.2 env: RUNTIME="iOS 8.4" DEVICE="iPhone 4s" From 3111dcca11970ded19306c9a99596454bb1be4c2 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 13:17:53 -0400 Subject: [PATCH 10/16] [ci] Remove the travis_retry command --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e2b3ad19..cddaa703 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ before_script: - if [[ $BUILD_ONLY == YES ]]; then ACTIONS="build"; else ACTIONS="build-for-testing test-without-building"; fi - echo "xcodebuild -workspace \"$TRAVIS_XCODE_WORKSPACE\" -scheme \"$TRAVIS_XCODE_SCHEME\" -destination \"id=$DESTINATION_ID\" $ACTIONS" -script: set -o pipefail && travis_retry xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" -destination "id=$DESTINATION_ID" $ACTIONS | xcpretty -c +script: set -o pipefail && xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" -destination "id=$DESTINATION_ID" $ACTIONS | xcpretty -c after_success: - bash <(curl -s https://codecov.io/bash) From a722b66a5799fdfa3850eb74167bac80ddb7a642 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 17:27:05 -0400 Subject: [PATCH 11/16] Remove the cross-module Generator initializer, and fix invalid tests Cross-module struct initializers which set properties directly are deprecated in Swift 4.1, and will be an error in Swift 5. The fact that a custom initializer was needed to construct the invalid Generators used by the test is indicative of a design flaw in the tests. If creating an invalid Generator with the library's default API is not possible, then testing such impossible-to-create invalid Generators is unnecessary. It is enough to test that attempts to create these invalid generators will fail. --- Tests/GeneratorTests.swift | 46 +++++++------------------------------- 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/Tests/GeneratorTests.swift b/Tests/GeneratorTests.swift index f82c9ec9..d2449f65 100644 --- a/Tests/GeneratorTests.swift +++ b/Tests/GeneratorTests.swift @@ -174,35 +174,17 @@ class GeneratorTests: XCTestCase { } func testPasswordWithInvalidPeriod() { - let generator = Generator(unvalidatedFactor: .timer(period: 0)) - let time = Date(timeIntervalSince1970: 100) - - do { - _ = try generator.password(at: time) - } catch Generator.Error.invalidPeriod { - // This is the expected type of error - return - } catch { - XCTFail("passwordAtTime(\(time)) threw an unexpected type of error: \(error))") - return - } - XCTFail("passwordAtTime(\(time)) should throw an error)") + // It should not be possible to try to get a password from a generator with an invalid period, because the + // generator initializer should fail when given an invalid period. + let generator = Generator(factor: .timer(period: 0), secret: Data(), algorithm: .sha1, digits: 8) + XCTAssertNil(generator) } func testPasswordWithInvalidDigits() { - let generator = Generator(unvalidatedDigits: 3) - let time = Date(timeIntervalSince1970: 100) - - do { - _ = try generator.password(at: time) - } catch Generator.Error.invalidDigits { - // This is the expected type of error - return - } catch { - XCTFail("passwordAtTime(\(time)) threw an unexpected type of error: \(error))") - return - } - XCTFail("passwordAtTime(\(time)) should throw an error)") + // It should not be possible to try to get a password from a generator with an invalid digit count, because the + // generator initializer should fail when given an invalid digit count. + let generator = Generator(factor: .timer(period: 30), secret: Data(), algorithm: .sha1, digits: 3) + XCTAssertNil(generator) } // The values in this test are found in Appendix D of the HOTP RFC @@ -283,15 +265,3 @@ class GeneratorTests: XCTestCase { } } } - -private extension Generator { - init(unvalidatedFactor factor: Factor = .timer(period: 30), - unvalidatedSecret secret: Data = Data(), - unvalidatedAlgorithm algorithm: Algorithm = .sha1, - unvalidatedDigits digits: Int = 8) { - self.factor = factor - self.secret = secret - self.algorithm = algorithm - self.digits = digits - } -} From 0c38045fbc8336e03eafe58a29b74f04f4a1d6ce Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sat, 21 Apr 2018 19:04:12 -0400 Subject: [PATCH 12/16] [lint] Enable several new SwiftLint opt-in rules --- .swiftlint.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.swiftlint.yml b/.swiftlint.yml index 35945f22..86fc1ea4 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -11,7 +11,9 @@ opt_in_rules: - contains_over_first_not_nil - discouraged_object_literal - discouraged_optional_boolean + - discouraged_optional_collection - empty_count + - empty_string - explicit_enum_raw_value - explicit_init - extension_access_modifier @@ -23,6 +25,7 @@ opt_in_rules: - joined_default_parameter - let_var_whitespace - literal_expression_end_indentation + - lower_acl_than_parent - multiline_parameters - nimble_operator - operator_usage_whitespace @@ -36,6 +39,7 @@ opt_in_rules: - sorted_first_last - switch_case_on_newline - unneeded_parentheses_in_closure_argument + - untyped_error_in_catch - vertical_parameter_alignment_on_call - yoda_condition disabled_rules: From f82884cb26be77267705e9dc68bbeba3c5380466 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Mon, 23 Apr 2018 17:08:47 -0400 Subject: [PATCH 13/16] Bump the version number to 3.1.2 --- OneTimePassword.podspec | 2 +- Sources/Info.plist | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OneTimePassword.podspec b/OneTimePassword.podspec index 437c2154..f988c7b4 100644 --- a/OneTimePassword.podspec +++ b/OneTimePassword.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "OneTimePassword" - s.version = "3.1.1" + s.version = "3.1.2" s.summary = "A small library for generating TOTP and HOTP one-time passwords." s.homepage = "https://github.com/mattrubin/OneTimePassword" s.license = "MIT" diff --git a/Sources/Info.plist b/Sources/Info.plist index ae3a3e0f..ba9f4e86 100644 --- a/Sources/Info.plist +++ b/Sources/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.1.1 + 3.1.2 CFBundleSignature ???? CFBundleVersion - 3.1.1 + 3.1.2 NSPrincipalClass From ef2fd1392caadf68ee052424484cf46aa249c734 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Mon, 23 Apr 2018 17:08:54 -0400 Subject: [PATCH 14/16] Update the changelog --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d013d3bc..8bda1496 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ +## [3.1.2][] (2018-04-23) +- Synthesize Equatable conformance when compiling with Swift 4.1. ([#173](https://github.com/mattrubin/OneTimePassword/pull/173)) +- Fix a warning about deprecation of cross-module struct initializers by simplifying test cases for impossible-to-create invalid Generators. ([#174](https://github.com/mattrubin/OneTimePassword/pull/174)) +- Upgrade xcconfigs for Xcode 9.3. ([#172](https://github.com/mattrubin/OneTimePassword/pull/172)) +- Enable several new SwiftLint opt-in rules. ([#175](https://github.com/mattrubin/OneTimePassword/pull/175)) + + ## [3.1.1][] (2018-03-31) - Add support for Swift 4.1. ([#168](https://github.com/mattrubin/OneTimePassword/pull/168)) - Update build and linter settings for Xcode 9.3. ([#167](https://github.com/mattrubin/OneTimePassword/pull/167)) @@ -148,8 +155,9 @@ Changes between prerelease versions of OneTimePassword version 2 can be found be ## [1.0.0][] (2014-07-17) -[develop]: https://github.com/mattrubin/OneTimePassword/compare/3.1.1...develop +[develop]: https://github.com/mattrubin/OneTimePassword/compare/3.1.2...develop +[3.1.1]: https://github.com/mattrubin/OneTimePassword/compare/3.1.1...3.1.2 [3.1.1]: https://github.com/mattrubin/OneTimePassword/compare/3.1...3.1.1 [3.1]: https://github.com/mattrubin/OneTimePassword/compare/3.0.1...3.1 [3.0.1]: https://github.com/mattrubin/OneTimePassword/compare/3.0...3.0.1 From ff3e1d9b46593b2984f3854a40192d5841ef9aab Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Mon, 23 Apr 2018 17:19:48 -0400 Subject: [PATCH 15/16] Fix changelog link for 3.1.2 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bda1496..7bb13ec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -157,7 +157,7 @@ Changes between prerelease versions of OneTimePassword version 2 can be found be [develop]: https://github.com/mattrubin/OneTimePassword/compare/3.1.2...develop -[3.1.1]: https://github.com/mattrubin/OneTimePassword/compare/3.1.1...3.1.2 +[3.1.2]: https://github.com/mattrubin/OneTimePassword/compare/3.1.1...3.1.2 [3.1.1]: https://github.com/mattrubin/OneTimePassword/compare/3.1...3.1.1 [3.1]: https://github.com/mattrubin/OneTimePassword/compare/3.0.1...3.1 [3.0.1]: https://github.com/mattrubin/OneTimePassword/compare/3.0...3.0.1 From bf24ffd5564f3a92bee582a9adcbba6e0707eba6 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Mon, 23 Apr 2018 17:32:34 -0400 Subject: [PATCH 16/16] Clarify Swift version compatibility in the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d98ce0f..1eb62664 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Then run `pod install` to install the latest version of the framework. ## Usage -> The [latest version][swift-4] of OneTimePassword uses Swift 4, and can be linked with Swift 3.2 projects using the Swift compiler's [compatibility mode](https://swift.org/blog/swift-4-0-released/#new-compatibility-modes). To use OneTimePassword with earlier versions of Swift, check out the [`swift-3`][swift-3] and [`swift-2.3`][swift-2.3] branches. To use OneTimePassword in an Objective-C based project, check out the [`objc` branch][objc] and the [1.x releases][releases]. +> The [latest version][swift-4] of OneTimePassword compiles with Swift 4.x, and can be linked with Swift 3.2+ projects using the Swift compiler's [compatibility mode](https://swift.org/blog/swift-4-0-released/#new-compatibility-modes). To use OneTimePassword with earlier versions of Swift, check out the [`swift-3`][swift-3] and [`swift-2.3`][swift-2.3] branches. To use OneTimePassword in an Objective-C based project, check out the [`objc` branch][objc] and the [1.x releases][releases]. [swift-4]: https://github.com/mattrubin/OneTimePassword/tree/swift-4 [swift-3]: https://github.com/mattrubin/OneTimePassword/tree/swift-3