diff --git a/ExampleApp/ContentView.swift b/ExampleApp/ContentView.swift index 7564eab..1d6cc0b 100644 --- a/ExampleApp/ContentView.swift +++ b/ExampleApp/ContentView.swift @@ -9,12 +9,12 @@ struct ContentView: View var body: some View { VStack(spacing: 60) { VStack { - TextField("Name", text: self.$name) + TextField("Name", text: self.$name.binding) .textFieldStyle(.roundedBorder) .padding() VStack { - ForEach(self._name.errors.localizedDescriptions, id: \.self) { message in + ForEach(self.$name.errors.localizedDescriptions, id: \.self) { message in Text(message) .foregroundColor(.red) .font(.footnote) diff --git a/README.md b/README.md index 35ad4c2..1d5b794 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,12 @@ struct ContentView: View { var body: some View { VStack(spacing: 60) { VStack { - TextField("Name", text: self.$name) + TextField("Name", text: self.$name.binding) .textFieldStyle(.roundedBorder) .padding() VStack { - ForEach(self._name.errors.localizedDescriptions, id: \.self) { message in + ForEach(self.$name.errors.localizedDescriptions, id: \.self) { message in Text(message) .foregroundColor(.red) .font(.footnote) diff --git a/Validate/Source/Validate.swift b/Validate/Source/Validate.swift index 941d71e..a0fa328 100644 --- a/Validate/Source/Validate.swift +++ b/Validate/Source/Validate.swift @@ -25,7 +25,14 @@ public struct Validate: DynamicProperty { } } - public var projectedValue: Binding { + public var projectedValue: Validate { + self + } + + /// Create a binding for the wrapped value. + /// + /// This is useful for working with SwiftUI components. + public var binding: Binding { Binding( get: { self.wrappedValue }, set: { self.wrappedValue = $0 } diff --git a/ValidateTests/CountValidationTests.swift b/ValidateTests/CountValidationTests.swift index 90bc4e8..10baba6 100644 --- a/ValidateTests/CountValidationTests.swift +++ b/ValidateTests/CountValidationTests.swift @@ -2,12 +2,10 @@ import XCTest @testable import Validate -class CountValidationTests: XCTestCase -{ +class CountValidationTests: XCTestCase { // MARK: Greater than - func testCountGreaterThanValidation() - { + func testCountGreaterThanValidation() { @Validate(.count(greaterThan: 3)) var value: String = "" XCTAssertFalse(_value.isValid) @@ -18,8 +16,7 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testCountGreaterThanForOptionalValidation() - { + func testCountGreaterThanForOptionalValidation() { @Validate(.count(greaterThan: 3)) var value: String? = nil XCTAssertFalse(_value.isValid) @@ -30,24 +27,21 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testGreaterThanErrorMessage() throws - { + func testGreaterThanErrorMessage() throws { @Validate(.count(greaterThan: 3)) var value: String = "" let error = try XCTUnwrap(_value.errors.first as? ValidationError) XCTAssertEqual(error.errorDescription, "Should be greater than 3") } - func testGreaterThanErrorMessageForOptional() throws - { + func testGreaterThanErrorMessageForOptional() throws { @Validate(.count(greaterThan: 3)) var value: String? = nil let error = try XCTUnwrap(_value.errors.first as? ValidationError) XCTAssertEqual(error.errorDescription, "Should be greater than 3") } - func testGreaterThanCustomErrorMessage() throws - { + func testGreaterThanCustomErrorMessage() throws { let message = "a message" @Validate( .count( @@ -61,8 +55,7 @@ class CountValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, message) } - func testGreaterThanCustomErrorMessageForOptional() throws - { + func testGreaterThanCustomErrorMessageForOptional() throws { let message = "a message" @Validate( .count( @@ -78,8 +71,7 @@ class CountValidationTests: XCTestCase // MARK: Less than - func testCountLessThanValidation() - { + func testCountLessThanValidation() { @Validate(.count(lessThan: 3)) var value: String = "12345" XCTAssertFalse(_value.isValid) @@ -90,8 +82,7 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testCountLessThanForOptionalValidation() - { + func testCountLessThanForOptionalValidation() { @Validate(.count(lessThan: 3)) var value: String? = nil XCTAssertFalse(_value.isValid) @@ -102,24 +93,21 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testLessThanErrorMessage() throws - { + func testLessThanErrorMessage() throws { @Validate(.count(lessThan: 3)) var value: String = "1234" let error = try XCTUnwrap(_value.errors.first as? ValidationError) XCTAssertEqual(error.errorDescription, "Should be less than 3") } - func testLessThanErrorMessageForOptional() throws - { + func testLessThanErrorMessageForOptional() throws { @Validate(.count(lessThan: 3)) var value: String? = nil let error = try XCTUnwrap(_value.errors.first as? ValidationError) XCTAssertEqual(error.errorDescription, "Should be less than 3") } - func testLessThanCustomErrorMessage() throws - { + func testLessThanCustomErrorMessage() throws { let message = "a message" @Validate( .count( @@ -133,8 +121,7 @@ class CountValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, message) } - func testLessThanCustomErrorMessageForOptional() throws - { + func testLessThanCustomErrorMessageForOptional() throws { let message = "a message" @Validate( .count( @@ -150,8 +137,7 @@ class CountValidationTests: XCTestCase // MARK: Equal - func testCountEqualToValidation() - { + func testCountEqualToValidation() { @Validate(.count(equalTo: 3)) var value: String = "" XCTAssertFalse(_value.isValid) @@ -165,8 +151,7 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testCountEqualToForOptionalValidation() - { + func testCountEqualToForOptionalValidation() { @Validate(.count(equalTo: 3)) var value: String? = nil XCTAssertFalse(_value.isValid) @@ -180,8 +165,7 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testEqualToErrorMessage() throws - { + func testEqualToErrorMessage() throws { @Validate(.count(equalTo: 3)) var value: String = "" XCTAssertFalse(_value.isValid) @@ -189,16 +173,14 @@ class CountValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, "Should be equal to 3") } - func testEqualToErrorMessageForOptional() throws - { + func testEqualToErrorMessageForOptional() throws { @Validate(.count(equalTo: 3)) var value: String? = nil let error = try XCTUnwrap(_value.errors.first as? ValidationError) XCTAssertEqual(error.errorDescription, "Should be equal to 3") } - func testEqualToCustomErrorMessage() throws - { + func testEqualToCustomErrorMessage() throws { let message = "a message" @Validate( .count( @@ -212,8 +194,7 @@ class CountValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, message) } - func testEqualToCustomErrorMessageForOptional() throws - { + func testEqualToCustomErrorMessageForOptional() throws { let message = "a message" @Validate( .count( @@ -229,8 +210,7 @@ class CountValidationTests: XCTestCase // MARK: Range - func testCountRangeValidation() - { + func testCountRangeValidation() { @Validate(.count(in: 2...4)) var value: String = "" XCTAssertFalse(_value.isValid) @@ -244,8 +224,7 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testCountRangeForOptionalValidation() - { + func testCountRangeForOptionalValidation() { @Validate(.count(in: 2...4)) var value: String? = nil XCTAssertFalse(_value.isValid) @@ -259,24 +238,21 @@ class CountValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testRangeErrorMessage() throws - { + func testRangeErrorMessage() throws { @Validate(.count(in: 2...4)) var value: String = "" let error = try XCTUnwrap(_value.errors.first as? ValidationError) XCTAssertEqual(error.errorDescription, "Should be between 2 and 4") } - func testRangeErrorMessageForOptional() throws - { + func testRangeErrorMessageForOptional() throws { @Validate(.count(in: 2...4)) var value: String? = nil let error = try XCTUnwrap(_value.errors.first as? ValidationError) XCTAssertEqual(error.errorDescription, "Should be between 2 and 4") } - func testRangeCustomErrorMessage() throws - { + func testRangeCustomErrorMessage() throws { let message = "a message" @Validate( .count( @@ -290,8 +266,7 @@ class CountValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, message) } - func testRangeCustomErrorMessageForOptional() throws - { + func testRangeCustomErrorMessageForOptional() throws { let message = "a message" @Validate( .count( diff --git a/ValidateTests/FormatValidationTests.swift b/ValidateTests/FormatValidationTests.swift index 90882ff..324e336 100644 --- a/ValidateTests/FormatValidationTests.swift +++ b/ValidateTests/FormatValidationTests.swift @@ -2,10 +2,8 @@ import XCTest @testable import Validate -class FormatValidationTests: XCTestCase -{ - func testFormatValidation() - { +class FormatValidationTests: XCTestCase { + func testFormatValidation() { @Validate(.format("\\d{3}")) var value: String = "" XCTAssertFalse(_value.isValid) @@ -13,8 +11,7 @@ class FormatValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testFormatValidationForOptionalString() - { + func testFormatValidationForOptionalString() { @Validate(.format("\\d{3}")) var value: String? = nil XCTAssertFalse(_value.isValid) @@ -27,8 +24,7 @@ class FormatValidationTests: XCTestCase // MARK: Errors - func testFormatErrorMessage() throws - { + func testFormatErrorMessage() throws { @Validate(.format("\\d{3}")) var value: String = "" XCTAssertEqual(_value.errors.count, 1) @@ -36,8 +32,7 @@ class FormatValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, "Is incorrectly formatted") } - func testCustomErrorMessage() throws - { + func testCustomErrorMessage() throws { let message = "this is a message" @Validate( .format( @@ -51,8 +46,7 @@ class FormatValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, message) } - func testCustomErrorMessageForOptionalString() throws - { + func testCustomErrorMessageForOptionalString() throws { let message = "this is a message" @Validate( .format( diff --git a/ValidateTests/PresenceValidationTests.swift b/ValidateTests/PresenceValidationTests.swift index 88ab636..90e7ec3 100644 --- a/ValidateTests/PresenceValidationTests.swift +++ b/ValidateTests/PresenceValidationTests.swift @@ -2,10 +2,8 @@ import XCTest @testable import Validate -class PresenceValidationTests: XCTestCase -{ - func testPresenceValidation() throws - { +class PresenceValidationTests: XCTestCase { + func testPresenceValidation() throws { @Validate(.presence()) var value: Int? = nil XCTAssertFalse(_value.isValid) @@ -13,8 +11,7 @@ class PresenceValidationTests: XCTestCase XCTAssert(_value.isValid) } - func testPresenceValidationForOptionalString() - { + func testPresenceValidationForOptionalString() { @Validate(.presence(allowEmpty: true)) var blankAllowed: String? = nil XCTAssertFalse(_blankAllowed.isValid) blankAllowed = "" @@ -28,8 +25,7 @@ class PresenceValidationTests: XCTestCase XCTAssert(_blankNotAllowed.isValid) } - func testPresenceValidationForString() - { + func testPresenceValidationForString() { @Validate(.presence()) var value: String = "" XCTAssertFalse(_value.isValid) value = "a" @@ -38,8 +34,7 @@ class PresenceValidationTests: XCTestCase // MARK: Errors - func testPresenceErrorMessage() throws - { + func testPresenceErrorMessage() throws { @Validate(.presence()) var value: Int? = nil XCTAssertEqual(_value.errors.count, 1) @@ -47,8 +42,7 @@ class PresenceValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, "Can't be blank") } - func testCustomErrorMessage() throws - { + func testCustomErrorMessage() throws { let message = "this is a message" @Validate( .presence( @@ -75,8 +69,7 @@ class PresenceValidationTests: XCTestCase XCTAssertEqual(error.errorDescription, message) } - func testCustomErrorMessageForOptionalString() throws - { + func testCustomErrorMessageForOptionalString() throws { let message = "this is a message" @Validate( .presence( diff --git a/ValidateTests/SequenceTests.swift b/ValidateTests/SequenceTests.swift index fcdb690..856eaef 100644 --- a/ValidateTests/SequenceTests.swift +++ b/ValidateTests/SequenceTests.swift @@ -2,10 +2,8 @@ import XCTest @testable import Validate -class SequenceTests: XCTestCase -{ - func testErrorMessages() - { +class SequenceTests: XCTestCase { + func testErrorMessages() { let descriptionA = "abc" let errorA = ValidationError(description: descriptionA) diff --git a/ValidateTests/ValidationTests.swift b/ValidateTests/ValidationTests.swift index 2a0237b..0321aa5 100644 --- a/ValidateTests/ValidationTests.swift +++ b/ValidateTests/ValidationTests.swift @@ -2,10 +2,8 @@ import XCTest @testable import Validate -class ValidationTests: XCTestCase -{ - func testSingleValidationErrors() - { +class ValidationTests: XCTestCase { + func testSingleValidationErrors() { @Validate(.presence()) var value: Int? = nil XCTAssertEqual(_value.errors.count, 1) @@ -13,8 +11,7 @@ class ValidationTests: XCTestCase XCTAssertEqual(_value.errors.count, 0) } - func testMultipleValidationErrors() - { + func testMultipleValidationErrors() { @Validate(.count(greaterThan: 2), .count(equalTo: 4)) var value: String = ""