ValidatedPropertyKit enables you to easily validate your properties

Overview

ValidatedPropertyKit Logo

Swift 5.1 CI Status Version Platform
Carthage Compatible SPM Documentation Twitter


ValidatedPropertyKit enables you to easily validate your properties
with the power of Property Wrappers.


struct LoginView: View {
    
    @Validated(!.isEmpty && .isEmail)
    var mailAddress = String()
    
    @Validated(.range(8...))
    var password = String()
    
    var body: some View {
        List {
            TextField("E-Mail", text: self.$mailAddress)
            TextField("Password", text: self.$password)
            Button(
                action: {
                    print("Login", self.mailAddress, self.password)
                },
                label: {
                    Text("Submit")
                }
            )
            .validated(
                self._mailAddress,
                self._password
            )
        }
    }
    
}

Features

  • Easily validate your properties 👮
  • Predefined validations 🚦
  • Logical Operators to combine validations 🔗
  • Customization and configuration to your needs 💪

Installation

CocoaPods

ValidatedPropertyKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'ValidatedPropertyKit'

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

To integrate ValidatedPropertyKit into your Xcode project using Carthage, specify it in your Cartfile:

github "SvenTiigi/ValidatedPropertyKit"

Run carthage update to build the framework and drag the built ValidatedPropertyKit.framework into your Xcode project.

On your application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase” and add the Framework path as mentioned in Carthage Getting started Step 4, 5 and 6

Swift Package Manager

To integrate using Apple's Swift Package Manager, add the following as a dependency to your Package.swift:

dependencies: [
    .package(url: "https://github.com/SvenTiigi/ValidatedPropertyKit.git", from: "0.0.5")
]

Or navigate to your Xcode project then select Swift Packages, click the “+” icon and search for ValidatedPropertyKit.

Manually

If you prefer not to use any of the aforementioned dependency managers, you can integrate ValidatedPropertyKit into your project manually. Simply drag the Sources Folder into your Xcode project.

Validated 👮‍♂️

The @Validated attribute allows you to specify a validation alongside to the declaration of your property.

☝️ @Validated supports SwiftUI View updates and will basically work the same way as @State does.

@Validated(!.isEmpty)
var username = String()

@Validated(.hasPrefix("https"))
var avatarURL: String?

If @Validated is applied on an optional type e.g. String? you can specify whether the validation should fail or succeed when the value is nil.

@Validated(
   .isURL && .hasPrefix("https"), 
   nilValidation: .constant(false)
)
var avatarURL: String?

By default the argument nilValidation is set to .constant(false)

In addition the SwiftUI.View extension validated() allows you to disable or enable a certain SwiftUI.View based on your @Validated properties. The validated() function will disable the SwiftUI.View if at least one of the passed in @Validated properties evaluates to false.

@Validated(!.isEmpty && .contains("@"))
var mailAddress = String()
    
@Validated(.range(8...))
var password = String()

Button(
   action: {},
   label: { Text("Submit") }
)
.validated(self._mailAddress && self._password)

By using the underscore notation you are passing the @Validated property wrapper to the validated() function

Validation 🚦

Each @Validated attribute will be initialized with a Validation which can be initialized with a simple closure that must return a Bool value.

@Validated(.init { value in
   value.isEmpty
})
var username = String()

Therefore, ValidatedPropertyKit comes along with many built-in convenience functions for various types and protocols.

@Validated(!.contains("Android", options: .caseInsensitive))
var favoriteOperatingSystem = String()

@Validated(.equals(42))
var magicNumber = Int()

@Validated(.keyPath(\.isEnabled, .equals(true)))
var object = MyCustomObject()

Head over the Predefined Validations section to learn more

Additionally, you can extend the Validation via conditional conformance to easily declare your own Validations.

extension Validation where Value == Int {

    /// Will validate if the Integer is the meaning of life
    static var isMeaningOfLife: Self {
        .init { value in
            value == 42
        }
    }

}

And apply them to your validated property.

@Validated(.isMeaningOfLife)
var number = Int()

isValid

You can access the isValid state at anytime by using the underscore notation to directly access the @Validated property wrapper.

@Validated(!.isEmpty)
var username = String()

username = "Mr.Robot"
print(_username.isValid) // true

username = ""
print(_username.isValid) // false

Validation Operators 🔗

Validation Operators allowing you to combine multiple Validations like you would do with Bool values.

// Logical AND
@Validated(.hasPrefix("https") && .hasSuffix("png"))
var avatarURL = String()

// Logical OR
@Validated(.hasPrefix("Mr.") || .hasPrefix("Mrs."))
var name = String()

// Logical NOT
@Validated(!.contains("Android", options: .caseInsensitive))
var favoriteOperatingSystem = String()

Predefined Validations

The ValidatedPropertyKit comes with many predefined common validations which you can make use of in order to specify a Validation for your validated property.

KeyPath

The keyPath validation will allow you to specify a validation for a given KeyPath of the attributed property.

@Validated(.keyPath(\.isEnabled, .equals(true)))
var object = MyCustomObject()

Strings

A String property can be validated in many ways like contains, hasPrefix and even RegularExpressions.

@Validated(.isEmail)
var string = String()

@Validated(.contains("Mr.Robot"))
var string = String()

@Validated(.hasPrefix("Mr."))
var string = String()

@Validated(.hasSuffix("OS"))
var string = String()

@Validated(.regularExpression("[0-9]+$"))
var string = String()

Equatable

A Equatable type can be validated against a specified value.

@Validated(.equals(42))
var number = Int()

Sequence

A property of type Sequence can be validated via the contains or startsWith validation.

@Validated(.contains("Mr.Robot", "Elliot"))
var sequence = [String]()

@Validated(.startsWith("First Entry"))
var sequence = [String]()

Collection

Every Collection type offers the isEmpty validation and the range validation where you can easily declare the valid capacity.

@Validated(!.isEmpty)
var collection = [String]()

@Validated(.range(1...10))
var collection = [String]()

Comparable

A Comparable type can be validated with all common comparable operators.

@Validated(.less(50))
var comparable = Int()

@Validated(.lessOrEqual(50))
var comparable = Int()

@Validated(.greater(50))
var comparable = Int()

@Validated(.greaterOrEqual(50))
var comparable = Int()

Featured on

Contributing

Contributions are very welcome 🙌

License

ValidatedPropertyKit
Copyright (c) 2021 Sven Tiigi [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Comments
  • How to provide the custom message for validation

    How to provide the custom message for validation

    How can I provide a custom message for validation like:

    Validated(.nonEmpty("Username cannot be empty")) var username: String?

    Where can I provide "Username cannot be empty" message?

    enhancement 
    opened by azamsharp 5
  • Validation Error support

    Validation Error support

    Hello Sven. Wonderful project, well done!

    Motivation

    I believe it would be a nice addition to implement support for reporting validation errors. It can be helpful, for example, when you want to display a related error message to the user.

    Solution

    I played around with the project in a fork. I would love to implement the changes myself and submit a PR, but wanted to first do a proposal and open a discussion.

    There are a couple of ways to do it. What first comes to my mind would be this:

    • Let's say that we have a special struct to report our errors:
    public struct ValidationError: Error {
        let localizedMessage: String
        ...
    }
    
    • The validation closure could return a Result<Value, ValidationError>, instead of a Bool.

    • The property wrapper could include a validationError optional property that receives values upon validation and gets set to nil when restore() is called.

    • When using, we would be able to check for a validationError and if there isn't any, we can go ahead and use the value.

    Here's a rough example:

    public extension Validation where Value == String {
    
        static var isValidPassword: Validation {
            return .init { (value) -> Result<String, ValidationError> in
                if value.count < 6 {
                    return .failure(ValidationError(localizedMessage: "Password is too short. Minimum character count is 6."))
                }
    
                /* Additional checks
    
                    ...
    
                */
    
                return .success(value)
            }
        }
    
    }
    
    if let errorMessage = $passwordInput.validationError?.localizedMessage {
        UserNotification.displayError(message: errorMessage)
        return 
    }
    
    // Safe to continue and use the passwordInput string
    
    

    Additional Remarks

    This feature would require quite some changes, but all of them would be internal to the API, meaning that the users of it won't have to change anything when using the default provided validations. However, their custom ones will have to be rewritten to return Results, instead of Bools.

    All of this is a result of a small pre-lunch brainstorm. I'm sure there is a way to improve it 😄 Let me know what you think :)

    enhancement 
    opened by myurieff 4
  • Referencing initializer 'init(wrappedValue:_:nilValidation:)' on 'Validated' requires that 'Published<String>' conform to 'Optionalable'

    Referencing initializer 'init(wrappedValue:_:nilValidation:)' on 'Validated' requires that 'Published' conform to 'Optionalable'

    ValidatedPropertyKit Environment

    • ValidatedPropertyKit version: 0.0.5

    • macOS version: 11.6.2

    • Xcode version: 13.2.1

    • Dependency manager (Carthage, CocoaPods, SPM, Manually): SPM

    What did you do?

    I'm using a view model.

    import CoreData
    import Foundation
    import ValidatedPropertyKit
    
    extension EditView {
        class ViewModel: NSObject, ObservableObject {
            let item: Item
            let add: Bool
            let hasRelationship: Bool
    
            private let dataController: DataController
    
            @Validated(!.isEmpty)
            @Published var title = "" <= error
            // @Published var title: String <= error 
    

    What did you expect to happen?

    To access the variable as shown in the readme examples.

    What happened instead?

    Error....

    Referencing initializer 'init(wrappedValue:_:nilValidation:)' on 'Validated' requires 
    that 'Published<String>' conform to 'Optionalable'
    

    I'm not sure why this is occurring?

    Thanks in advance.

    question 
    opened by JulesMoorhouse 3
  • Doesn't seems to work on latest iOS version ( 14.2 )

    Doesn't seems to work on latest iOS version ( 14.2 )

    ValidatedPropertyKit Environment

    • ValidatedPropertyKit version: 0.0.4
    • macOS version: 11.0.1
    • Xcode version: 12.2
    • Dependency manager (Carthage, CocoaPods, SPM, Manually): SPM

    What did you do?

    I have @Validated(.isEmail) var email: String? { didSet { emailError = _email.isValid } } in an ObservableObject In a view I have a TextField linked to email

    What did you expect to happen?

    I expected the emailError to contains a bool & email to contains the text that was typed.

    What happened instead?

    emailError do contains a bool but it's always false because when I type, the letter disappears. The value is present when I call willSet but isn't anymore in the didSet. If I remove the call to isValid it works.

    It works as expected on devices running 14.1 or lower but not on devices running 14.2

    bug 
    opened by clementleroy 2
  • Support validation for non NIL fields

    Support validation for non NIL fields

    Motivation

    There are many occasions where you have non nil Published variables in SwiftUI's ViewModel, validation of this kind of fields would be a nice addition.

    enhancement 
    opened by andreivladmatei 2
  • Please update the docs to add a real world example

    Please update the docs to add a real world example

    Please update the docs to add a real world example. Even after reading the docs for 10 times it is hard to understand what and how to use this library.

    enhancement 
    opened by azamsharp 2
  • Support for iOS 13.x?

    Support for iOS 13.x?

    Motivation

    ℹ My app needs to support iOS 13 and this package requires 14

    Solution

    ℹ There only seems to be one incompatible thing, which is the use of @StateObject in Validated

    Additional context

    ℹ This doesn't look like it's too difficult of a change. Would it be a case of changing the @StateObject to maybe an @ObservedObject and calling it a day?

    opened by mylogon341 1
  • Validation on UITextField and UITextView

    Validation on UITextField and UITextView

    Motivation

    It could be really cool if we could use @Validated on UITextField and UITextView to simplify form validation.

    Solution

    I don't have any solution yet but the purpose is to have : @Validated(.nonEmpty) var myTextField: UITextField @Validated(.hasPrefix("prefix") var myTextView: UITextView

    And to have a new class Validator which can validate a list of specific @Validated. let validator = Validator() validator.add(myTextField) validator.add(myTextView) let isFormValid = validator.isValid()

    Additional context

    I use UITextField as example but it could be applied to any UIKit components, example: @Validated(.isOn or .ifOff) var mySwitch: UISwitch @Validated(.range(13...)) var myStepper: UIStepper

    I'm not sur if it's possible to easily adapt your code to UIKit components.

    enhancement 
    opened by titiphoque 1
  • Sugestivní

    Sugestivní

    Motivation

    ℹ Please replace this with your motivation. For example if your feature request is related to a problem.

    Solution

    ℹ Please replace this with your proposed solution.

    Additional context

    ℹ Please replace this with any other context or screenshots about your feature request (optional).

    opened by holibak 0
Releases(0.0.7)
  • 0.0.7(Dec 30, 2022)

    What's Changed

    • Fixed a bug where a property attributed with @Validated couldn't be mutated.

    Full Changelog: https://github.com/SvenTiigi/ValidatedPropertyKit/compare/0.0.6...0.0.7

    Source code(tar.gz)
    Source code(zip)
  • 0.0.6(Dec 30, 2022)

    What's Changed

    • Lowered deployment target to iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15
    • Support for CocoaPods and Carthage has been removed. Swift Package Manager is now the preferred way of integrating ValidatedPropertyKit to your project.

    Full Changelog: https://github.com/SvenTiigi/ValidatedPropertyKit/compare/0.0.5...0.0.6

    Source code(tar.gz)
    Source code(zip)
  • 0.0.5(Jan 17, 2021)

    Refactored Architecture

    This release contains breaking changes and introduces a more SwiftUI oriented architecture.

    struct LoginView: View {
        
        @Validated(!.isEmpty && .isEmail)
        var mailAddress = String()
        
        @Validated(.range(8...))
        var password = String()
        
        var body: some View {
            List {
                TextField("E-Mail", text: self.$mailAddress)
                TextField("Password", text: self.$password)
                Button(
                    action: {
                        print("Login", self.mailAddress, self.password)
                    },
                    label: {
                        Text("Submit")
                    }
                )
                .validated(
                    self._mailAddress,
                    self._password
                )
            }
        }
        
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 0.0.4(Feb 7, 2020)

  • 0.0.3(Sep 26, 2019)

  • 0.0.2(Jul 10, 2019)

    Error Handling 🕵️‍♂️

    Each property that is declared with the @Validated attribute can make use of advanced functions and properties from the Validated Property Wrapper itself via the $ notation prefix.

    Beside doing a simple nil check on your @Validated property to ensure if the value is valid or not you can access the validatedValue or validationError property to retrieve the ValidationError or the valid value.

    @Validated(.nonEmpty)
    var username: String?
    
    // Switch on `validatedValue`
    switch $username.validatedValue {
    case .success(let value):
        // Value is valid ✅
        break
    case .failure(let validationError):
        // Value is invalid ⛔️
        break
    }
    
    // Or unwrap the `validationError`
    if let validationError = $username.validationError {
        // Value is invalid ⛔️
    } else {
        // Value is valid ✅
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 0.0.1(Jun 25, 2019)

Owner
Sven Tiigi
iOS Engineer @opwoco
Sven Tiigi
Drop in user input validation for your iOS apps.

Validator Validator is a user input validation library written in Swift. It's comprehensive, designed for extension, and leaves the UI up to you. Here

Adam Waite 1.4k Dec 29, 2022
Easily validate your Properties with Property Wrappers 👮

ValidatedPropertyKit enables you to easily validate your properties with the power of Property Wrappers. struct LoginView: View { @Validated(

Sven Tiigi 873 Dec 22, 2022
WhatsNewKit enables you to easily showcase your awesome new app features.

WhatsNewKit enables you to easily showcase your awesome new app features. It's designed from the ground up to be fully customized to your needs. Featu

Sven Tiigi 2.8k Jan 3, 2023
PlaygroundTester enables you to easily run tests for your iPad Playgrounds 4 project.

PlaygroundTester PlaygroundTester is a package that enables you to add tests to your iPad Swift Playgrounds project. Installation Just add PlaygroundT

Paweł Łopusiński 36 Dec 13, 2022
Helps you define secure storages for your properties using Swift property wrappers.

?? Secure Property Storage Helps you define secure storages for your properties using Swift property wrappers. ?? Features All keys are hashed using S

Alex Rupérez 443 Jan 4, 2023
Simple App for European people who need to validate an EU VAT number, calculate your VAT, check current VAT rates in Europe

Simple App for European people who need to validate an EU VAT number, calculate your VAT, check current VAT rates in Europe. How many euros can you save if you freelanced in another country? You can find out! Make more money now!

Nikola Franičević 8 Dec 29, 2022
Tip-Calculation- - A program for calculate the tip. You can easily calculate it and you can split money easily

Tip-Calculation- It is a program for calculate the tip. You can easily calculate

Burak Pala 0 Jan 13, 2022
JSONExport is a desktop application for Mac OS X which enables you to export JSON objects as model classes with their associated constructors, utility methods, setters and getters in your favorite language.

JSONExport JSONExport is a desktop application for Mac OS X written in Swift. Using JSONExport you will be able to: Convert any valid JSON object to a

Ahmed Ali 4.7k Dec 30, 2022
Avo Keepr enables you to track your avocados so they don't end up uneaten in the garbage

Avo Keepr Open source repo for the Avo Keepr app. Avo Keepr on the App Store Screenshots: App Store Listing: Avo Keepr enables you to track your avoca

Dave Jacobsen 5 Dec 11, 2022
SwiftDate 🐔 Toolkit to parse, validate, manipulate, compare and display dates, time & timezones in Swift.

Toolkit to parse, validate, manipulate, compare and display dates, time & timezones in Swift. What's This? SwiftDate is the definitive toolchain to ma

Daniele Margutti 7.2k Jan 4, 2023
A framework to validate inputs of text fields and text views in a convenient way.

FormValidatorSwift The FormValidatorSwift framework allows you to validate inputs of text fields and text views in a convenient way. It has been devel

ustwo™ 500 Nov 29, 2022
Validate iOS, Android, and Mac localizations. Find errors in .strings, .stringsdict, and strings.xml files.

Locheck An Xcode and Android localization file validator. Make sure your .strings, .stringsdict, and strings.xml files do not have any errors! What do

Asana 73 Dec 13, 2022
Swift String Validator. Simple lib for ios to validate string and UITextFields text for some criterias

Swift String validator About Library for easy and fastest string validation based on сciterias. Instalation KKStringValidator is available through Coc

Kostya 17 Dec 21, 2019
A framework to validate inputs of text fields and text views in a convenient way.

FormValidatorSwift The FormValidatorSwift framework allows you to validate inputs of text fields and text views in a convenient way. It has been devel

ustwo™ 500 Nov 29, 2022
KYC-iOS-Native - To Scan Doc and Validate KYC

KYC-iOS-Native Example To run the example project, clone the repo, and run pod i

Faceki Identity Verification & Biometric Authentication 0 Jan 10, 2022
Validate that apple-app-site-association files are set up correctly

SwiftAASAValidator Validate that apple-app-site-association files are set up correctly The idea is you can use these functions in your test suite for

Ben Spratling IV 1 Apr 12, 2022
A SwiftUI view that enables you to properly present a UIActivityViewController. (iOS)

ActivityView Also available as a part of my SwiftUI+ Collection – just add it to Xcode 13+ A SwiftUI view that enables you to properly present a UIAct

SwiftUI+ 39 Dec 25, 2022
An iOS application enables you explore art works provided by DeviartArt.com with high quality UX.

Iris.iOS Iris is a model mobile application based on iOS. It provides basic functions allow users to explore on DeviantArt and check Daily Arts, Notif

Xueliang Chen 63 Dec 13, 2022
Fridax enables you to read variables and intercept/hook functions in Xamarin/Mono JIT and AOT compiled iOS/Android applications.

Fridax is a Node package for dealing with Xamarin applications while using the Frida API. Goal • Installation • Usage • Examples • Issues • License Bu

Northwave 125 Jan 3, 2023
Enables you to hide ur UIViews and make them screen/screen shot proof. objective c/c++ only

SecureView Enables you to hide ur UIViews and make them screen/screen shot proof. objective c/c++ only Usage UIWindow* mainWindow; - (void) setup {

Red16 6 Oct 13, 2022