{"id":873,"url":"https://github.com/andresinaka/SwiftCop","last_synced_at":"2025-08-06T14:31:24.943Z","repository":{"id":62456428,"uuid":"45357429","full_name":"andresinaka/SwiftCop","owner":"andresinaka","description":"SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations.","archived":false,"fork":false,"pushed_at":"2019-04-07T16:28:07.000Z","size":372,"stargazers_count":541,"open_issues_count":1,"forks_count":38,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-11-29T00:32:55.621Z","etag":null,"topics":["clarity","email-validation","swift","validation"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andresinaka.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-11-01T21:04:47.000Z","updated_at":"2024-11-08T15:52:50.000Z","dependencies_parsed_at":"2022-11-01T23:45:44.406Z","dependency_job_id":null,"html_url":"https://github.com/andresinaka/SwiftCop","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andresinaka%2FSwiftCop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andresinaka%2FSwiftCop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andresinaka%2FSwiftCop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andresinaka%2FSwiftCop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andresinaka","download_url":"https://codeload.github.com/andresinaka/SwiftCop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228905550,"owners_count":17989782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clarity","email-validation","swift","validation"],"created_at":"2024-01-05T20:15:33.521Z","updated_at":"2024-12-09T14:31:17.070Z","avatar_url":"https://github.com/andresinaka.png","language":"Swift","funding_links":[],"categories":["Code Quality","Libs","Quality [🔝](#readme)"],"sub_categories":["Quality","Other free courses","Getting Started"],"readme":"![SwiftCop](swiftCop.png)\n\nSwiftCop is a validation library fully written in Swift and inspired by the clarity of [Ruby On Rails Active Record validations](http://guides.rubyonrails.org/active_record_validations.html).\n\n[![Build Status](https://travis-ci.org/andresinaka/SwiftCop.svg)](https://travis-ci.org/andresinaka/SwiftCop) [![codecov.io](https://codecov.io/github/andresinaka/SwiftCop/badge.svg?branch=master)](https://codecov.io/github/andresinaka/SwiftCop?branch=master) [![codecov.io](https://img.shields.io/badge/pod-v1.0.0-brightgreen.svg)]()\n\n### Objective\n\nBuild a standard drop-in library for validations in Swift while making it easily extensible for users to create custom validations. And avoid developers from writing over and over again the same code and validations for different projects.\n\n## Features\n\n- Quick validations.\n- Super simple and declarative syntax.\n- Easily extensible.\n- Fully Swift 4.0\n\n## Modules\n\nSwiftCop was built around three different concepts:\n\n### Trial\n\n```Trial``` is an ```Enum``` that implements the ```TrialProtocol```\n\n```swift\npublic protocol TrialProtocol {\n\tfunc trial() -\u003e ((_ evidence: String) -\u003e Bool)\n}\n```\n\nWe can use ```Trial``` to quickly validate ```strings```. ```SwiftCop``` ships with a very fully featured ```Trial``` implementation. The following trials are provided:\n\n#### ```Exclusion([String])```\nThis validates that the attributes are not included in the evidence string.\n\n```swift\nlet exclusionTrial = Trial.exclusion([\".com\",\".ar\", \".uy\"])\nlet trial = exclusionTrial.trial()\n\nXCTAssertFalse(trial(\"http://www.nytimes.com\"))\nXCTAssertFalse(trial(\"http://www.lanacion.com.ar\"))\nXCTAssertTrue(trial(\"http://www.elpais.es\"))\n```\n\n#### ```Format(String)```\nThis validates whether the evidence matches a given regular expression.\n\n```swift\nlet formatTrial = Trial.format(\"^#([a-f0-9]{6}|[a-f0-9]{3})$\") // hexa number with #\nlet trial = formatTrial.trial()\n\nXCTAssertTrue(trial(\"#57b5b5\"))\nXCTAssertFalse(trial(\"57b5b5\"))\nXCTAssertFalse(trial(\"#h7b5b5\"))\n```\n\n#### ```Inclusion([String])```\nThis validates that the attributes are included in the evidence string.\n\n```swift\nlet inclusionTrial = Trial.inclusion([\".com\",\".ar\", \".uy\"])\nlet trial = inclusionTrial.trial()\n\nXCTAssertTrue(trial(\"http://www.nytimes.com\"))\nXCTAssertTrue(trial(\"http://www.lanacion.com.ar\"))\nXCTAssertFalse(trial(\"http://www.elpais.es\"))\n```\n\n#### ```Email```\nThis validates whether the evidence is an email or not.\n\n```swift\nlet emailTrial = Trial.email\nlet trial = emailTrial.trial()\nXCTAssertTrue(trial(\"test@test.com\"))\n```\n\n#### ```Length(Length,Any)```\nThis validates the length of given evidence:\n\n```swift\nlet lengthTrial = Trial.Length(.Is, 10)\nlet trial = lengthTrial.trial()\nXCTAssertTrue(trial(\"0123456789\"))\n```\n```swift\nlet lengthTrial = Trial.Length(.Minimum, 10)\nlet trial = lengthTrial.trial()\nXCTAssertTrue(trial(\"0123456789\"))\n```\n```swift\nlet lengthTrial = Trial.Length(.Maximum, 10)\nlet trial = lengthTrial.trial()\t\t\nXCTAssertTrue(trial(\"0123456789\"))\n```\n```swift\nlet interval = Trial.Length(.In, 2..\u003c5 as HalfOpenInterval)\nlet trial = interval.trial()\nXCTAssertTrue(trial(\"1234\"))\n```\n```swift\nlet interval = Trial.Length(.In, 2...5 as ClosedInterval)\nlet trial = interval.trial()\nXCTAssertFalse(trial(\"123456\"))\n```\n\n### Suspect\n\nThe ```Suspect``` is a ```Struct``` that is the glue between some other concepts always used while validating fields. It puts together a ```UITextField``` that is going to be the source of the ```evidence```, a ```sentence``` that is going to be the text shown if the ```suspect``` is guilty (when the ```Trial``` returns false) and the ```Trial``` itself, that can be a custom made trial for the suspect or you can use one of the trials provided by the library:\n\n```swift\nSuspect(view: UITextField, sentence: String, trial: TrialProtocol)\nSuspect(view: UITextField, sentence: String, trial: (String) -\u003e Bool)\n```\n\nWe can check if the ```Suspect``` is guilty or not with:\n\n```\nfunc isGuilty() -\u003e Bool\n```\n\nThis method is going to return ```true``` if the ```Trial``` returns ```false```.\n\nAlso we can directly ask for the ```verdict``` on the ```Suspect```, this is going to check if it's guilty or not and then return and empty string (```\"\"```) or the ```sentence```.\n\nFor example:\n\n```swift\nlet suspect = Suspect(view: self.dummyTextField, sentence: \"Invalid email\", trial: .Email)\t\t\nlet verdict = suspect.verdict() // this can be \"\" or \"Invalid Email\"\n```\n\n### SwiftCop\n\nFinally we have the guy that is going to enforce the validations! The cop is going to get all the suspects together and give us the tools to check who are the guilty suspects or if there is any guilty suspect at all.\n\nAs you can imagine this is going to add a suspect under the vigilance of a cop, we can add as many suspects as we want:\n\n```swift\nopen func addSuspect(_ suspect: Suspect)\n```\n\nThis will let us check if there is any guilty suspect between all the suspects under the surveillance of our cop:\n\n```swift\npublic func anyGuilty() -\u003e Bool\n```\n\nThis will let us know all the guilty suspects our cop found:\n\n```swift\npublic func allGuilties() -\u003e Array\u003cSuspect\u003e\n```\n\nThis will let us check if a UITextField that is suspect is guilty or not:\n\n```swift\npublic func isGuilty(textField: UITextField) -\u003e Suspect?\n```\n\n## Example\n\nThe example is shipped in the repository:\n\n```Swift\nclass ViewController: UIViewController {\n\t@IBOutlet weak var validationLabel: UILabel!\n\n\t@IBOutlet weak var fullNameMessage: UILabel!\n\t@IBOutlet weak var emailMessage: UILabel!\n\t@IBOutlet weak var passwordMessage: UILabel!\n\n\t@IBOutlet weak var fullName: UITextField!\n\t@IBOutlet weak var emailTextField: UITextField!\n\t@IBOutlet weak var password: UITextField!\n\n\tlet swiftCop = SwiftCop()\n\n\toverride func viewDidLoad() {\n\t\tsuper.viewDidLoad()\n\n\t\tswiftCop.addSuspect(Suspect(view: self.fullName, sentence: \"More Than Two Words Needed\"){\n\t\t\treturn $0.components(separatedBy: \" \").filter{$0 != \"\"}.count \u003e= 2\n\t\t})\n\t\tswiftCop.addSuspect(Suspect(view:self.emailTextField, sentence: \"Invalid email\", trial: Trial.email))\n\t\tswiftCop.addSuspect(Suspect(view:self.password, sentence: \"Minimum 4 Characters\", trial: Trial.length(.minimum, 4)))\n\t}\n\n\t@IBAction func validateFullName(_ sender: UITextField) {\n\t\tself.fullNameMessage.text = swiftCop.isGuilty(sender)?.verdict()\n\t}\n\n\t@IBAction func validateEmail(_ sender: UITextField) {\n\t\tself.emailMessage.text = swiftCop.isGuilty(sender)?.verdict()\n\t}\n\n\t@IBAction func validatePassword(_ sender: UITextField) {\n\t\tself.passwordMessage.text = swiftCop.isGuilty(sender)?.verdict()\n\t}\n\n\t@IBAction func allValid(_ sender: UITextField) {\n\t\tlet nonGultiesMessage = \"Everything fine!\"\n\t\tlet allGuiltiesMessage = swiftCop.allGuilties().map{ return $0.sentence}.joined(separator: \"\\n\")\n\n\t\tself.validationLabel.text = allGuiltiesMessage.characters.count \u003e 0 ? allGuiltiesMessage : nonGultiesMessage\n\t}\n\n\t@IBAction func hideKeyboard(_ sender: AnyObject) {\n\t\tself.view.endEditing(true)\n\t}\n}\n```\n\n![SwiftCopExampel](swiftCopExample.gif)\n\n# Installation\n\nYou can just clone the repo and copy the ```SwiftCop``` folder to your project or you can use one of the following options:\n\n### Setting up with [CocoaPods](http://cocoapods.org/)\n\n```\npod 'SwiftCop'\n```\n\nThen:\n\n```\nimport SwiftCop\n```\n\nAnd you are all set!\n\n### Setting up with [Carthage](https://github.com/Carthage/Carthage)\n\n- TODO\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandresinaka%2FSwiftCop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandresinaka%2FSwiftCop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandresinaka%2FSwiftCop/lists"}