• This repository has been archived on 11/May/2023
  • Stars
    star
    165
  • Rank 228,357 (Top 5 %)
  • Language
    Objective-C
  • License
    MIT License
  • Created almost 10 years ago
  • Updated over 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Validation has never been as easy as now!

NGRValidator

Platform Version License Carthage compatible Swift Version

NGRValidator is a 3rd party library for iOS and macOS. It allows you to validate the data in the way that you want. It's an easy to read, centralized, and comprehensive solution to validating any model in just a few lines of code.

Why use NGRValidator?

Typically every project which handles user account requires email validation. Let's take a look how to do this:

NSString *email = <#your string email address#>;
NSError *error = [NGRValidator validateValue:email named:@"E-mail address" rules:^(NGRPropertyValidator *validator) {
    // 'is', 'to', 'have' are syntactic sugar and can be safely omitted
    validator.is.required().to.have.syntax(NGRSyntaxEmail);
}];

Too much code? There are better ways to achieve this? And, what if you want to validate passwords as well? You can use a similar method to the one above. Nevertheless, in order to keep the MVC pattern, it would be much better to create a simple model with validation functionality:

@interface UserAccount : NSObject

//should have email syntax:
@property (strong, nonatomic) NSString *email;
//should have at least 5 signs:
@property (strong, nonatomic) NSString *password;

@end

@implementation  UserAccount

- (NSError *)validate {
    NSError *error = nil;
    [NGRValidator validateModel:self error:&error delegate:nil rules:^NSArray *{
        return @[NGRValidate(@"email").required().syntax(NGRSyntaxEmail),
                 NGRValidate(@"password").required().minLength(5)];
    }];
    return error;
}

@end

Let's take it one step further. Consider this model should be used both for login and for password change. Moreover to change password, user should provide old, new and repeated new password. Obviously new and repeated new password shouldn't be validated on login. Improved UserAccount model looks as follows:

@interface UserAccount : NSObject

//should have email syntax:
@property (strong, nonatomic) NSString *email;
//should have at least 5 signs:
@property (strong, nonatomic) NSString *password;
//should have at least 5 signs and be different than password. Validated only on "changePassword" scenario.
@property (strong, nonatomic) NSString *newPassword;
//should have at least 5 signs and be same as newPassword. Validated only on "changePassword" scenario.
@property (strong, nonatomic) NSString *repeatedNewPassword;

@end

@implementation  UserAccount

- (NSError *)validateWithScenario:(NSString *)scenario {
     NSError *error = nil;
    [NGRValidator validateModel:self error:&error scenario:scenario delegate:nil rules:^NSArray *{
        return @[NGRValidate(@"email").required().syntax(NGRSyntaxEmail),
                 NGRValidate(@"password").required().minLength(5),
                 NGRValidate(@"newPassword").required().minLength(5).differ(self.password).onScenarios(@[@"changePassword"]),
                 NGRValidate(@"repeatedNewPassword").required().match(self.newPassword).onScenarios(@[@"changePassword"])];
    }];
    return error;
}

@end

That's it! All validation requirements in one place. Continue reading to learn more about rules, scenarios and messaging.

Requirements

  • iOS 9.0+ SDK
  • macOS 10.11.4+ SDK
  • CocoaPods 0.39.0 (use gem install cocoapods to grab it!)

Installation:

Installation with CocoaPods

CocoaPods is a dependency manager for Objective-C and Swift, which automates and simplifies the process of using 3rd-party. To use NGRValidator via CocoaPods write in your Podfile:

pod 'ngrvalidator', '~> 2.0.0'

and run pod update or pod install

Carthage

Install using Carthage by adding the following line to your Cartfile:

github "netguru/ngrvalidator"

Then, run the following command:

$ carthage update

Last if you're building for macOS:

  • On your application targets โ€œGeneralโ€ settings tab, in the โ€œEmbedded Binariesโ€ section, drag and drop NGRValidator.framework from the Carthage/Build/Mac folder on disk.

If you're building for iOS

  • On your application targets โ€œGeneralโ€ settings tab, in the โ€œLinked Frameworks and Librariesโ€ section, drag and drop each framework you want to use from the Carthage/Build folder on disk.

  • On your application targets โ€œBuild Phasesโ€ settings tab, click the โ€œ+โ€ icon and choose โ€œNew Run Script Phaseโ€. Create a Run Script with the following contents: /usr/local/bin/carthage copy-frameworks

  • and add the paths to the frameworks you want to use under โ€œInput Filesโ€, e.g.:

$(SRCROOT)/Carthage/Build/iOS/NGRValidator.framework

Submodule

In your projects git folder type:

git submodule init
git submodule add --copy link to the repo--
git submodule update

Just download & attach

This is strongly misadvised as you won't be able to see code updates. Clone or download the source, copy all files from NGRValidator folder.

Configuration

Use #import "NGRValidator" whenever you want to use it.

As many other libraries, NGRValidator offers handy VALIDATOR_SHORTHAND which allows to omit prefixes in some methods. To use it, write before #import:

#define VALIDATOR_SHORTHAND

and feel free to use validate(...) instead of NGRValidate(...)

Invoking validation

There are 3 general methods of validation:

  • single value validation:
+ (NSError *)validateValue:(NSObject *)value
					 named:(NSString *)name
					 rules:(void (^)(NGRPropertyValidator *validator))rules;
  • model validation till first error. NGRValidator will break validation when any error will appear:
+ (BOOL)validateModel:(NSObject *)model
			    error:(NSError **)error
			 delegate:(id<NGRMessaging>)delegate
			    rules:(NSArray *(^)())rules;

// with scenario counterpart:
+ (BOOL)validateModel:(NSObject *)model
			    error:(NSError **)error
			 scenario:(NSString *)scenario
			 delegate:(id<NGRMessaging>)delegate
			    rules:(NSArray *(^)())rules;
  • entire model validation. NGRValidator will validate entire model and return an array populated with errors (if validation failed). Otherwise nil:
+ (NSArray *)validateModel:(NSObject *)model
                  delegate:(id<NGRMessaging>)delegate
                     rules:(NSArray *(^)())rules;

// with scenario counterpart:                
+ (NSArray *)validateModel:(NSObject *)model
                  scenario:(NSString *)scenario
                  delegate:(id<NGRMessaging>)delegate
                     rules:(NSArray *(^)())rules;

Psst hey! if any error did appear you can determine which property did not validate just by checking error.userInfo[NGRValidatorPropertyNameKey].

Validation rules

NGRValidator offers many ready to use rules:

  • required() - validates if property is nil or not. If is not required and has any other validation rule attached, like .decimal(), property will be validated only when is not nil.

  • allowEmpty() - validates if property can be empty (means it's length or count is equal to 0). By default cannot be empty. When is allowed to be empty, validator will pass validation when property will be empty. Works for both required and non-required rules. NOTE: Refers to NSString, NSAttributedString, NSData, NSArray, NSSet, NSDictionary (and their mutable counterparts).

  • order(NSUInteger) - changes priority of NGRPropertyValidator. By default all property validators have same priority and will be invoked in order of NSArray order returned in rules: block.

NSString:

  • minLength(NSUInteger) - validates minimum length of NSString (inclusive).
  • maxLength(NSUInteger) - validates maximum length of NSString (inclusive).
  • lengthRange(NSUInteger, NSUInteger) - validates minimum and maximum length of NSString (inclusive).
  • exactLength(NSUInteger) - validates exact length of NSString.
  • match(NSString *) - validates that the NSString match another NSString.
  • differ(NSString *) - validates that the NSString is different than another NSString.
  • decimal() - validates that the NSString contains only decimal signs.
  • emoji(BOOL) - validates that the NSString does or does not contain emoji.

Syntax:

  • regex(NSString *, NSRegularExpressionOptions) - validates that the NSString match given regex pattern with options.
  • syntax(NGRSyntax) - validates that the NSString has given syntax.

For full list of supported Syntaxes go here

NSNumber:

  • min(CGFloat) - validates lower limit of NSNumber (inclusive).
  • max(CGFloat) - validates upper limit of NSNumber (inclusive).
  • range(CGFloat, CGFloat) - validates minimum and maximum value of NSSNumber (inclusive).
  • exact(CGFloat) - validates exact value of NSNumber.
  • beFalse() - validates if NSNumber represents false status.
  • beTrue() - validates if NSNumber represents true status.

UIImage/NSImage:

  • minRatio(CGFloat)/maxRatio(CGFLoat) - validates if the ratio of the image is greater/smaller than CGFloat
  • minWidth(CGFloat)/maxWidth(CGFloat) - validates if the pixel width of the image is greater/smaller than CGFloat
  • minHeight(CGFloat)/maxHeight(CGFloat) - validates if the pixel height of the image is greater/smaller than CGFloat
  • minSize(CGSize)/maxSize(CGSize) - validates if the pixel size of the image is greater/smaller than CGSize on both dimensions

NSDate:

  • earlierThan(NSDate *) - validates if NSDate property is earlier than given date (inclusive).
  • earlierThanOrEqualTo(NSDate *) - validates if NSDate property is earlier than or equal to given date (inclusive).
  • laterThan(NSDate *) - validates if NSDate property is later than given date (inclusive).
  • laterThanOrEqualTo(NSDate *) - validates if NSDate property is later than or equal to given date (inclusive).
  • betweenDates(NSDate *, NSDate *, BOOL) - validates if NSDate property is between given dates. BOOL parameter specify inclusiveness of comparison.
  • earlierThanUnixTimestamp(NSTimeInterval) - validates if date is earlier than specified UNIX epoch
  • earlierThanOrEqualToUnixTimestamp(NSTimeInterval) - validates if date is earlier than or equal to specified UNIX epoch
  • laterThanUnixTimestamp(NSTimeInterval) - validates if date is later than specified UNIX epoch
  • laterThanOrEqualToUnixTimestamp(NSTimeInterval) - validates if date is later than or equal to specified UNIX epoch

NSData:

  • minByteSize(CGFloat)/maxByteSize(CGFloat) - validates if data has byte size greater/smaller than CGFloat
  • image/video/audio/archive - validates if data represents image/video/audio/archive
  • mimeType(NGRMimeType) - validates if data has given MIMEType.

For full list of supported MIMETypes go here

NSArray:

  • includes(NSObject *) - validates whether given object is included in validated array property or not.
  • excludes(NSObject *) - validates whether given object is excluded from validated array property or not.
  • includedIn(NSArray *) - validates whether validated property is included in given array. If array is empty validation will return an error.
  • excludedFrom(NSArray *) - validates whether validated property is excluded from given array. If array is empty validation will pass.

Scenarios

Scenarios allows to keep same model across all possible actions. Sometimes some properties should be obligatory for one action and optional for another. Scenarios makes model validation more flexible and usable without any conditional statements. If property should conform specified scenario(s), pass NSArray of scenarios using:

onScenarios(NSArray *)

Property which doesn't conform any scenario, will be validated on every scenario. Just remember to pass scenario names as NSString

Validation messages

Although NGRValidator contains default error messages for each validation, it is possible to customize them as well. There are two way to achieve this:

1. by using msg prefixed method in rules block:
NGRValidate(@"password").minLength(5).msgTooShort(@"should have at least 5 signs")

Notice that NGRValidator will use capitalized name of validated property in error description. Nevertheless there is possibility to localize it's name with:

localizedName(NSString *)
2. by conforming NGRMessaging delegate and returning error key - messages dictionary for appropriate property key:
- (NSDictionary *)validationErrorMessagesByPropertyKey {
    return @{@"password" :
    		    @{MSGTooShort : @"Password should have at least 5 signs."}
    	    };
}

This two methods can be used simultaneously. Order of taking messages is defined as follows:

  1. If any error will be encountered by validator, it will ask delegate first for error description.
  2. If delegate will be nil or validator will not find message for expected error-key and property name, it will search for an error description in given in rules block.
  3. If developer didn't declare message for encoutered error, validator will use default one prepared by library.

For more info please refer to messaging system.

Sugar syntax

NGRValidator contains sugar syntax to improve readbility and introduce natural speech to code. To sugar syntax belongs:

is, are, on, has, have, to, toNot, notTo, be, with, should

Note difference between sugar syntax and regular validation method:

                          validation method has to be invoked always with parentheses (even if do not take any parameter).
                           v
 validate(@"password").is.required()
                       ^
                      sugar syntax is always invoked without parentheses.

##Demo Contains 5 examples:

  • UI examples on 3 levels: simple, medium and complex. Every level has been eplained more on less in this readme.
  • coded
  • usage in Swift

UI example will be automatically fired when you hit โŒ˜+R. To enable coded example please change logStory flag from NO to YES in AppDelegate. To improve story readability and understandability, set brakepoint at the beginning of story method and follow debugger line by line.

License

NGRValidator is available under the MIT license.

Contribution

First, thank you for contributing! Here a few guidelines to follow:

More Info

Changelog available here.

Feel free to contribute, comment, ask, and share your ideas by opening an issue.

You can also read our blog post introducing: Open Source NGRValidator.

Author

Created and maintained by Patryk Kaczmarek.

Copyright ยฉ 2014 - 2017 Netguru

More Repositories

1

ResponseDetective

Sherlock Holmes of the networking layer. ๐Ÿ•ต๏ธโ€โ™‚๏ธ
Swift
1,956
star
2

sticky-parallax-header

A simple React Native library, enabling the creation of fully customized header for your iOS and Android apps.
TypeScript
1,811
star
3

CarLensCollectionViewLayout

An easy-to-use Collection View Layout for card-like animation.
Swift
548
star
4

Kissme

Kissme: Kotlin Secure Storage Multiplatform
Kotlin
411
star
5

videochatguru-android

Open source library to create fast and beautiful video chats over WebRTC
Kotlin
309
star
6

BlueSwift

Swift framework for easy connection with Bluetooth peripherals.
Swift
169
star
7

compose-multiplatform-charts

Charts library for Kotlin multiplatform applications
Kotlin
136
star
8

CarLens-iOS

CarLens - Recognize and Collect Cars
Swift
130
star
9

AnimatedCardInput

Easy to use iOS library with components for input of Credit Card data.
Swift
38
star
10

ar-localizer-view-android

Kotlin
33
star
11

CarLens-Android

CarLens - Recognize and Collect Cars
Kotlin
24
star
12

mobile-security-checklist

Netguru mobile security checklist
Python
23
star
13

rnd-retail-multiplatform-public

Kotlin
22
star
14

baby-monitor-client-android

Internal Baby Monitor android project
Kotlin
20
star
15

heroes-api

TypeScript
18
star
16

baby-monitor-client-ios

Swift
17
star
17

netguru

netguru gem - collection of solutions we use to develop and deploy our projects.
Ruby
16
star
18

awesome-list

Ruby
15
star
19

xcconfigs

Collection of common Xcode configuration files. ๐Ÿ› ๏ธ
14
star
20

CreateML-Research

The easy ways to start your journey with CreateML.
Swift
14
star
21

mobile-security-review

Security review guidelines for mobile projects
13
star
22

react-native-ar-localizer

Java
12
star
23

nodejs-recruitment-task

Repository for Node.js department's recruitment process.
JavaScript
11
star
24

productivity

Productivity tips for Netguru
Dockerfile
10
star
25

ng-ios-network-module

iOS Networking Module
Swift
9
star
26

commentable-rs

Rust
9
star
27

highway

Build system on top of Fastlane.
Ruby
9
star
28

coolcal-android

Kotlin
9
star
29

flutter-recruitment-task

Dart
8
star
30

design-process

CSS
7
star
31

opoca

Library for speeding up building machine learning proof of concepts.
Python
7
star
32

atstats-android

atStats native android app
Kotlin
5
star
33

graphql-starter-pack

Graphql training by Netguru.
Ruby
4
star
34

kivy-games

Python
4
star
35

SimpleRegEx

Wrapper for RegEx, made so the RegEx code will be understable
Python
4
star
36

smarthome

Kotlin
4
star
37

netguru-grdb

Swift
4
star
38

react-native-modal-dropdown

JavaScript
4
star
39

sections-decorator-android

Kotlin
4
star
40

bitrise-step-slack

A next-gen Slack webhook step for Bitrise
Ruby
3
star
41

frontend-recruitment-task

3
star
42

picguard-swift

Image analysis framework for Swift
Swift
3
star
43

hubguru-ios-public

Swift
3
star
44

ios-framework-template

Swift
3
star
45

qa-selenium-java-framework

Java
2
star
46

ar-localizer-view-iOS

Swift
2
star
47

capistrano-docker

Ruby
2
star
48

ngrcrop-ios

ngrcrop-ios: UI component for editing selected photos.
Objective-C
2
star
49

rack_password

Small rack middleware to block your site from unwanted vistors.
Ruby
2
star
50

awesome-frontend-architecture

Collection of awesome frontend architecture resources
2
star
51

iOS-Good-Practices

Swift
2
star
52

inicjatywyotwarte-be

A website that tries to collect all important and relevant initiatives that could help in the times of COVID-19. https://www.inicjatywyotwarte.pl
Ruby
2
star
53

terraform-module-hcloud

Hetzner Cloud module for terraform
HCL
2
star
54

inicjatywyotwarte-fe

A website that tries to collect all important and relevant initiatives that could help in the times of COVID-19.
JavaScript
2
star
55

sync-aws-extend-switch-roles

Sync AWS Extend Switch Roles
1
star
56

ios-bitrise-client-public

Swift
1
star
57

bitrise-step-ng-jira-step

Shell
1
star
58

codestories-react-native-hooks

JavaScript
1
star
59

devise-2fa

Devise with 2FA support based on Twilio
Ruby
1
star
60

twilio-2fa-bot

Simple Twilio messages scrapper for shared phone numbers
JavaScript
1
star
61

danger-flutter-coverage

Ruby
1
star
62

meetguru

JavaScript
1
star
63

django-modular-user

Python
1
star
64

bitrise-step-danger-android

Shell
1
star
65

dc-docker-task

This repo stores docker recruitment tasks for devops-college
Dockerfile
1
star