<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Fields on A&#43; programming moments</title>
    <link>https://aplus.rs/tags/fields/</link>
    <description>Recent content in Fields on A&#43; programming moments</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 17 Sep 2019 09:40:00 +0000</lastBuildDate>
    
	<atom:link href="https://aplus.rs/tags/fields/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Modeling form field</title>
      <link>https://aplus.rs/2019/modeling-form-field/</link>
      <pubDate>Tue, 17 Sep 2019 09:40:00 +0000</pubDate>
      
      <guid>https://aplus.rs/2019/modeling-form-field/</guid>
      <description>&lt;p&gt;Let’s go back to example from previous intro post – regular one-line text field.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://aplus.rs/images/2019/fields-login-form.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;First, let’s build a simple &lt;code&gt;FieldCell&lt;/code&gt; subclass, which contains &lt;code&gt;UILabel&lt;/code&gt; for the title and &lt;code&gt;UITextField&lt;/code&gt; for the value.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;TextFieldCell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FieldCell&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;c1&#34;&gt;//	UI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kr&#34;&gt;@IBOutlet&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;titleLabel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UILabel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kr&#34;&gt;@IBOutlet&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;textField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UITextField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nothing unusual here: both controls are private for the cell, as they should be.&lt;/p&gt;
&lt;p&gt;Now, let’s build a &lt;a href=&#34;https://github.com/radianttap/Fields/blob/master/Fields/CellModels/TextFieldModel.swift&#34;&gt;(view)model object&lt;/a&gt; to supply the required values. First, we need a unique ID for this field:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;/// Model that corresponds to TextFieldCell instance.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;TextFieldModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FieldModel&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;c1&#34;&gt;///	unique identifier (across the containing form) for this field&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we need few strings that corresponds to values shown in label and text field:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///	String to display in the title label&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///	Value to show inside the textField&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///	Placeholder value to show inside the textField&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;placeholder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that &lt;code&gt;value&lt;/code&gt; is plain &lt;code&gt;String&lt;/code&gt;. Your form data source object, whatever that may be, is responsible to convert application’s model objects into TextFieldModel.&lt;/p&gt;
&lt;p&gt;Now comes the fun part. Text field can be used to input unlimited variety of values: username, password, street name, email, city name, phone number, card number…anything, really. Some of these uses require custom configurations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For passwords, you need to setup the &lt;code&gt;UITextField&lt;/code&gt; to be secure text field.&lt;/li&gt;
&lt;li&gt;For the iOS’ password auto-fill feature, you need to set &lt;code&gt;textContentType&lt;/code&gt; to &lt;code&gt;.password&lt;/code&gt; (similar for username).&lt;/li&gt;
&lt;li&gt;If you are inputting phone numbers, you should set &lt;code&gt;keyboardType&lt;/code&gt; to &lt;code&gt;.phonePad&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Similar for email fields. On and on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There’s an ever increasing array of possible configuration options. Making a model property for each one is fool’s errand. Instead, let’s expose the &lt;code&gt;UITextField&lt;/code&gt; through custom closure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///	Custom configuration for the textField.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///	Default implementation does nothing.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;customSetup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UITextField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Void&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way, the model stays really clean and endlessly expandable while the field itself is still private and encapsulated inside the &lt;code&gt;TextFieldCell&lt;/code&gt; component. If you have custom config, supply the closure and it will be executed at the end of the &lt;code&gt;cell.populate(_ model:TextFieldModel)&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Finally, we need a way to receive the final edited value back. For that, we use the similar closure approach:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///	Method called when editing is done.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;///	Default implementation does nothing.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;valueChanged&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TextFieldCell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Void&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the minimal setup for the field. You can expand this to whatever you want, depending on the cell design. Let’s say that you want to show some glyph icon that suggest when a particular cell is mandatory + each field has an icon in-front of it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;TextFieldModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FieldModel&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;isMandatory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Bool&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;icon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UImage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now adjust the cell design to use these new properties and…done. There are really no design limits with this approach &lt;em&gt;and&lt;/em&gt; there is nothing left unused; you adapt the Cell + Model for your intended design and then go on and just build your forms by creating instances of these model objects.&lt;/p&gt;
&lt;p&gt;Ok, going back now to the cell. When it’s instantiated from its .xib file, first clean any contents (set in Interface Builder) and then process edited value when editing ends:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;override&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;awakeFromNib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kc&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;awakeFromNib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;cleanup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;textField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addTarget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;action&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;#selector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;editText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;editingDidEnd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;textField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addTarget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;action&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;#selector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;editText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;editingDidEndOnExit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt;	&lt;span class=&#34;kr&#34;&gt;@objc&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;editText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sender&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UITextField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;valueChanged&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sender&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;editText()&lt;/code&gt; method has to call model’s &lt;code&gt;valueChanged()&lt;/code&gt; closure. In order to call it, we need to save it locally as the cell’s property. We do this in the same method that populates the cell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;populate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TextFieldModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;valueChanged&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;valueChanged&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;render&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;render&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TextFieldModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;titleLabel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;textField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;textField&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;placeholder&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;placeholder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customSetup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;textField&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that’s about it. The very same approach is applied to all other models, like &lt;a href=&#34;https://github.com/radianttap/Fields/blob/master/Fields/CellModels/ButtonModel.swift&#34;&gt;ButtonModel&lt;/a&gt;, &lt;a href=&#34;https://github.com/radianttap/Fields/blob/master/Fields/CellModels/ToggleModel.swift&#34;&gt;ToggleModel&lt;/a&gt;, &lt;a href=&#34;https://github.com/radianttap/Fields/blob/master/Fields/CellModels/TextViewModel.swift&#34;&gt;TextViewModel&lt;/a&gt; etc. They are fairly self explanatory, I hope.&lt;/p&gt;
&lt;p&gt;Not all fields are this straight-forward thus in next post I’ll look at the &lt;code&gt;PickerCell&lt;/code&gt; and its model.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Trouble with form fields in iOS apps</title>
      <link>https://aplus.rs/2019/trouble-with-ios-forms/</link>
      <pubDate>Thu, 05 Sep 2019 14:22:00 +0000</pubDate>
      
      <guid>https://aplus.rs/2019/trouble-with-ios-forms/</guid>
      <description>&lt;p&gt;Data models driving the forms are different from one app to another. Form designs tend to be different. Input methods change over time, accessibility is always looming as task you should not forget. On top of that, each app aims to distinguish itself from the pack and thus designers are aiming to infuse the input fields with some life and offer small wins for the end customer using them.&lt;/p&gt;
&lt;p&gt;Such a variety and open goals are nightmare for developers. We love stuff that can be fully modeled, rendered using pre-defined rules. And we love to use and re-use existing code without much modifications.&lt;/p&gt;
&lt;p&gt;All together, it makes the task of building declarative, easy-to-expand and free-to-augment form libraries next to impossible. iOS world is not lacking in attempts, some better than others.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/xmartlabs/eureka&#34;&gt;Eureka&lt;/a&gt; has near 10k stars on GitHub. It has neat interactions and supports the largest variety of cells, including ability to add your own custom ones. But it uses a home &lt;a href=&#34;https://blog.xmartlabs.com/2015/09/29/Introducing-Eureka-iOS-form-library-written-in-pure-Swift/&#34;&gt;grown syntax&lt;/a&gt; using custom Swift operators which &lt;em&gt;increases learning curve&lt;/em&gt;. It has &lt;em&gt;validations built-in which is conceptually wrong&lt;/em&gt; in light of my preferred application architecture — validations are defined by business rules, thus they should live in middleware, not UI. That’s a lot of features, which translates to huge dependency when introduced into your project.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ra1028/Former&#34;&gt;Former &lt;/a&gt; has an advanced DSL of its own. You need to learn its template syntax in order to build a form. Plus it’s rather old now, layout is built purely in code using AutoLayout’s old visual syntax. &lt;em&gt;Both of those are big turn-offs.&lt;/em&gt; However, it has really wide range of pre-built cells and excellent implementation of inline-field editing, including date pickers, multi-value pickers etc.&lt;/p&gt;
&lt;p&gt;iZettle’s Form is another huge layout framework based on reactive programming concepts. &lt;a href=&#34;https://github.com/iZettle/Form/blob/master/Documentation/Forms.md&#34;&gt;Forms&lt;/a&gt; are just one part of it all; on first glance, I don’t think you can use just the Forms bit without the rest. A framework like this is really not my cup of tea but it deserves to be mentioned if you are into signals and observers.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ortuman/SwiftForms&#34;&gt;SwiftForms&lt;/a&gt; is another attempt with rather weird approach to styling. It has custom selection handlers that you need to learn but other than that it’s fairly simple to pick up. Not much magic under the hood, which is a plus for me.&lt;/p&gt;
&lt;p&gt;SwiftTalk duo built a very modern &lt;a href=&#34;https://talk.objc.io/collections/building-a-form-library&#34;&gt;Form Library&lt;/a&gt; based on somewhat advanced usage of Swift generics. Code is rather hard to comprehend unless you are &lt;em&gt;really&lt;/em&gt; proficient in Swift. I both like and don’t like how it can create multiple forms, spread out over multiple VCs, using one data-source (they call it state) declaration. Quite smart, if you are willing to extend it further and learn how it works internally so you can actually adapt it to your needs.&lt;/p&gt;
&lt;p&gt;Lastly: &lt;em&gt;all of these libraries are using table view cells&lt;/em&gt;. I know the reason; self-expanding layouts are quite easy to implement with table rows. It scrolls as much as needed and adapts to input methods. UITableViewController handles the keyboard appearance and scrolling stuff into view, for free.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I have built so many forms in last 5 years, I honestly believe it’s impossible to create a forms library that will work out of box &lt;em&gt;if&lt;/em&gt; you care about design consistency across your app. I &lt;a href=&#34;https://github.com/radianttap/RTFormKit&#34;&gt;tried&lt;/a&gt; as well. There will always be the need to tweak and adjust, add custom information here and there. For every single library I tried or built, it turned out that I needed to adjust either its behavior or look&amp;amp;feel or both.&lt;/p&gt;
&lt;p&gt;Plus, iOS screens are ever expanding and single-column forms may not be enough anymore. Even with single column, you may have some data which are looking better when shown side by side (state / post code / city of an address, for example).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Let’s look at the simplest possible form that you may need in any app: login, with just username and password.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://aplus.rs/images/2019/fields-login-form.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;You need something like &lt;code&gt;TextFieldCell&lt;/code&gt;, populated using title and optional string value and be done with it. Simple, eh?&lt;/p&gt;
&lt;p&gt;Here’s some challenges for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;setup custom configuration like isSecure for the password field&lt;/li&gt;
&lt;li&gt;show mandatory mark, only on some fields&lt;/li&gt;
&lt;li&gt;show/hide per-field error messages / validation rules&lt;/li&gt;
&lt;li&gt;add arbitrary textual or image hints above or below the form field&lt;/li&gt;
&lt;li&gt;looks too bland — designers want to have the title labels appear over the field when no value is present but to appear like on the picture when value is set&lt;/li&gt;
&lt;li&gt;when person activates the text field, that hovering label should slide upwards&lt;/li&gt;
&lt;li&gt;it should also slide back if you activate and deactivate the field without entering value&lt;/li&gt;
&lt;li&gt;what about cute icons? maybe in front of the field? maybe behind the field? maybe inside the field, before the text?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I could go on and on, just continue with design requests I had to handle in last 10 years or so. This is wild west territory. The amount of customization points for the model driving such display counts in dozens.&lt;/p&gt;
&lt;p&gt;That’s just user/pass using one type of field; imagine what other model data can be shown in text fields: address parts, person names, phone numbers etc. Addresses have things like state/province, zip/post-codes and city names - which can be short (say Richmond, NY 12322) thus it makes sense to show them side-by-side instead of in separate rows. Etc.&lt;/p&gt;
&lt;p&gt;That’s just a minor set of possible customizations related to &lt;em&gt;field display&lt;/em&gt;. Getting values back and re-connecting them with your model objects is another set of challenges &lt;em&gt;if&lt;/em&gt; you want to have a declarative way to setup the form.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’ve come to believe the right approach is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cover just the basics, don’t even attempt to model everything &lt;em&gt;in advance&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;make the model truly expanding by not making any assumptions about the look and feel&lt;/li&gt;
&lt;li&gt;build Cells’ look &amp;amp; feel on case-by-case basis then alter its corresponding Model to support it&lt;/li&gt;
&lt;li&gt;base all of it on some variant of self-sizing UICollectionView(Flow)Layout&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;=&amp;gt; it can’t be neither a library nor framework.&lt;/p&gt;
&lt;p&gt;You start with bare cell/model combination then adjust it to the design at hand. You then build each of your form data sources independently by transforming your actual model objects into TextFieldModel, ToggleModel etc. These are then used to populate their corresponding cells. While this inevitably leads to more work per form you will still be able to fairly quickly build any kind of form, with lots of easy copy/paste.&lt;/p&gt;
&lt;p&gt;Over the last year or so, I was slowly building &lt;a href=&#34;https://github.com/radianttap/Fields&#34;&gt;Fields&lt;/a&gt; which you can plow however you like (all puns intended). I gave up trying to make it perfect, gave up trying to handle all possible cases out of the box and just wanted to have a solid base to adapt for each and every form I have to build.&lt;/p&gt;
&lt;p&gt;Thus the cell design is really, really simple – on purpose. I have field title and the field itself with corresponding value. There’s no hints, explanation, per-field error messages, mandatory glyphs or anything like it. I add them as I need them in each specific implementation. Plus, each field is designed in Interface Builder, making it easy to preview behavior when the cell, as container, is too small or too large. Lastly — entire form uses vertically self-sizing cells, thus you can put as much content inside as you want.&lt;/p&gt;
&lt;p&gt;There’ll be more details in &lt;a href=&#34;https://aplus.rs/tags/fields/&#34;&gt;upcoming post(s)&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>