{"id":175,"date":"2016-08-25T10:00:00","date_gmt":"2016-08-25T10:00:00","guid":{"rendered":"http:\/\/thibaultklein.com\/ios\/?p=175"},"modified":"2016-09-06T12:44:38","modified_gmt":"2016-09-06T12:44:38","slug":"a-functional-approach-to-uitextfield-validation","status":"publish","type":"post","link":"https:\/\/thibaultklein.com\/ios\/a-functional-approach-to-uitextfield-validation\/","title":{"rendered":"A Functional Approach to UITextField Validation"},"content":{"rendered":"<p>It is very common for an app to validate user input and provide instant feedback when something is typed incorrectly. In this article, I will walk through the implementation I worked on to validate a text field\u2019s string. I decided to attempt a <a href=\"http:\/\/harlankellaway.com\/blog\/2015\/08\/10\/swift-functional-programming-intro\">functional<\/a> approach and found a solution that is reusable and scalable for every kind of validation.<\/p>\n<h2 id=\"identifyingthefunctions\">Identifying the Functions<\/h2>\n<p>One thing that the functional programming paradigm urges us to do is to think how computation can be broken down into functions that reliably take an input and produce an output, without modifying state.<\/p>\n<p>When I approached this problem, my first step was to identify what kind of data I wanted to deal with. I figured that the entry data would always be a <code>String<\/code> type and the result a <code>Bool<\/code>. So I\u2019d write validation functions that would take a string as an argument and return <code>true<\/code> or <code>false<\/code>.<\/p>\n<p>With that in mind, I wanted another function that would allow me to take an unlimited amount of validation functions, compute the result of all of them, and return the final result. I wrote a function that would take an array of functions with the same signature as the validation functions `(String -&gt; Bool) that function would return a Bool as the final result of evaluating all validation function.<\/p>\n<p>For those more familiar with functional concepts, this is a take on using a \u201cpipeline\u201d &#8211; a sequence of operations that are applied in succession to, generally, produce a value.<\/p>\n<h2 id=\"implementation\">Implementation<\/h2>\n<p>I decided to create a <code>UITextField<\/code> extension and came up with an implementation using <code>map<\/code> and <code>reduce<\/code>, two functions commonly used in functional programming:<\/p>\n<pre><code>extension UITextField {\r\n\r\n    func validateField(_ functions: [(String) -> Bool]) -> Bool {\r\n        return functions.map { f in f(self.text ?? \"\") }.reduce(true) { $0 && $1 }\r\n    }\r\n\r\n}\r\n<\/code><\/pre>\n<p><code>validateField<\/code> iterates over the <code>functions<\/code> array and apply each function with the current <code>UITextField<\/code> text, reduces each result into the final result and returns it.<\/p>\n<p>All I needed after was a bunch of validation functions taking a <code>String<\/code> as argument and returning a <code>Bool<\/code>:<\/p>\n<pre><code>func isPhoneNumberValid(text: String) -&gt; Bool\r\nfunc isZipCodeValid(text: String) -&gt; Bool\r\nfunc isStateValid(text: String) -&gt; Bool\r\nfunc isCVCValid(text: String) -&gt; Bool\r\n<\/code><\/pre>\n<p>This functional approach gave me some consistency through all the validation functions, and thanks to that I found a way to use all of them the same way in a clean, short function. <\/p>\n<h2 id=\"evaluationwithregularexpression\">Evaluation with regular expression<\/h2>\n<p>For the actual implementation of these validation functions, I created an <code>evaluate<\/code> function as part of a <code>String<\/code> extension that would take a regular expression as an argument and return a boolean based on the evaluation:<\/p>\n<pre><code>extension String {\r\n\r\n    func evaluate(with condition: String) -> Bool {\r\n        guard let range = range(of: condition, options: .regularExpression, range: nil, locale: nil) else {\r\n            return false\r\n        }\r\n\r\n        return range.lowerBound == startIndex && range.upperBound == endIndex\r\n    }\r\n\r\n}\r\n<\/code><\/pre>\n<p>I could then use this <code>evaluate<\/code> function for each validation function:<\/p>\n<pre><code>func isPhoneNumberValid(text: String) -> Bool {\r\n    let regexp = \"^[0-9]{10}$\"\r\n    return text.evaluate(with: regexp)\r\n}\r\n\r\nfunc isZipCodeValid(text: String) -> Bool {\r\n    let regexp = \"^[0-9]{5}$\"\r\n    return text.evaluate(with: regexp)\r\n}\r\n\r\nfunc isStateValid(text: String) -> Bool {\r\n    let regexp = \"^[A-Z]{2}$\"\r\n    return text.evaluate(with: regexp)\r\n}\r\n\r\nfunc isCVCValid(text: String) -> Bool {\r\n    let regexp = \"^[0-9]{3,4}$\"\r\n    return text.evaluate(with: regexp)\r\n}\r\n\r\nfunc isEmailValid(text: String) -> Bool {\r\n    let regexp = \"[A-Z0-9a-z._]+@([\\\\w\\\\d]+[\\\\.\\\\w\\\\d]*)\"\r\n    return text.evaluate(with: regexp)\r\n}\r\n<\/code><\/pre>\n<p>And here is how I call my validation implementation on any text field:<\/p>\n<pre><code>textField.validateField([isStateValid])\r\n<\/code><\/pre>\n<p>The beauty is that any number of validation functions can be added to this list and <code>validateField<\/code> will work reliably. Moreover, it is trivial for other developers to read such a descriptive list of validations and understand what is required of the field.<\/p>\n<h2 id=\"testing\">Testing<\/h2>\n<p>Testing this code is also trivial:<\/p>\n<pre><code>func test_whenTextFieldIsValidState() {\r\n    \/\/ Given\r\n    let textField = UITextField()\r\n    \/\/ When\r\n    textField.text = &quot;NY&quot;\r\n    \/\/ Then\r\n    XCTAssertTrue(textField.isStateValid(textField.text!))\r\n}\r\n\r\nfunc test_whenTextFieldIsInvalidEmail_withUnderscoreCharacter() {\r\n    \/\/ Given\r\n    let textField = UITextField()\r\n    \/\/ When\r\n    textField.text = &quot;thibault+test@_gmail.com&quot;\r\n    \/\/ Then\r\n    XCTAssertFalse(textField.isEmailValid(textField.text!))\r\n}\r\n<\/code><\/pre>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>This implementation gives me a lot of options if I want to combine multiple validation functions for a text field &#8211; I simply create an extra validation function and apply it. Moreover, it provides a very descriptive way to understand what validations need to take place for a given text field. And, it is very easy to test.<\/p>\n<p>Though many iOS developers are not familiar with functional concepts, it sometimes pays off to start by thinking through how to solve a small problem in a functional way. Creating functions with minimal responsibilities can make code clean and concise. It made my code easy to test and scale. On top of that this functional approach perfectly interoperates with my object-oriented code.<\/p>\n<p>So far this functional solution has proven to be very efficient for the projects I\u2019ve used it in, and I hope it will be useful for you as well! You\u2019ll find a Xcode playground in this <a href=\"https:\/\/github.com\/klein-thibault\/TextFieldValidation\">repository<\/a> that has all the code I used in this article.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It is very common for an app to validate user input and provide instant feedback when something is typed incorrectly. In this article, I will walk through the implementation I worked on to validate a text field\u2019s string. I decided to attempt a functional approach and found a solution that is reusable and scalable for&hellip; <a class=\"more-link\" href=\"https:\/\/thibaultklein.com\/ios\/a-functional-approach-to-uitextfield-validation\/\">Continue reading <span class=\"screen-reader-text\">A Functional Approach to UITextField Validation<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-175","post","type-post","status-publish","format-standard","hentry","category-ios","entry"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6mZvu-2P","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts\/175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/comments?post=175"}],"version-history":[{"count":2,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts\/175\/revisions"}],"predecessor-version":[{"id":184,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts\/175\/revisions\/184"}],"wp:attachment":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/media?parent=175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/categories?post=175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/tags?post=175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}