Long Form Entry with Native UI Elements (Part 1)

longFormOne of my recent projects involved recreating the client’s HTML web form for submitting real estate listings.  I’ve spent the past couple of weeks tearing apart methods for handling this within native iOS Apps, and I have to say that I am not impressed with any of the available frameworks.   There was one that looked promising called QuickDialog (http://github.com/escoz/quickdialog), and I almost thought that it would fit perfectly.  Although the framework seems to be setup nicely, it really doesn’t work well with existing Apps that need the form to be integrated with UI elements such as a UITabBarController, etc.  And Storyboard integration is pretty much impossible.  I also needed some more complex elements using UICollectionViews for attaching images, which would require tampering with the framework to expand it to fit my needs.  Lastly, validation is also non-existant with this framework, and mandatory for my design.

There are tons of other frameworks that you can easily find via a quick Google Search, particularly at http://www.cocoacontrols.com.

After about a day of experimenting with other peoples code, I decided that I need to get my hands dirty and write this thing from scratch.  As tempting as it was to start with a UIScrollView and add in my UITextViews and UILabels, I found that using UIScrollViews like this inside Storyboards is an absolute nightmare.  My next option, which proved to be the best and most accepted by my more experienced peers, is to use a UITableView.

And so it begins …

There are some UI differences that you will most likely encounter when converting HTML forms, so I thought I would compile a list of all the ones I’ve encountered and my recommended solutions.

<select> to UIPickerView

UIKit does not provide any default UI element that replicates the way HTML <select> elements display options in a web browser (or not that I’m aware of).  The best way to handle this in iOS is to create a UIPickerView and assign it to a UITextField’s inputView.

The required delegate methods you’ll need are:

I didn’t find a need for multiple components within simple <select> elements, so you can easily just return 1 for numberOfComponentsInPickerView.  For returning the numberOfRowsInComponent, the easiest way is to just use a simple if statement to check for which picker view you’re passing into it, and returning the count for their respective arrays:

Be sure to return 0 if no pickerView is selected, or else it may not return a value and end up breaking your code.

Returning the titleForRow:forComponent: is as simple as above with using an if statement, but instead return the objectAtIndex:row from the respective picker view’s array:

And using the same setup again, when the user makes a selection, didSelectRow:inComponent: will update the respective UITextView.text.  This method doesn’t require a return value:

<input type=”radio” …/> to Custom UISwitch

Another form element that I found myself needing was a simple toggle element for defining boolean values.  This will also work for <select>’s that simply have a Yes / No option set.  These elements can be translated into a custom UISwitch.  Apple provides a default “On/Off’ text with the standard UISwitch, but this would make no sense for a lot of my options.  Fortunately, you can set a custom image to your UISwitch and simply embed the text within the image.

In accordance with the UISwitch Class Reference, the image size must be 77px wide x 27px tall.  Then it’s simply a matter of setting the onImage and offImage properties of your UISwitch.

In the next part(s), I’ll talk more about selecting keyboards, navigation with an accessory view, validation and form submission methods.  Feel free to leave questions and comments below.

Why Can’t We Merge Storyboards?

There’s no denying that Storyboards are an amazing addition to our App development toolset, but there seems to be a clear divide between developers who enjoy them and those who do not.  And it seems that those who don’t are developers who work collaboratively on teams.  For example, Adam Ernst, an iOS Engineer for Facebook, was asked at the Mobile DevCon on April 13th, 2013, in New York after presenting How We Built Facebook for iOS on how they handle .xib and .xcodeproj merging.  His answer was pretty much the same as most others I’ve seen online:

Don’t use xibs is the answer.  Not only because they’re not mergeable, but they’re a pain to deal with localization.  So, all your interfaces and everything are in code.  And yeah, Xcode projects are not easily mergable.  We just deal with the pain.  We have merge conflicts once in a while, sadly.
– Adam Ernst, Facebook

Curiosity struck me.  How hard could it be?  I decided to have a look at why this has become the generally accepted answer.  Storyboards at their core are just XML files, right?  Here’s an example blank Storyboard file after adding it to a project:

You can view the source code of your own Storyboard by right clicking the file in the Project Navigator and clicking “Open As > Source Code”.  Now, let’s take a very simple problem and see how complex this can get.

The Scenario:

You have a team of 2 developers, each of whom is tasked with managing a simple View Controller within a shared Tab Bar Controller.  For the simplicity of this problem, there will be nothing but a single View within each controller, and a Label stating which view is being displayed.  The tabs are arranged from left to right, Developer A and Developer B respectively.  Developer A’s View background must be colored Green, and Developer B’s View background must be colored Blue.  Each developer will leave a blank View Controller in place of the other’s, which will aide in the merging process (I hope).

Merging with Storyboards:

Developer A’s Storyboard:

DevA

Developer B’s Storyboard:

DevB

Xcode provides a utility for merging files called FileMerge, located in the Xcode menu under “Xcode > Open Developer Tool > FileMerge” (also located at /Applications/Xcode.app/Contents/Applications/FileMerge.app).  Using this utility, we can identify 17 differences.

FileMerge

Each of the differences can be selected individually and an appropriate Action selected from the bottom Right corner.  Let’s attempt to resolve these differences 1-by-1:

  1. Although the initialViewController for each Storyboard is properly set, the IDs of respective view controllers are different in each file.  Because the initialViewController is Developer A’s, we’ll set this to “Chose Left”.
  2. We’ve reached a point of contention.  It seems that FileMerge doesn’t understand that these XML elements are suposed to be different objects, and instead would like us to override the other View Controller’s information.  This is not what we want to do at all …

… /facepalm …

So, What Happened?

Well, this is the point where we come to a crude discovery that Storyboard  XML files are not hierarchal, and Merge/Diff utilities like FileMerge will not help to resolve this problem.  In fact, as of this writing, I don’t know of any utility that will make any of this easy to do.  If you you, feel free to drop a comment below and shed some insight onto this problem.  As an independent developer, I’ve never found myself in a situation where I would actually need to do something like this.  This experiment was purely created for the sake of exploring the difficulty of merging Storyboard files, and left here for your educational entertainment.

Moral of the Story (TL;DR)

If you are part of an iOS development team, handcode all of your UI elements.

NSLog(@”Hello World, Again!”);

Since having switched gears several years ago and pushing most of my development work into my company website at http://www.nittanygeek.com, my personal website has been incredibly dormant in activity.  I’ve recently sparked a strong interest in rekindling my blogging, mostly which relates directly to my experiences and work as an iOS Application Developer.  The past several years have brought along quite a few changes in my life.  I’m glad I’ve made the tough decisions that lead me to where I am today, and I look forward to an outstanding future.

Allow me to bring you up to speed …

About a year ago, I was presented an opportunity from an old colleague of mine to begin working as an independent iOS developer.  I’ve only but dabbled in Objective-C and Xcode beforehand, but I have always wanted to really push my skills into developing amazing iOS Apps and getting my own work into the Apple App Store.  With understanding of my novitiate beginnings, my journey into iOS development truly began.

Although I have learned an incredible amount over the past year, I am by far an expert in the field.  Everyday is a learning experience and I am constantly refining my knowledge to become better as I go.  Along my way, I’ve learned quite a few tricks and tips from much more experienced developers.  This blog is my outlet to share these experiences with everyone, tenderfoots to old hands.  Welcome.