April 22, 2009

TableFormEditor v1.4: text field settings

A while ago, I introduced a reusable class for producing editable forms. This article can be read here. There was also a followup article containing a detailed usage example and some bug fixes in the TableFormEditor code. I have been using this class since then, and it quickly became clear that I needed a way to configure the text fields that were used in the form. For instance, one of the fields in my app takes a URL as input, and I would have liked to use the special keyboard that is designed for that type of input. This forced me to do some research on how to configure text fields. This research culminated into these two articles: part 1 and part 2. Now it is time to put this research into the TableFormEditor class. I came up with a solution that may not be the best, but since I need to make some progress on my app, I forged ahead and implemented this solution. Comments are appreciated on other ways to do this. It currently serves its purpose and might even be deemed "clever". If you are familiar with the TableFormEditor class, you know that you provide the field labels in an array. These labels are also used as keys to a dictionary that contains the field data. The edited data is also returned in a dictionary, again keyed by the row labels. Even if you don't use the field rows as labels, you still need to provide those for keying purposes. I extended this idea by allowing you to provide text field properties for each field. These properties are set to configure the behavior of the text field, as well as the keyboard behavior. All the supported properties are described in the two-part article mentioned above. I first thought about using a dictionary to hold the properties, or creating a new class, but decided to use a real UITextField object to hold the properties. After all, this class already has all the properties I want. What you do is create a UITextField object, set all the properties you need, and put this object in a dictionary. The field labels provide the dictionary keys, just as they do for the field data dictionary. It's important to understand that these UITextField objects you create are not used in the GUI; they are only used to hold values for properties, then they are thrown away. In this sense, they serve as "prototype" UITextField objects. The reason I chose to do it this way was based purely on convenience. There was no sense creating another class with all the same properties. And when setting the properties, XCode knows what the properties and it does the code completion for you. I have modified the TableFormEditor class to have an additional property: textfieldProto This is a mutable dictionary. The keys are the label names of each field. The value for each key is a UITextField object that has all the desired properties set. I have modified the example to have 4 fields:
  1. name field. For this field I would like auto correction turned off, but would like to auto capitalize the beginning of each word.
  2. age. This field is all numbers, so I would like the numeric keypad to come up when this field has the focus.
  3. homepage. For this, I want the URL keyboard, and turn off any auto capitalization and auto correction.
  4. password. This field should use the secure key feature, which dots out each letter as you type it.
The following is the code snippet from the example that demonstrates how you create the UITextField prototype objects and set them in the TableFormEditor object:

   // create the dictionary to hold the text field properties
   NSMutableDictionary* textFieldProto = [[NSMutableDictionary alloc] initWithCapacity:4];
   // prototype for the Name field
   // shrink the font to fit, don't autocorrect, autocap first letter
   UITextField* tf = [[UITextField alloc] init];
   tf.adjustsFontSizeToFitWidth = YES;
   tf.minimumFontSize = 7.0;
   tf.autocorrectionType = UITextAutocorrectionTypeNo;
   tf.autocapitalizationType = UITextAutocapitalizationTypeWords;
   // add it to the dictionary
   [textFieldProto setObject:tf forKey:@"Name"];
   [tf release];
   // prototype for the Age field
   // use the numeric keyboard
   tf = [[UITextField alloc] init];
   tf.keyboardType = UIKeyboardTypeNumberPad;
   [textFieldProto setObject:tf forKey:@"Age"];
   [tf release];
   // prototype for the Homepage field
   // use the URL keyboard, turn off autocorrect, show clear button, autocap off
   tf = [[UITextField alloc] init];
   tf.keyboardType = UIKeyboardTypeURL;
   tf.autocorrectionType = UITextAutocorrectionTypeNo;
   tf.autocapitalizationType = UITextAutocapitalizationTypeNone;
   tf.clearButtonMode = UITextFieldViewModeAlways;

   [textFieldProto setObject:tf forKey:@"Homepage"];
   [tf release];
   // prototype for the Password field
   // use secure entry
   tf = [[UITextField alloc] init];
   tf.secureTextEntry = YES;
   [textFieldProto setObject:tf forKey:@"Password"];
   [tf release];

   // now register all the text field prototypes
   form.textFieldProto = textFieldProto;
The updated example XCode project is available for you to play around with, as well as the updated TableFormEditor class to support text field prototypes,  using this link.

1 comment:

  1. Hi John,

    This is a great script - a life-saver for me. I have a couple of issues though - I wonder if you have any thoughts. The first is there is a little black dot that appears just under the navigation bar when the edit view is displayed. It disappears almost straight-away but its odd, and I can't see what's drawing it and how to get rid of it.

    Also, once you edit the form and click save, the view gets removed. If I call up the view again none of the data is remembered except for the first 2 rows (I have 7 rows). Can you think why that would be?

    Many thanks! Craig