The Jungle, Part 1: Basic UI Elements


Recently, we’ve been discussing concepts. This week, we’re going to take a break from that and start working on an app that will cover many of the high-level topics in the iOS SDK and allow you to build many interfaces with Interface Builder. We’ll start from a bare-bones project template and work our way up from there.

I’m running Xcode 4.1 on Mac OS X 10.7 Lion. Xcode 4 is available on the Mac App Store for both Snow Leopard and Lion. You can use Xcode 3, but some things (especially Interface Builder) will be different, so you may have to “translate” some of the screenshots. Nevertheless, the procedure in Xcode 3 is still similar, just in different places. Xcode 4 is the future, and despite the criticisms, does have some really nice features. And it includes the latest features, many of which make coding much easier. So fire up Xcode, and let’s get started.

Setting Up the Project

When you first start Xcode 4, you’ll be presented with the Welcome to Xcode window. As you create more projects, the list to the right will get populated with those projects. For now, read the texts if you wish, but click on “Create a new Xcode project” to get started.

Xcode 4 Welcome Window

Xcode 4.1 Welcome Window

A new window will appear, and a modal sheet will slide down. From the left column, under iOS, select “Application”. Then, in the top-right pane select “Window-Based Application” (it may be called “Empty Application”). Click Next.

For Product Name:, call it “SDK Demo”. You can call it something else, but you’ll have to make adjustments down the road. You can ignore the other options; we’ll talk about them in later posts. Click Next and find a place to save your project.

Xcode Main Project Window

Xcode Main Project Window

Xcode should now present the main project window, and your project has been set up. At this point you can click on the circular Run button in the top-left of the main Xcode window, which will launch your app in the iPhone Simulator.

All you’ll see at the moment is a blank white screen—that’s because we haven’t done anything yet. Let’s do that now.

The Root View Controller

All iOS applications should have a root view controller. There are books and tutorials online that tell you to do your whole interface in the app delegate (I’ll talk about this below)—which you can, but it is not recommended for anything but the simplest project. Sometime in the future, applications will be expected to have a root view controller—they will no longer be optional. It’s just a good idea. So let’s create one.

In Xcode, go to File > New > New File… (Command-N). On the left, select Cocoa Touch under iOS and select the second option, UIViewController subclass. Click Next. For Class, call it RootViewController. Make sure it’s a subclass of UIViewController, and that it comes with a XIB for the user interface. Click Next, and accept the default save location. Click Create.

New File View

New File Picker

New File Name

Name new file

In the File Navigator, click on AppDelegate.h. There is some existing code provided by the template; leave that there. Note that the provided code may differ across versions of Xcode, but the general meaning and end results are the same. Add the following lines to the existing code to set up the header file.

#import <UIKit/UIKit.h> 
@class RootViewController;    // Add this line
@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) RootViewController *rootViewController;    // Add this line too 
@end

Switch to the .m file, either by selecting the file in the File Navigator, or pressing Command-Control-↑. In this case, there’s a lot of comments and sample code that we aren’t going to use now. You can keep it if you wish, or replace the file with this code:

#import "AppDelegate.h"
#import "RootViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize rootViewController = _rootViewController;

- (void)dealloc {
	[_window release];
	[_rootViewController release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
	_rootViewController = [[RootViewController alloc] init];
	self.window.rootViewController = self.rootViewController;
    [self.window makeKeyAndVisible];
    return YES;
}

@end

The code of interest is in the application:DidFinishLaunchingWithOptions: method. Every app starts off as a window, and that’s what the first line does—it creates a window that is the size of the screen, and autoreleases it. That line, and the next, which sets the window’s background color to white, is provided by the template. The next two lines are what’s important here—you’re initializing the RootViewController instance, and assigning it to the window’s rootViewController property, which was new in iOS 4.0. In iOS 3.x and earlier, you couldn’t directly set the view controller; you had to set the view instead.

[_window addSubview:self.rootViewController.view];

The last two lines actually display the window, and return YES. If you return NO, the app will then be quit. The app setup is now done. Running the app, you won’t notice any visual difference, but the setup is indeed complete.

The App Delegate

Now is a good place to take a detour and talk about the app delegate. This class, created with every project, is the interface between the iOS system and your app. When the system has finished loading the app, the application:didFinishLaunchingWithOptions: method is called. In many cases, you can ignore the arguments to the method. Generally, here you perform some basic setup, including creating the main window and the root view controller as you saw above. In a game, you may also choose to initialize timers or graphics engines here, but make sure you don’t do something too time-intensive, or your app will appear to hang.

Other situations in which app delegate methods may be called include times when your app is being quit, in which you have a few seconds to do some last-minute processing or to save state, or when your app goes into or comes from the background. “The background” is only present in a multi-tasking environment (iOS 4.0 or higher on some iOS devices), when your app may be dismissed without being quit. In those cases, you may want to save state, or pause game timers, or close network connections.

Do note that in all these cases, you have limited time to do your processing, so you shouldn’t be calculating pi to 15 million digits here. Taking too long to do any processing will make your app appear to hang, and the system will try to avoid that.

A technical note: how does the system know which class the app delegate is? If you want to know, open up the Supporting Files group in the File Navigator. Select the main.m file. Inside, you’ll find this code:

UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]))

That fourth argument to the UIApplicationMain() function is the name of the app delegate class, passed in as an NSString. NSStringFromClass() takes a Class object (found by invoking the +class method on any class) and returns the string with its name. That’s how the system finds the app delegate.

Creating the Root View Controller

In this initial revision of our app, we’ll add in some basic functionality that shows off some basic UIKit elements. We will also be exploring Xcode 4’s new Interface Builder, included within Xcode’s main window.

Open up RootViewController.h and put in the following code.

#import <UIKit/UIKit.h>
@interface RootViewController : UIViewController {
	int buttonPressCount;
}

@property (nonatomic, retain) IBOutlet UILabel *buttonPressLabel;
@property (nonatomic, retain) IBOutlet UILabel *echoLabel;

- (IBAction)simpleButtonPressed:(id)sender;
- (IBAction)textFieldTextDidChange:(id)sender;
@end

You add two label outlets and two action methods. The IBOutlet and IBAction qualifiers don’t affect your code at all, but they are a “hint” to Interface Builder as connect points.

Interestingly, the action methods take one argument, of a generic type. This sender object is the object that triggered the event. You could have written the method without the argument, but then you would not know which object triggered the method. In some cases, you can determine what course of action you want to take based on the sender object (you can hook up one action method to multiple objects), or access some property of the sender. We will use the second reason. By doing so, we can avoid declaring two additional outlets, only to access their properties. As you gain more experience, you’ll get a feel for which properties you need to declare and hook up, and which you can obtain from method arguments, cleaning up your code.

Setting Up the Interface

Blank XIB

Blank window with Utilities

UIView Attributes

UIView Attributes

With your declarations done, switch over to RootViewController.xib. Open up the Utilities pane by clicking on the third button in the View group in the toolbar, or by pressing Command-Option-4. Click in the main view to select it and bring up the Attributes.

The white background is a bit garish, so click on the double arrows at the right end of the Background popup. If you click in the middle, you’ll get the standard color picker. If you click on the double arrows, you get a list of recent colors, and some options that you can’t get in the color picker.

Color Choices

Color choices

Select the “Group Table View Background Color”. The main view will take on a blue-and-white pinstripe appearance. That’s better.

The bottom part of the Utilities pane has four small icons. Select the third one to bring up a list of UI elements you can use. The search bar at the bottom allows you to filter the results. Drag out a button into the main view.

UI Elements Library

UI elements library

As you drag, you’ll see blue guidelines appear—those are Apple’s recommendations for spacing, keeping your UI elements away from the edges of the screen, where they may be hard to hit, and away from each other, to prevent the wrong element from being touched. A guideline will appear at the middle of the screen. Align the button with the top guideline and down the middle.

Blue Guidelines

Blue guidelines

Using the horizontal drag handles, make the button about 160 pixels wide (there will be an overlay telling you the size; don’t worry about the exact value), and bring it back to the center using the guides. Double click in the center of the button to bring up a text-editing field. Type in “Press Me!” or something similar. Click off the main view to deselect the button.

Finalized Button

Finalized button

Drag out a label and center it. Move it up toward the button until the guide appears underneath the button, and leave it there. Again, make it 128 pixels wide and center it. Using the Attributes inspector, set the following properties:

Label Attributes

Label attributes

  • Set Alignment to centered
  • Make the Text Color Black (or Default)
  • Make the Shadow color White
  • Make the Shadow Offset 0 Horizontal, 1 Vertical (the default is -1)
  • Clear out the text, so that the label isn’t displaying “Label”

Drag out a text field. Make it 160 pixels wide, centered horizontally. The vertical position doesn’t really matter too much. Keep the default attributes for now; feel free to play around with them later. Now hold down the Option key. Click and drag the original label to a position underneath the text field. You’ll make a copy of the original label, including all the attributes.

Making Connections

Connections Inspector

Connections inspector

Now that we have the UI elements laid out, we’re going to connect it to our outlets and actions. There are many ways to do that; for now, because our inspectors are open, we’re going to use those. We’ll cover other methods in future posts.

Open the Connections inspector (the sixth option in the Utilities sidebar) or press Command-Option-6. Select the first object along the bar to the left—it looks like a light orange cube and when you mouse over it, the pop-up says “File’s Owner.” This is a proxy object (I’ll talk about that in a future post when we explore Xcode) that references the owner of the XIB—in this case, RootViewController.h. Selecting that, some outlets show up in the connections inspector. First we’ll wire up the outlets.

Click in the little circle to the right of the buttonPressLabelentry. Drag the cursor over to the label below the button, and let go. As you drag, you’ll see a blue line appear, starting from that little circle.

Visual connection—blue line

Blue line shows connection

The connection will show up in the connection inspector. Repeat the process for the echoLabel, connecting it to the label beneath the text field.

Shows Connection

Visual connection

Under the Received Actions section, drag from simpleButtonProssed: to the button in your interface. This time, you’re connecting an action; when you release, you’ll get a list of eventsthat the button can respond to. You can have different methods trigger based on what type of touch input the button receives.

UIControl Events List

Events list

Select “Touch Up Inside”, which means that the action will only be triggered if a finger touches down and up—what you would naturally do—all within the borders of the button. This is the most commonly-used choice for buttons. Connect textFieldTextDidChange: to the text field, but this time select Editing Changed for the event. This will have the method be called every time the text inside the text field changes—it’ll get called every time the user types a letter or hits the backspace.

Having wired up the entire interface, return to the code—open RootViewController.m.

Coding the Actions

You can replace the existing code with the following:

#import "RootViewController.h"

@implementation RootViewController
@synthesize buttonPressLabel = _buttonPressLabel;
@synthesize echoLabel = _echoLabel;

#pragma mark - Memory Management
- (void)dealloc {
	[_buttonPressLabel release];
	[_echoLabel release];
}

#pragma mark - View lifecycle
- (void)viewDidLoad {
	buttonPressCount = 0;
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view to relieve memory usage
	self.buttonPressLabel = nil;
	self.echoLabel = nil;
}

#pragma mark - Action Methods
- (IBAction)simpleButtonPressed:(id)sender {
	buttonPressCount++;
	NSString *pluralHandlerString = (buttonPressCount == 1) ? @"time" : @"times";
	NSString *displayString = [[NSString alloc] initWithFormat:@"Button pressed %d %@", buttonPressCount, pluralHandlerString];
	self.buttonPressLabel.text = displayString;
	[displayString release];
}

- (IBAction)textFieldTextDidChange:(id)sender {
	UITextField *textField = (UITextField *)sender;
	NSString *textFieldText = textField.text;
	self.echoLabel.text = textFieldText;
}
@end

The beginning isn’t of much interest—we’re importing files, synthesizing properties, and dealing with memory management. The viewDidLoad method is where you usually do some setup—initialize instance variables, or set some properties on UI elements. viewDidUnload is where you release your retained subviews (and any other properties that you initialize or create in viewDidLoad) to free up that memory, when your view disappears. The action methods warrant some discussion.

The first action method simply keeps track of the number of times the button is pressed and displays that. It uses the buttonPressCount instance variable, incrementing it each time the button is pressed. There is initially a string that uses the conditional operator to determine whether or not to use the plural form of “time.” Then that string is plugged into the final string, along with the run count, to form the displayString. This is then assigned to the text property of the corresponding label, which causes the text to be displayed. The string is released according to memory management rules.

The second action method uses the sender argument, first casting it to a UITextField. It grabs the current text value from the text field—this method is called every time the text changes, so the text value will be different every time, and then this text is assigned to the label’s text property as before. The text field manages its text property, so you don’t have to release it.

The Finished Product

Finished Project Version 1 Screenshot

Finished product

At this point, the first version of our demo app is done. Hit Run in the toolbar, and it should bring up the iPhone Simulator. Play around with the button presses and the text field. If you have build issues or warnings, post them in the comments or email me, and I’ll get back to you as soon as possible.

One More Thing

Once the keyboard shows up, you can’t get rid of it without quitting the app. Let’s fix that.

Add an action method called dismissKeyboard: to the header, which takes one sender. The sender will be the text field. Connect the method in IB to the text field’s Did End on Exit event. The implementation of the method should be like this:

- (IBAction)dismissKeyboard:(id)sender { 
    [(UITextField *)sender resignFirstResponder];
}

Now, if you hit the Return key on the keypad, the keyboard will slide away. The important part is the resignFirstResponder method call, which in the case of a text field will also dismiss the keyboard.

And that’s all there is to it.

Project Download

You can download the source for this project here.

IceFall!


IceFall Icon

IceFall

My friend came to me a few weeks ago for a simple game idea. I was glad to help him build up his concept, and after a few weeks (it’s true—the last 20% takes 80% of the time…), we have finished it. It’s a clean, simple game; it was a blast for us to make and we hope you enjoy it too. Please do us a favor and check it out! It would mean a lot to us.

IceFall
On the App Store

Design Patterns: Key-Value Observing


Key-Value Observing (KVO) is heavily used in OS X development in bindings and form a significant portion of UI design. However, with iOS, it takes on somewhat less significance and is mostly used as necessary to simplify program design. KVO “broadcasts” a notification whenever a property is modified, and any class can receive those notifications and handle changes as necessary. This helps to decouple your classes from each other, allowing more flexible and re-usable code, especially as your code grows large and you have many sets of MVC objects.

KVO Layout

KVO Structure

It is primarily used when you have one model object backing multiple controllers, in which case you can use KVO to update the model when any controller changes its data.

Preparing for Key-Value Observing

KVO is set up for you when you use properties. Whenever you use dot-notation or the setter methods to change a property, the corresponding KVO method is called and all receivers will be notified. If you do not use properties or write your own setters, you may want to manually call change notification methods; see the section below to do so.

Key-Value Observing Compliance

To be KVO-compliant, your class must first be KVC compliant. This means that you should have proper, working implementations for valueForKey: and setValue:forKey:. In addition, you should emit the proper notifications when changes are made.

As stated above, if you use standard setters, the notifications are called for you, and you don’t have to worry about them.

Manually Call Change Notifications

You may need to manually call notifications if you don’t use standard setters, if you want to minimize notifications for certain situations, or to package multiple changes into a single notification.

First, you have to override the implementation of automaticallyNotifiesObserversForKey:, which is a class method declared in the NSKeyValueObserving protocol. Given a key, if you want manual notification, return NO; otherwise, return YES. If the key is not recognized, call the super implementation. The default implementation in NSObject simply returns YES.

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey { if ([theKey isEqualToString:@"openingBalance"]) return NO; else return [super automaticallyNotifiesObserversForKey:theKey]; }

Then, to call the actual notifications, you call willChangeValueForKey: before changing the value, and didChangeValueForKey: after the change.

- (void)setBalance:(double)newBalance { // Should not compare double directly, // But means the same as if (balance == newBalance) if (fabs(balance - newBalance) < 0.0001) return; [self willChangeValueForKey:@"balance"]; balance = newBalance; [self didChangeValueForKey:@"balance"]; }

Note that to minimize redundant notifications, you can check to see if the value has actually changed.

Finally, you can call willChangeValueForKey: and didChangeValueForKey: multiple times with different keys to send multiple notifications if multiple values get changed.

Registering for Key-Value Observing

To register a class for Key-Value Observing, the observed class must be KVO-compliant for the properties that you want to observe (obviously), you must register as an observer, and implement the observing method.

Note that not all classes are KVO-compliant for all properties. Ensure compatibility as necessary in your classes, but note that properties in Apple’s code are only KVO-compliant of the documentation says so.

Register an Observer

The observed object must be made aware of the observer by sending the addObserver:forKeyPath:options:context: method. In your view controller, you might have the following method, which registers a model object as an observer for the balance property:

- (void)registerObserver { [modelObject addObserver:self forKeyPath:@"balance" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL]; }

The options argument takes one or more of the NSKeyValueObservingOptions values. You will most often use the constants in the example above, which tells the system to return both the original and new values. You specify both using the bitwise OR operator (|), the vertical bar.

The context is a pointer to anything you wish, and is provided as-is to the observer. You can use it as an identifier to determine the change, or to provide any other data. It is your responsibility to retain and/or release it as necessary; it is not retained by the system. The context can be used to identify your notifications. A problem may arise because you can register the same keyPath on multiple objects. You can therefore use a distinguishing context to determine the calling class. See this link for more information on how to solve this issue.

Receiving Notifications

All observers must implement the observeValueForKeyPath:ofObject:change:context: method. The observer is provided the original object and key path that triggered the change, a dictionary containing the details of the actual change, and the user-specified context described above.

The dictionary has a value accessed through the NSKeyValueChangeKindKey, which is a standard NSDictionary change key. It provides information about the change, returning an NSKeyValueChangeSetting. The exact values are defined in the link. You can also access the old or new values (depending on whether neither, one, or both were requested) through the NSKeyValueChangeOldKey and NSKeyValueChangeNewKey keys. If the property is an object, it is returned directly; scalars or C structs are wrapped as an NSValue object.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqual:@"balance"]) { // Handle change } else // Unrecognized keypath [super observeValueForKeyPath:keyPath]; }

Removing an Observer

To clean up after yourself, you should remove yourself as an observer by calling the removeObserver:forKeyPath: method.

- (void)unregisterForKVO { [modelObject removeObserver:self forKeyPath:@"balance"]; }

If you received a context from the notifications, you should only release it after removing the observer.

Extension: Cocoa Naming Conventions


The Cocoa framework and applications that use Cocoa (Touch) follow a fixed set of naming conventions that make the programs easier to read, use, and understand.

General Principles

  • Keep your code brief, but never at the expense of clarity. You’ll often see long method names in Cocoa—some programmers will complain about them, but the truth is that they make the code that much more understandable. And with Xcode’s code completion, you really don’t have to worry about all that extra typing. As an example, consider the method name removeObjectAtIndex:. That’s a very clear method name—you’re removing an object, and the argument takes an index. However, the method remove: is significantly less clear. Are you passing in an object to be removed, or an index to be removed? Or something else? The method never specifies.
  • Don’t add redundancy to names. Prefixes such as “my” or suffixes such as “object” are (almost, in the case of the latter) always unnecessary—it is obvious that it’s your variable, or that (in many cases) it’s an object.
  • 95% of the time, don’t abbreviate unless it is a well-known technical term, such as PDF or URL. Abbreviations are often not as obvious as you think they are, especially for developers from other lingual backgrounds.
  • Avoid noun/adjective-verb dualities. For instance, you may encounter a method called displayText. Does that method perform the action of displaying the text, or does it signify the text that is displayed (versus some private identifier text)? The developer has no way of knowing.
  • Consistency is important. Don’t have a count method in one class and a size method in another. Classes which have methods of the same name should do the same thing with those methods.
  • Prefixes are encouraged in Cocoa, and are used throughout Cocoa itself. Foundation and many desktop Cocoa classes begin with NS; UIKit classes begin with UI. Many developers who publish source code will prefix things with their initials, or some initialism of their company. Prefixes are especially important in determining who wrote the code, especially with generic names, such as the String class (which exists in languages such as Java).
  • Class names should have a noun involved. Other names, especially enumerated types/state representations, should have some resemblance to the class name. For example, UITableViewCell is a class, and you can specify a style using constants such as UITableViewCellStyleDefault or UITableViewCellStyleSubtitle. These constants are long, but make it clear that they work with UITableViewCell and involve its style. If you just had Default and Subtitle, they’re very ambiguous, could be used by other classes (which could lead to interesting mix-ups and collisions), and are not at all clear about what they’re referring to.
  • Categories are usually expressed as className+categoryName, such as the fictitious NSString+HTMLFormatting. Note there the “HTML” abbreviation, which is completely acceptable because HTML is widely understood.
  • Delegate and Data Source protocols will have the descriptor in the name—note UITableViewDelegate and UITableViewDataSource.
  • Other protocol names usually take a verb form of the noun they modify. For example, the NSCoding protocol works with NSCoder and NSDecoder classes.
  • Method Names

  • Method names usually begin with a lowercase letter, and each subsequent “word” in the name has its initial letter capitalized. Avoid abbreviations that are not clear. Most methods should not begin with a prefix, but you may use a prefix to denote a private method. You may also use a leading underscore (no, Apple does not reserve this method, although any Apple method with a leading underscore is supposed to be private).
  • Methods that perform an action should start with a verb. Auxiliary verbs such as “do” are not necessary and add nothing to the method except extra typing. According to the documentation, “never use adverbs or adjectives before the verb.”
  • If the method returns an attribute, the method should have the same name as the attribute, without any other modifiers, such as “calculate” or “get”. This is the naming convention that getters for properties follow.
  • Name all arguments, and make the name describe the argument. See the remove: example above.
  • Only use “and” to link two parts of a method that do different thing. For example, do not write getValue:andData:, but a method name like getValue:andDelete: is correct because it is doing two things—reading in a value and deleting (potentially) something else.
  • Verbs should not be made into adjectives. performsCalculation is preferred to calculationPerformed
  • Delegate & Data Source Methods

  • The first argument should be the object that is making the delegate or data source call. In certain cases, a class such as a view controller may be managing more than one object, such as a table view. In that case, the view controller can check to see which table view is calling the method.
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        if (tableView == tableView1)
            // return 1;
        else if (tableView == tableView2)
            // return 2;
        else
            // return something else
    }

    You’re comparing instances here, so you can use the == operator. They’ll both point to the same thing, because you’re just passing pointers around—in memory, there is only one instance of tableView1 and tableView2.

  • Delegate methods often use “did” and “will” to notify the delegate that something is about to happen, or has happened. This allows the delegate to prepare or setup some data, or to clean up after an operation. The terms provide a sense of time.
  • Methods that ask a delegate for permission, such as shouldDeleteObjectAtIndex:, should use the term “should”.
  • Miscellaneous

  • Use enumerated types, often with a typedef, to declare constants, rather than plain integers. This gives a name to the numbers, and makes it much more meaningful later. UITableViewCellStyleDefault is a lot more meaningful than simply 0.
  • Preprocessor constants are usually in all-caps, with an underscore separating the words, LIKE_THIS. Preprocessor macros maybe be named either like this, or as a standard method name; the former is preferred. Preprocessor macros defined by the compiler have leading and trailing double underscores, such as __LINE__.
  • Exceptions are named as Prefix+UniqueName+Exception, such as NSIllegalSelectorException or NSRangeException.
  • A much more in-depth look at naming conventions, along with more examples and more rules is available from Apple’s developer documentation:

    Coding Guidelines for Cocoa.

Design Patterns: Model-View-Controller


As programs get larger, there is a greater need for a paradigm to keep everything in order. At the simplest level, any program is a means to store data and present it in a meaningful way. With only a few views and a good data store, this might be rather easy in a simple app for iPhone. But with Pages-caliber apps, especially on the iPad, a formal solution is needed. Cocoa adopts the Model-View-Controller paradigm (MVC) to better organize projects.

What is MVC?

MVC Overview

MVC Overview

Under the MVC system, your classes are one of three types—a model, a view, or a controller. Models store data in an organized form. For a simple app, the model could just be the actual data store, either in-memory (maybe as an NSArray or NSDictionary), or to-and-from disk. In a more complex app, you may choose to use a SQLite database or Core Data, and your model would be a simple instance or one piece of data. More importantly to MVC though, your model must not describe how to store the data—it must not contain any information about padding in the UI, for example, or the position (frame) of any item. Models are usually specific to your application, so they usually are not reusable, unless you have a “template” method to store data.

Views are what you actually see on-screen. They have functions to draw to screen or to other contexts. The view should not store the data it is displaying though—a label should not keep its text around; a table view should not store a copy of its data. Instead, along with MVC there are the patterns of delegation and the language features of KVC and KVO. Many of the classes from UIKit, including UILabel, UITableView, UITextView, and indeed UIView are views. Obviously, views, because they just display (any) data, can be very easily reused. Conversely, views of should not be bound to specific data. Some views may be suited to certain types of data—table views are more suited to text; the iPhone’s home screen is more suited for icons and short text—but you should not impose other restrictions, such as a maximum text length or that the text should only be of one case (that’s so 1980s…).

The view and the model should never interact. This preserves reusability. If UITableView had an outlet to your MainDataModel, it could it only be used with MainDataModel. If you had a model class called Person, it wouldn’t work with UITableView (and the Address Book app would never exist). The controller serves as a median. As shown in the image above, the controller controls interaction. If the model changes, the controller is notified and the view is changed accordingly (for example, you could call [tableView reloadData]). If user interaction changes the model (for example, deleting a row from a table view), the controller is also notified, and from there the change gets propagated to the data store. Therefore, the view can just tell the controller that some data at this location got deleted; the view does not have to worry about what to do or how to handle the deletion so it actually gets deleted. This goes back to the concept of abstraction, one of the fundamentals of object-oriented programming. Similarly, the model does not have to be concerned with exactly how the data got deleted, and just delete the data. In this way, the classes are kept clean and perform one function—the point of a class in the first place. Because the controller is the median and has to deal with specific views and data models, it is typically the least reusable. UIViewController implements so little functionality (from a functionality perspective—it actually does a lot behind the scenes) because controllers are very specific to each application. Most of your app logic goes into the controller.

Another compelling reason to use a controller is to make decisions. Obvious, but there are situations where changes to the model or view should not or need not propagate to the other. Without a controller, a change in the data at row 586 would affect the view even if the view was only showing rows 5–10, an unnecessary operation (which may even cause the UI to slow down for a moment). Other times, data should not be deleted, or deleted at a later time—if a file is being written to from another thread, a delete command from the UI should not be executed immediately. The write should be stopped or allowed to finish before the delete occurs.

Mediation

Hand-in-hand with MVC comes the concept of delegation (and data sources). Data sources are obvious—protocols such as UITableViewDataSource make it so a table view can get data from an id type, making the table view very reusable. The controller implements the delegate, and asks its data model for data as necessary (or as the data source methods are called). More interestingly though, the controller can return data that does not correspond to the data model; in fact, the controller could calculate values and not have a data model at all. The table view does not have to know about this though, and does not need to do any extra handling in these cases.

The data source protocol “pushes” data to the view; the delegate goes in the other direction and informs the controller of changes to the view. There is a naming convention involved, which will be the topic of a future post. Again, the controller can notify the model, or not, depending on the situation.

KVC and KVO are not really used in simple applications. However, with multiple controllers that need to interact with each other, KVC and KVO can be used to great benefit. KVO, which stands for Key-Value Observing, registers a class for notifications when a key-value is changed in any other class. This is a more advanced topic, and will form the basis of another post. It is an effective way to allow multiple controllers to communicate without resorting to a tangle of protocols.

Resources

WWDC 2010 had a great lecture on MVC and the “10 Best MVC Tips Ever.” It is highly recommended. Note that you will need to be a registered developer, including free developers.
Video Link | iTunes Link | Slides (9.7MB)

Handy Little Tool for Errors


During the development of any application, there will be times when you have to track errors in your code. Having the errors be clearly expressed in the Console or in an alert will help with the debugging. As an example, rather than letting your application crash with an exception, it might make sense to log a clear error and defer the fix to a later time.

Because of this, I’ve made a simple little macro that formats the error in a nate way. This is the macro:

#define LOCATION_AS_NSSTRING [NSString stringWithFormat:@"Function: %s\nLine: %d\nFile: %s", __func__, __LINE__, __FILE__]
#define STRING_REPRESENTATION_OF_ERROR(x) [NSString stringWithFormat:@"\n==== ERROR ====\nError %d: %@\nSeverity: %@\n%@", x, x ## _STRING, x ## _SEVERITY, LOCATION_AS_NSSTRING]

It is actually two macros; the former is a “helper” macro and you interact with the latter. The macro works with three other preprocessor declarations. It’ll make the most sense to put this in context:

/******* Severity Levels ******/
#define SEVERITY_NO_ACTION @"No action required"
#define SEVERITY_LOW @"Low"	// Minimal user action to fix OR cannot fix, but doesn't severly affect usability
#define SEVERITY_HIGH @"High"	// Extensive user action to fix OR cannot fix, and affects usability somewhat
#define SEVERITY_CRITICAL @"Critical"	// Crashers; cannot recover from issue
#define SEVERITY_UNKNOWN @"Unknown"	// Not enough information to decide

#define ERROR_CODE_1 1	// No sections defined for library
#define ERROR_CODE_1_STRING @"No sections defined for library browser. Returning 1"
#define ERROR_CODE_1_SEVERITY SEVERITY_NO_ACTION

// … Some code later …
NSLog(@"%@", STRING_REPRESENTATION_OF_ERROR(ERROR_CODE_1));

This code example will output the following:

==== ERROR ====
Error 1: No sections defined for library browser. Returning 1
Severity: No action required
Function: <ContainingMethod>
Line: <SomeLineNumberOfCalling>
File: <ContainingFile>

So how does this work? It’s actually rather simple. You pass in the error code listing, and the preprocessor “assigns” this value to the “variable” x. Then it uses that variable in the standard NSString method call. It first “plugs in” the value of x, then combines the full token (remember that you pass in the entire token, ERROR_CODE_1, so that gets combined and forms ERROR_CODE_1 ## _STRING, which gets joined into ERROR_CODE_1_STRING). It then does the same thing with _SEVERITY token, resulting in ERROR_CODE_1_SEVERITY. Finally, it plugs in the results from the other macro, LOCATION_AS_NSSTRING, which in turn calls three built-in macros (__func__, __LINE__, and __FILE__), which return the calling function, line, and file is C-style strings.

So really, it’s quite simple. There are just a lot of macros involved, and it really becomes quite useful. As an example, you could use this to show a meaningful error to users with an alert, if necessary.

Floating in Uncertainty


Among the primitive data types that Objective-C offers are float and double. Similar to long, double is simply double the storage in bits of float. However, as the name suggests, both are floating-point numbers. That is, the decimal point literally “floats” around as necessary. This can lead to many subtle bugs, even between executions of the same program.

How Do They Work?

Both types have a certain numbers of bits for storage. The exact number of bits varies per implementation, just as the exact storage sizes for ints and doubles aren’t fixed. However, a floating point number effectively has two parts, the “whole” part and the “fractional” part. The floating nature comes in because the number of bits used to store each section is not always the same, and will vary depending on the sizes of the numbers involved.

The Precise Issue

Although there are an infinite number of integers, they all differ by the same amount—1. Therefore it is relatively easy to represent an integer value as bits. By contrast, however, the difference between one decimal number and another is incredibly small, and, what’s worse, this difference can change. When trying to squeeze an infinite number of digits with infinite precision into a finite number of bits, something has to give. This usually means that the floating-point value is rounded, and is not completely accurate. Here’s a simple program (using plain C) to illustrate this issue:

int main (int argc, const char *argv[]) {
	float f = 1234.123456789;
	printf("%f\n", f);
	printf("%.9f\n", f);
	return 0;
}

Output:

1234.123413
1234.123413086

The first print statement (printf() is nearly identical to NSLog(), except that it takes C-style strings instead) shows the actual value of f in memory, with ten digits in this case. Notice that the value is different from the value we assigned to the variable. This is because there are not enough bits to hold every single digit, so some of it had to be rounded away. That rounding is not perfectly accurate—it rounds the tailing ‘456789’ into ‘413’. If, however, we try to force it to display nine digits as seen in the next line, we still end up with the ‘413’, along with a tailing ‘086’—not digits that we put in.

Comparisons

How many times should this loop run?

#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]){
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	int count = 0;
	for (float i = 10; i != 0; i -= 0.1) {
		count++;
		printf("count is %d\n", count);
	}
	[pool drain];
    return 0;
}

Common sense tells us that it should run 100 times, but in fact this is an infinite loop. Because of these rounding errors, i will never be exactly equal to zero. It’ll come close after 100 cycles through, but it won’t be perfect. As such, when dealing with floating point numbers, you want to check to see if it’s close to a value. In the above example, the comparison should be i >= 0; (the equal bit because the floating point number might be a tiny negative value) to ensure that the loop ends.

To check if two floating point numbers are equal, you could use the == (double equals) operator, but there’s no guarantee that they will give an accurate result, especially after many calculations. A better way (albeit less efficient) would be to get the absolute value of their difference, and see if it’s less than a small number, such as 0.00001. If it’s less, you can safely assume they’re equal; otherwise, they’re not.

Floating point inaccuracies can be very difficult to debug, so it pays off to take precautions earlier. As a matter of fact, I spent about half an hour trying to figure out why something wasn’t showing up on screen, when in fact a botched conversion from integers to floating point (similar issues result) lead to everything being 0. Not fun.

Mutable vs. Immutable Strings


As promised, some more interesting topics are on the way. Today, I stumbled across an interesting question over at StackOverflow:

Usage of NSString and NSMutableString objects in Objective C

The primary point of confusion is the exact role of NSMutableString, and how it differs from NSString. It’s a topic well worth looking into, so let’s dive right in.

Inheritance

Conveniently, NSMutableString is a subclass of NSString, which makes things a lot easier. In Java for example, the String class is barely related to the StringBuilder class (functionally similar to NSMutableString), which means that there could be constant conversions between the two classes, which is neither efficient nor convenient to code. Inheritance negates this issue.

Many methods in the Foundation and UIKit frameworks take or return NSStrings. If you had a mutable string that you meticulously constructed, you would not have to convert it to an NSString—you could just pass it right in, and reuse it as necessary. You don’t even have to cast it to an NSString. Not only is this convenient to code, it’s also more efficient. You don’t have to copy the mutable string and turn it into a regular string, which is certainly not all the efficient (relatively speaking, it could take thousands of nanoseconds, rather than the tens of nanoseconds it would take to pass a pointer). Speaking of memory, why are two separate classes needed anyway?

In-Memory

Okay, so that segue might not have made much sense. But it actually all has to do with how the strings are represented in memory. An NSString is a static block of memory that has been allocated wherever there was free space at the time. As such, you can’t shrink it, and definitely can’t add to it—shrinking it would just leave a block of garbage memory that would probably be too small to be used, and adding to it would mean taking up more memory—it could very well encroach into a block of memory that was being used elsewhere, and that would lead to very weird results. This inflexibility has an advantage though—there is only one static block of memory, and so it is very efficient. NSMutableString has a different implementation—the details of which are not public—which most likely involves multiple linked “blocks” of RAM. This linkage allows flexibility, but comes at a price of efficiency. It takes time to look up the next block and go to it (again, it’s all relatively speaking, but in the time that it take to look up the next block of memory, the system could conceptually have loaded two or even four characters, depending on if memory addresses were 32-bit or 64-bit. Each character is 16-bit). As a comparison, Java allows you to concatenate strings by using the + operator. How does it do this? By copying the old string into a new block of memory, then putting the new bit to the end of the new, bigger block. Not very efficient.

So,

When Should You Use Mutable?

A mutable string should be used when you are physically changing the value of the existing string, without completely discarding the old value. Examples might include adding a character to the beginning or the end, or changing a character in the middle. With a mutable string, you can do this “in place”—you’ll just modify the existing string. By contrast, an immutable string, once its value is set, cannot change that value. NSString has methods such as stringByAppendingString:, which does add a string to an existing one—but it returns a new string. Behind the scenes, NSString has copied your old string to a new (larger) memory location, added the argument, and returned the new string. That copying is a lot less efficient (relatively speaking, or if you have to do it a lot).

Of course, there’s nothing stopping you from physically assigning one string to another. Old values will be overwritten. Most NSStrings, including the @”String Constants”, are autoreleased. If you are creating a new string and you decide to alloc/init, you can then assign it to another value without consequence:

myString = anotherString;
myString = myTextField.text;

You can do this with both mutable and immutable strings. The main takeaway is that you should only use mutable when your changing the string itself. But you can change the variable with both mutable and immutable strings without compiler or runtime issues (short of memory management, but most of it is autoreleased anyway).

Extension 15: Foreach Loop


Enumerating through the contents of a collection class is a very common activity. Collection classes in the Foundation framework include NSSet and NSArray. Enumerating is simply the act of going through the collection and getting every value inside—you might do this, for example, if you were doing the same thing to each one, like disabling the buttons in an NSArray of UIButtons. Normally, this would involve a for() loop, like this:

NSArray *array = // Some array
for (int i = 0; i < [array count]; i++)
    [(UIButton *)[array objectAtIndex:i] setEnabled:NO];

This kind of syntax is so common that there is a shorthand way of doing it (known officially in Objective-C as fast enumeration:

NSArray *array = // Some array
for (UIButton *button in array)
    button.enabled = NO;

The key is what goes inside the for() loop. You declare a variable of any type (to avoid a runtime crash, declare to be the type of variable in the array, such as the UIButton shown here, or if is more than one type, you could use id). Then you put the keyword in, followed by the name of the collection. Basically at this point, the new variable you created will be assigned to the “next” value in the collection at every iteration of the loop. In the body of the loop, you can do whatever you want to the variable. Note though that if you need to access the index of the object, you’ll have to go back to the original style.

An Update


So, it’s been a few weeks since I’ve have time to post here. Unfortunately this busy-ness will last for a few more days, so there won’t be any new content until then. But more importantly, the content on this site—at this point, the Objective-C portion is mostly completed. Over the next few weeks, then, I’ll be wrapping up the Objective-C portion, and move into more fun stuff. I’ve noticed a surprising lack of Xcode 4 information; seeing how it has been released for several months now, lots of people must be using it. So that’ll be really useful, and I’m itching to dive right in.

Thanks to everyone for stopping by, and I hope this site has been helpful. Over the next few weeks, I hope to add much more content, and make this little slice of the Internet even more useful. 🙂

  • Welcome

    My goal is to make CupsOfCocoa into a beautiful source for beginners to the iPhone platform to get started. Subscribe below for more, and stay tuned!

  • Contact Me

    If you need to contact me for any reason, feel free to send me an email.
  • The Giving Spirit

    If you've found this site helpful, would you consider donating a little sum? Any amount is appreciated...Thanks so much!

  • Roadmap

  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 220 other followers

  • Back to the Past

    May 2020
    S M T W T F S
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  
  • Time Machine

  • You count!

    • 622,650 views
  • Worldwide Stats

    free counters
%d bloggers like this: