Sometimes the best way to learn is to do the work. When you
reach the end of these
tutorials
you will have a working shipment tracking application for iOS.

Static Cells and TextFields

Now that we are ready to add Shipments, we have to modify
the tableview we created in order to have it display only one cell. After all,
we will only be adding one shipment at a time. For this we will use Static
Cells instead of Dynamic Prototypes. A dynamic prototype is a cell that will be
mass-produced dynamically (on the fly). A static cell is used to create one or a
few individually distinct cells according to a limited set of requirements. For
example, we only need one of said cells and they will not require dynamically
changing data. Our unique cell only requires a textfield the user can fill in.

In storyboard, select the AddShipmentViewController
tableview and switch from Dynamic Prototype cells to Static Cells. (Figure A)

Figure A

Delete the bottom two cells as you will not need them. Simply
click on them and hit the delete key. Now to make it look more professional,
set the table view style to “grouped” so your cell looks like Figure B.

Figure B

Now drag a Text Field control from the Object library into
the cell and center it. Now let’s size it up to be roughly the size of the cell
itself and set it to Borderless so you basically cannot tell the Text Field is
there. Notice we used a Text Field and that’s because it’s a control made to
receive user input of varying size and it can respond to user interaction in a
way Labels can’t. So your cell now looks like Figure C.

Figure C

This is when that hierarchy view of your storyboard scenes
and objects comes in handy. It should look like Figure D.

Figure D

This makes it clear that the AddShipmentVC contains the
table view, which contains the section with a cell that contains the text field.
Sometimes you will accidentally drop a text field or label outside of a cell
and when you run the app you will go crazy trying to find it.

Run the app and notice that as soon as you tap on the text
field (inside the cell) the keyboard slides in and you can type. However, also
notice what happens if you tap on the right edge of the cell, where the text
field ends and there is still a bit of cell left over. (Figure E)

Figure E

You tapped on the actual cell, so the cell is responding to
its class method to respond to a tap by highlighting it blue. Let’s disable it
by adding this method to your AddShipmentVC .m file:

– (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

return nil;

}

And go ahead and set the cell’s Selection Style to None in
the Attributes Inspector in the storyboard.

Now let’s use another advanced XCode feature (as the Editor
Embed In feature). Look at the top right (Figure
F
) and notice these buttons.

Figure F

I have the Standard Editor open but not the Assistant Editor
nor the Version Editor. I also have the Navigator and Utilities pane open but
not the Debug pane. We are going to use the Assistant Editor to create an
outlet this time, but so it doesn’t get so crowded we will close the Utilities
pane. Go ahead and open the Assistant Editor. Since it is so crowded now, go on
and close the Utilities pane. If you don’t close the Utilities pane, your XCode
window will look like Figure G.

Figure G

Go on and close the Utilities pane so you have more room to
maneuver. If you want a cleaner look you can even close the Navigator pane on
the far left. In any event, your AddShipmentVC should appear in storyboard and
the Assistant Editor should have automatically selected the respective .h file
and displayed it. Now the interesting part – Ctrl + drag from the text field in
storyboard to the AddShipmentVC .h interface.

You will get a popup like Figure H.

Figure H

Note: Make sure
to drag to the @interface of your AddShipmentViewController and not to that of
the AddShipmentViewControllerDelegate protocol.

Notice it is trying to create a UITabelViewCell type outlet.
That is no good! We are trying to create an outlet for the text field so we can
access it in code and capture the user’s input. Click cancel and make sure you
select the text field control in the storyboard and repeat the Ctrl + drag
operation. You want to see something similar to Figure I.

Figure I

When you drag correctly, the hierarchy pane shows you have
correctly selected the text field. The storyboard shows the handles around the
text field. Finally the popup displays this outlet will be of type UITextField.

Make sure the fields are set to these values:

  • Connection: Outlet
  • Name: textField
  • Type: UITextField
  • Storage: Strong

Press the Connect button and notice how it creates the
property declaration. Don’t forget to @synthesize your new property and set it
to nil in the viewDidUnload method.

Change your AddShipmentVC done method to this:

– (IBAction)done:(id)sender

{

NSLog(@"Contents of the text field: %@", self.textField.text);

[self.delegate addShipmentViewControllerDidSave:self value:self.textField.text];

}

We slightly modified the delegate call to pass over the
textField.text value. Thus we must modify the receiving method in ViewController
to this (and log the value):

– (void) addShipmentViewControllerDidSave:(AddShipmentViewController *)controller value:(NSString*)value

{

NSLog(@"The value received in VC is %@",value);

[self dismissViewControllerAnimated:YES completion:nil];

}

This way we can receive the value and log it again. Don’t
forget to change the protocol method in AddShipmentViewController as well:

– (void)addShipmentViewControllerDidSave: (AddShipmentViewController *)controller value:(NSString*)value;

Now run the app and type in Shoes. Hit the Done button and
watch how the console logs the value two times. Once in the
AddShipmentViewController’s Done method and again in the ViewController’s
addShipmentControllerDidSave method.

Perfect! So we have successfully received the user input in
one viewcontroller object (vc object) into another vc object.

Polishing

It’s nice that when the user taps on the text field the
keyboard pops up. But that’s more useful when the user loads a screen with some
text to read and text fields to fill in. In our case the only thing to do is
fill in the text field thus it would be nice to simply present the keyboard as
soon as the new screen comes into view. So look for and add this method to the
AddItemViewController.

– (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

[self.textField becomeFirstResponder];

}

Now in storyboard select the text field and make the
following modifcations:

  • In placeholder set the
    value to “Shipment Name”
  • Set the Font to System 17
  • Scroll down and uncheck Adjust
    to Fit
  • Set Capitalization to
    Sentences
  • And set Return Key to Done

Additional features

There are many different options here you can play with. A
very nice user-experience oriented feature is to make keyboards of the type of
value you are entering into the text field. For example, if the user must enter
a Zip Code, use a Numeric Keyboard. If the user will enter an email or URL then
use the appropriate keyboard so the user doesn’t have to frantically look for
special symbols etc.

Finally, make sure the text field is selected and open the
Connections Inspector. Drag from the Did End on Exit event to the view
controller and pick the done action. This will fire the done selector when the
user hits the Done button on the keyboard.

Another simple feature you can add by a simple click is the
Auto-enable Return Key, which will automatically check the text field to make
sure there is at least a value in the text field before allowing you to tap the
Done button.

Okay, the next feature we will add is to check for valid
data before clicking the Done button to return and dismiss the
AddItemViewController. For that we need to make the view controller a delegate to
the text field. The text field will send events to this delegate. The delegate,
who will be our AddItemViewController, can then respond to these events and do
what is appropriate.

So let’s make sure our AddItemViewController interface line
looks like this:

@interface AddItemViewController : UITableViewController

The AddItemViewController is now the delegate for text field
objects in general. In this case we have to tell the text field object that the
AddItemViewController is its delegate. So go to storyboard and select the text
field. In the Connection Inspector, drag from “delegate” to the AddItemViewController
dock, like shown in Figure J.

Figure J

Now open the Assistant Editor and Ctrl drag from the Done
button to the AddItemViewController.h and name it doneBarButton. Add the
corresponding synthesize statement in .m and set it to nil in the viewDidUnload
method. Finally add this method to the AddItemViewController:

– (BOOL)textField:(UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

{

NSString *newText = [theTextField.text stringByReplacingCharactersInRange:range withString:string];

if ([newText length] > 0) {

self.doneBarButton.enabled = YES;

} else {

self.doneBarButton.enabled = NO;

}

return YES;

}

One last tweak

What we are doing here is getting the user input and placing
it into a string. Then we check to see if it’s empty and take the necessary
action. The only problem is that if you run the app now, the Done button is
initially enabled. If you go to storyboard and uncheck the Enabled Box of the
text field then it will work perfectly!

Also read: