Skip to content

Commit

Permalink
Increase the Swift version to 6.0 (#13)
Browse files Browse the repository at this point in the history
* Increase the Swift version to 6.0

* Add the `@retroactive` attribute

* Update `ci.yml`

* Fix `nonisolated(unsafe)` properties depending on the Swift version

* Update `CHANGELOG.md`

* Refactor unit tests for the UI module

* Update `ci.yml`
  • Loading branch information
ns-vasilev authored Dec 24, 2024
1 parent 93fd649 commit b6d7890
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 60 deletions.
92 changes: 64 additions & 28 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ jobs:
fail-fast: false
matrix:
include:
- xcode: "Xcode_16.0"
runsOn: macOS-14
name: "macOS 14, Xcode 16.0, Swift 6.0"
- xcode: "Xcode_15.4"
runsOn: macOS-14
name: "macOS 14, Xcode 15.4, Swift 5.10"
- xcode: "Xcode_15.0"
runsOn: macos-13
name: "macOS 13, Xcode 15.0, Swift 5.9.0"
Expand All @@ -44,16 +50,12 @@ jobs:
- uses: actions/checkout@v3
- name: ${{ matrix.name }}
run: xcodebuild test -scheme "Validator-Package" -destination "platform=macOS" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1
- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
- name: Upload test coverage reports to Codecov
uses: space-code/oss-common-actions/.github/actions/upload_test_coverage_report@main
with:
scheme_name: Typhoon
filename: ${{ matrix.name }}
token: ${{ secrets.CODECOV_TOKEN }}
xcode: true
xcode_archive_path: test_output/${{ matrix.name }}.xcresult
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: test_output

iOS:
name: ${{ matrix.name }}
Expand All @@ -65,6 +67,18 @@ jobs:
fail-fast: false
matrix:
include:
- destination: "OS=18.1,name=iPhone 16 Pro"
name: "iOS 18.1"
xcode: "Xcode_16.1"
runsOn: macOS-14
- destination: "OS=18.0,name=iPhone 16 Pro"
name: "iOS 18.0"
xcode: "Xcode_16.0"
runsOn: macOS-14
- destination: "OS=17.5,name=iPhone 15 Pro"
name: "iOS 17.5"
xcode: "Xcode_15.4"
runsOn: macOS-14
- destination: "OS=17.0.1,name=iPhone 14 Pro"
name: "iOS 17.0.1"
xcode: "Xcode_15.0"
Expand Down Expand Up @@ -92,6 +106,18 @@ jobs:
fail-fast: false
matrix:
include:
- destination: "OS=18.1,name=Apple TV"
name: "tvOS 18.1"
xcode: "Xcode_16.1"
runsOn: macOS-14
- destination: "OS=18.0,name=Apple TV"
name: "tvOS 18.0"
xcode: "Xcode_16.0"
runsOn: macOS-14
- destination: "OS=17.5,name=Apple TV"
name: "tvOS 17.5"
xcode: "Xcode_15.4"
runsOn: macOS-14
- destination: "OS=17.0,name=Apple TV"
name: "tvOS 17.0"
xcode: "Xcode_15.0"
Expand All @@ -104,16 +130,12 @@ jobs:
- uses: actions/checkout@v3
- name: ${{ matrix.name }}
run: xcodebuild test -scheme "Validator-Package" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1
- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
- name: Upload test coverage reports to Codecov
uses: space-code/oss-common-actions/.github/actions/upload_test_coverage_report@main
with:
scheme_name: Typhoon
filename: ${{ matrix.name }}
token: ${{ secrets.CODECOV_TOKEN }}
xcode: true
xcode_archive_path: test_output/${{ matrix.name }}.xcresult
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: test_output

watchOS:
name: ${{ matrix.name }}
Expand All @@ -125,6 +147,18 @@ jobs:
fail-fast: false
matrix:
include:
- destination: "OS=11.1,name=Apple Watch Series 10 (46mm)"
name: "watchOS 11.1"
xcode: "Xcode_16.1"
runsOn: macOS-14
- destination: "OS=11.0,name=Apple Watch Series 10 (46mm)"
name: "watchOS 11.0"
xcode: "Xcode_16.0"
runsOn: macOS-14
- destination: "OS=10.5,name=Apple Watch Series 9 (45mm)"
name: "watchOS 10.5"
xcode: "Xcode_15.4"
runsOn: macOS-14
- destination: "OS=10.0,name=Apple Watch Series 9 (45mm)"
name: "watchOS 10.0"
xcode: "Xcode_15.0"
Expand All @@ -137,16 +171,12 @@ jobs:
- uses: actions/checkout@v3
- name: ${{ matrix.name }}
run: xcodebuild test -scheme "Validator-Package" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1
- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
- name: Upload test coverage reports to Codecov
uses: space-code/oss-common-actions/.github/actions/upload_test_coverage_report@main
with:
scheme_name: Typhoon
filename: ${{ matrix.name }}
token: ${{ secrets.CODECOV_TOKEN }}
xcode: true
xcode_archive_path: test_output/${{ matrix.name }}.xcresult
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: test_output

spm:
name: ${{ matrix.name }}
Expand All @@ -158,10 +188,16 @@ jobs:
fail-fast: false
matrix:
include:
- name: "Xcode 15"
- name: "macOS 14, SPM 6.0.2 Test"
xcode: "Xcode_16.1"
runsOn: macOS-14
- name: "macOS 14, SPM 6.0.0 Test"
xcode: "Xcode_16.0"
runsOn: macOS-14
- name: "macOS 14, SPM 5.9.0 Test"
xcode: "Xcode_15.0"
runsOn: macos-13
- name: "Xcode 14"
runsOn: macos-14
- name: "macOS 13, SPM 5.8.1 Test"
xcode: "Xcode_14.3.1"
runsOn: macos-13
steps:
Expand All @@ -186,7 +222,7 @@ jobs:

discover-typos:
name: Discover Typos
runs-on: macOS-12
runs-on: macOS-13
env:
DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer
steps:
Expand Down
4 changes: 3 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ excluded:
- Package.swift
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- .build

# Rules
Expand Down Expand Up @@ -131,4 +133,4 @@ nesting:
type_name:
max_length:
warning: 40
error: 50
error: 50
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Change Log
All notable changes to this project will be documented in this file.

## [Unreleased]

#### Added
- Increase the Swift version to 6.0.
- Added in Pull Request [#13](https://github.com/space-code/validator/pull/13).

#### 1.x Releases
- `1.0.x` Releases - [1.0.0](#100) | [1.0.1](#101)

Expand Down
4 changes: 2 additions & 2 deletions Mintfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
nicklockwood/SwiftFormat@0.47.12
realm/SwiftLint@0.47.1
nicklockwood/SwiftFormat@0.54.0
realm/SwiftLint@0.55.1
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version: 5.9
// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down
26 changes: 26 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Validator",
platforms: [
.iOS(.v16),
.macOS(.v13),
.watchOS(.v9),
.tvOS(.v16),
.visionOS(.v1),
],
products: [
.library(name: "ValidatorCore", targets: ["ValidatorCore"]),
.library(name: "ValidatorUI", targets: ["ValidatorUI"]),
],
dependencies: [],
targets: [
.target(name: "ValidatorCore", dependencies: []),
.target(name: "ValidatorUI", dependencies: ["ValidatorCore"]),
.testTarget(name: "ValidatorCoreTests", dependencies: ["ValidatorCore"]),
.testTarget(name: "ValidatorUITests", dependencies: ["ValidatorCore", "ValidatorUI"]),
]
)
26 changes: 26 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Validator",
platforms: [
.iOS(.v16),
.macOS(.v13),
.watchOS(.v9),
.tvOS(.v16),
.visionOS(.v1),
],
products: [
.library(name: "ValidatorCore", targets: ["ValidatorCore"]),
.library(name: "ValidatorUI", targets: ["ValidatorUI"]),
],
dependencies: [],
targets: [
.target(name: "ValidatorCore", dependencies: []),
.target(name: "ValidatorUI", dependencies: ["ValidatorCore"]),
.testTarget(name: "ValidatorCoreTests", dependencies: ["ValidatorCore"]),
.testTarget(name: "ValidatorUITests", dependencies: ["ValidatorCore", "ValidatorUI"]),
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

import Foundation

#if hasFeature(RetroactiveAttribute)
extension String: @retroactive Error {}
#endif

// MARK: - String + IValidationError

extension String: IValidationError {
public var message: String { self }
}
26 changes: 17 additions & 9 deletions Sources/ValidatorUI/Classes/IUIValidatable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
// Copyright © 2023 Space Code. All rights reserved.
//

// swiftlint:disable prefixed_toplevel_constant

import Foundation
import ValidatorCore

// MARK: - IUIValidatable

@MainActor
public protocol IUIValidatable: AnyObject {
associatedtype Input

Expand Down Expand Up @@ -38,27 +37,36 @@ public protocol IUIValidatable: AnyObject {
func validateOnInputChange(isEnabled: Bool)
}

private var kValidationRules: UInt8 = 0
private var kValidationHandler: UInt8 = 0
#if swift(>=5.10)
private nonisolated(unsafe) var kValidationRules: UInt8 = 0
private nonisolated(unsafe) var kValidationHandler: UInt8 = 0

// swiftlint:disable:next prefixed_toplevel_constant
private nonisolated(unsafe) let validator = Validator()
#else
private var kValidationRules: UInt8 = 0
private var kValidationHandler: UInt8 = 0

private let validator = Validator()
// swiftlint:disable:next prefixed_toplevel_constant
private let validator = Validator()
#endif

public extension IUIValidatable {
@discardableResult
func validate<T>(rule: some IValidationRule<T>) -> ValidationResult where T == Input {
func validate(rule: some IValidationRule<Input>) -> ValidationResult {
let result = validator.validate(input: inputValue, rule: rule)
validationHandler?(result)
return result
}

@discardableResult
func validate<T>(rules: [any IValidationRule<T>]) -> ValidationResult where T == Input {
func validate(rules: [any IValidationRule<Input>]) -> ValidationResult {
let result = validator.validate(input: inputValue, rules: rules)
validationHandler?(result)
return result
}

func add<T>(rule: some IValidationRule<T>) where T == Input {
func add(rule: some IValidationRule<Input>) {
validationRules.append(rule)
}

Expand All @@ -81,7 +89,7 @@ public extension IUIValidatable {
objc_getAssociatedObject(self, &kValidationHandler) as? ((ValidationResult) -> Void)
}
set {
if let newValue = newValue {
if let newValue {
objc_setAssociatedObject(self, &kValidationHandler, newValue as AnyObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
Expand Down
10 changes: 7 additions & 3 deletions Sources/ValidatorUI/Classes/SUI/Extensions/View+Validation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
// Copyright © 2023 Space Code. All rights reserved.
//

// swiftlint:disable prefixed_toplevel_constant

import SwiftUI
import ValidatorCore

private let validator = Validator()
#if swift(>=5.10)
// swiftlint:disable:next prefixed_toplevel_constant
private nonisolated(unsafe) let validator = Validator()
#else
// swiftlint:disable:next prefixed_toplevel_constant
private let validator = Validator()
#endif

public extension View {
/// Validate a binding item using a set of validation rules and perform an action based on
Expand Down
22 changes: 6 additions & 16 deletions Tests/ValidatorUITests/UnitTests/UITextFieldTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,13 @@ import XCTest

#if os(iOS)
final class UITextFieldTests: XCTestCase {
// MARK: Properties

private var textField: UITextField!

// MARK: XCTestCase

override func setUp() {
super.setUp()
textField = UITextField()
}

override func tearDown() {
textField = nil
super.tearDown()
}

// MARK: Tests

@MainActor
func test_thatTextFieldValidationReturnsValid_whenInputValueIsValid() {
// given
let textField = UITextField()

textField.validateOnInputChange(isEnabled: true)
textField.add(rule: LengthValidationRule(max: .max, error: String.error))

Expand All @@ -49,8 +36,11 @@ import XCTest
else { XCTFail("The result must be equal to the valid value") }
}

@MainActor
func test_thatTextFieldValidationReturnsInvalid_whenInputValueIsInvalid() {
// given
let textField = UITextField()

textField.validateOnInputChange(isEnabled: true)
textField.add(rule: LengthValidationRule(max: .max, error: String.error))

Expand Down

0 comments on commit b6d7890

Please sign in to comment.