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.

Data Encapsulation


A central tenet of object-oriented programming is that the objects act as “black boxes”—that is, they hide, or encapsulate, their contents. When you call a method, you don’t care how the object does what you are asking it to do; you simply expect that the object will get the task done. The same concept applies to instance variables. The use of properties, and the accessor methods in particular, help to hide the instance variables themselves. You are indirectly accessing them; you get to control their access (such as making them readonly). By using methods, you also don’t have to worry about how the instance variables themselves are set up; you simply access the methods that are provided. An additional benefit of data encapsulation is that the creator of the class can change the internal workings (change the way the instance variables are set up, or the way a method operates) without breaking code that relies on the class. It’s like a car—most people don’t care how the car works, whether it burns gas or runs on gerbil power, as long as it gets them to the grocery store and back.

 

To be honest, it’s a difficult concept to explain; perhaps this page over at Stack Overflow (great site, BTW) does a better job.

Objects (Part 2): Properties


Every object is made up of instance variables (iVars) and methods. Our Fraction class, which we really began to build in the last post, contains two iVars, both NSIntegers, called numerator and denominator. Fraction also has two methods, setNumerator: and setDenominator:. These methods will set a value to the corresponding instance variable. In most cases, you would also have a method, with the same name as the instance variable (yes, this is permitted, and in this case, encouraged), which would return the value of the instance variable. These setter and getter methods are referred to as mutator and accessor methods, respectively. These methods are a major concept of object-oriented programming—data encapsulation, the notion that objects hide their instance variables.

At this moment, our Fraction class defines and implements the setter methods (note that we simply have not needed the getter methods so far). However, this would be difficult to do when we start working with large classes, which have many instance variables. This is also not very scalable; the same code to retrieve values for a small block of data stored on an iPhone should probably not be the same code used to retrieve a long string of data from a powerful desktop Mac or even from the internet. Fortunately, there is a very convenient concept that Objective-C provides, and this construct should be used wherever possible.

Properties

Properties replace the accessor methods for an object. Quite simply, our Fraction class’s interface now looks like this:

#import 
@interface Fraction : NSObject { 
	NSInteger numerator; 
	NSInteger denominator; 
}
@property NSInteger numerator; 
@property NSInteger denominator;
- (void)setNumerator:(NSInteger)value; 
- (void)setDenominator:(NSInteger)value;
- (void)display; 
@end

The general form of the property statement is

@property type name

Note that the setter (and if we had them, the getter) methods are no longer needed. We will have the compiler synthesize these methods for us, but placing this line in our implementation, right after the @implementation line:

#import "Fraction.h" @implementation Fraction
@synthesize numerator, denominator 
- (void)setNumerator:(NSInteger)value { 
    numerator = value; 
} 
- (void)setDenominator:(NSInteger)value {
    denominator = value; 
} 
- (void)display { 
    NSString *numeratorString = [[NSString alloc] initWithFormat:@"%d", self.numerator]; 
    NSString *denominatorString = [[NSString alloc] initWithFormat:@"%d", self.denominator]; 
    NSLog(@"%@/%@", numeratorString, denominatorString); 
    [denominatorString release]; 
    [numeratorString release]; 
}
@end 

Of course, the identifiers after the @synthesize have to match the names you declared as properties in the interface. However, the identifiers that you declared after @property do not have the match the instance variables; instance variables will be created at compile time if this happens.

You do not have to change your method calls in your main() routine; the methods still exist. However, there is an easier (and sometimes controversial) way to access these synthesized properties.

The Dot Operator

As previously mentioned, a getter method returns the value of an iVar; a setter sets a value to the iVar.

[myFraction setNumerator: 2] // Set numerator to 2 NSInteger 
numeratorValue = [myFraction numerator]; // returns the value of the numerator, and set to the new variable called numeratorValue

The dot operator, introduced in Objective-C 2.0 (yes, there was a 1.0, but that was a long time ago), allows you to invoke the getter method by writing

iVar.property

and the setter by

iVar.property = value

Therefore, the above example can be re-written as

myFraction.numerator = 2; // Set numerator to 2 
NSInteger numeratorValue = myFraction.numerator; // set value of numerator to numeratorValue 

C programmers might recognize this syntax as being used to access members of a struct—because that is exactly what you are doing. Behind the scenes, an object’s instance variables are stored as a struct. And if you have no idea what this line means, don’t worry—structs are a basic C data type that we may cover in a later lesson.

Property Attributes

In a property declaration, you can specify any number of (non-contradictory) attributes:

@property (attribute1, attribute2, etc.) type name;

A list of possible attributes follows (adapted from Apple’s developer documentation, The Objective-C Programming Language: Declared Properties)

Accessor Method Names

The default names for the getter and setter methods associated with a property are propertyName and setPropertyName: respectively—for example, given a property “foo”, the accessors would be foo and setFoo:. The following attributes allow you to specify custom names instead. They are both optional and may appear with any other attribute (except for readonly in the case of setter=).

  • getter=getterName: Specifies the name of a different (custom) getter method for the property. The method must return a value matching the iVar’s type, and it takes no arguments.
  • setter=setterName: Specifies the name of a different (custom) setter method for the property. The method must return void, and it takes one argument of the same type as the iVar.If you specify that a property is readonly then also specify a setter with setter=, you will get a compiler warning.

Writability

These attributes specify whether or not a property has an associated set accessor. They are mutually exclusive.

  • readwrite: This is the default; this indicates that the property will have read and write capabilities. When synthesized, both the getter and setter will be generated.
  • readonly This indicates that the property can only be read; no data can be assigned to it (through the property). When synthesized, only a getter will be generated; when you try to assign the property a value using dot syntax, a compiler error will be generated.

Setter Semantics

These attributes specify the semantics of the setter. They are mutually exclusive.

  • assign: This is the default; it tells the setter to directly assign the value. This is typically delineated with primitive data types (ints, floats, etc.)
  • retain: Specifies that a retain should be called on the object upon assignment; the previous value is released. This is only valid for objects. This has to do with memory management, a topic that will be fully explored in a later lesson.
  • copy: Specifies that the argument passed in should be copied, and the copy will be assigned. The previous value is released. This is only valid for objects. It is used in the case where the original property (perhaps stored on a shared server across the network) should not be modified by any other code, but when other code requests the value, for potential modification.

Atomicity

Atomicity means that the value is written to a temporary location in memory first, and then written to the intended location. This ensures that there is always a valid copy of the data somewhere. If an assignment was not atomic, and something happened during the writing period, the data could become fatally corrupt—the user would lose data. By writing data atomically, the data will either be the original, or the new value—never in a partially written state.

  • nonatomic: Specifies that the object should not be assigned atomically. By default, accessors are atomic (this is more beneficial in a multi-threaded environment, where multiple threads may be reading/writing value to a piece of memory.

CS193P Material

Properties are a very powerful notion, and used throughout the language. If this explanation was not clear enough, please see Lecture 3 of CS193P. The relevant content begins around the 16 minute mark, and ends with a demo around the 45 minute mark. Of course, feel free to view the whole lecture.

The slides for the lecture are available on the CS193P website; for a direct link, click here.

The code for the Fraction class at this moment can be downloaded by clicking here.

Supplement: CS193P


Stanford University has offered the CS193P class for a few quarters now. It has become the ubiquitous source of beginning iPhone programming material for many people. The lectures are filmed and uploaded to iTunes U, and they are now available in 720p HD video. However, the lectures, which are the only option for non-enrolled students, are rather impersonal, and sometimes move too quickly (in my opinion). I have learned a lot from them, but I don’t think they’re the only source. In fact, I find that they are more helpful once I got the basics down. Nevertheless, there are real gems, and so I will be occasionally referring links as supplementary material.

To access the lectures:

  1. Launch iTunes and head into the iTunes Store (don’t worry, all the lectures are free).
  2. Click on iTunes U on the black bar near the top of the storefront.
  3. At the time of this writing, the lectures were under Staff Favorites. Click on the link, and you’ll be led to the main listing.

    CS193P Fall 2010 Lectures Listing

    iTunes Listing

Direct link (will open iTunes, if it is not already running):
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=395605774

The lectures are available for streaming; alternatively, you can download them just like regular songs from iTunes. Note that file sizes are around 500MBs for the SD version and around 700MBs for the (linked) HD version.

The slides can be downloaded from the main website, listed above, as well as the sample code.

Objects (Part 1): Splitting Classes Into Multiple Files


This is the first in a multi-part series that will talk about the fundamentals of objects. If you’re still keeping track, I suppose these would all fall under Lesson 6: Objects.

In Lesson 3, we began a simple overview to object-oriented programming. Now, we’ve covered the major portions of the basic language—what is “plain C.” There are other topics, such as structs, arrays, and a slew of other rather obscure topics. Some of these are enclosed or remade in the code the Apple provides for free; others will be discussed as necessary. For now, we will start venturing into the exciting world of objects—and they really are exciting.

As part of our calculator, we will allow the calculator to operate on regular values, as well as fractions. For the sake of demonstration, we will begin by creating Fraction objects.

Creating the Test Code

Create a new Xcode project. In the New Project window, choose “Application” under Mac OS X from the left side, then choose “Command Line Tool” from the top right, and make sure the “Type” is set to Foundation. Click Choose, and save it as “FractionDemo” anywhere you choose. In the File List, load FractionDemo.m, and enter the following code:

#import "Fraction.h"
#import 

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    Fraction *myFraction = [[Fraction alloc] init];

	// Set myFraction to value of 2/5
	[myFraction setNumerator: 2];
	[myFraction setDenominator: 5];

	// Display the value of myFraction
	NSLog(@"myFraction has a value of: ");
	[myFraction display];

	[myFraction release];
    [pool drain];
    return 0;
}

Here, you can see that in our main code body, we create an object of type Fraction, and call it myFraction. Ignore the asterisk (* for now; it is a sign that you are actually creating a pointer…that’s an advanced topic that will be further explored later). You set myFraction to the value returned from the standard alloc/init method call.

Next, we call the methods setNumerator: and setDenominator: and pass both integer values; these methods will set the appropriate values of the Fraction object we’ve created. We then send another message call for myFraction to display itself (or so we assume, based on the method name—make sure to write descriptive method names). Then we release our object—don’t worry about the memory management for now.

Now, we will create the actual Fraction object itself.

Creating the Fraction Class

In Xcode, Go to File > New File (⌘N). From the left, choose Cocoa Class under Mac OS X, select Objective-C class from the top left, and make it a Subclass of NSObject. Click Next, and set the following parameters:

  1. Set the File Name to be “Fraction.m”. Note that the “.m” part is automatically added; just type “Fraction”, without the quotes, making sure that the “F” is capitalized. By convention, class names are capitalized.
  2. Make sure that ‘Also create “Fraction.h”‘ is selected.
  3. Leave the default settings for the other fields. Add to Project should display “FractionDemo,” the name of your project, and in your Targets window, the checkbox to the left of the “FractionDemo” entry should be selected.

Click “Finish”. In your File List, you will see two new files: “Fraction.h” and “Fraction.m.” Select Fraction.h, and enter the following code:

#import <Foundation/Foundation.h>

@interface Fraction : NSObject {
	NSInteger numerator;
	NSInteger denominator;
}
- (void)setNumerator:(NSInteger)value;
- (void)setDenominator:(NSInteger)value;
- (void)display;

@end

Here we define two instance variables, called “numerator” and “denominator”. They are defined as type NSInteger; this is identical to the standard int type; there’s really no difference. My personal preference is NSInteger.

Next, we define the methods that we call in the main() method. There should not be anything new here, if you’ve read through Lesson 3.

In Fraction.m, enter the following code:

#import "Fraction.h"

@implementation Fraction
- (void)setNumerator:(NSInteger)value {
	numerator = value;
}

- (void)setDenominator:(NSInteger)value {
	denominator = value;
}

- (void)display {
	NSString *numeratorString = [[NSString alloc] initWithFormat:@"%d", numerator];
	NSString *denominatorString = [[NSString alloc] initWithFormat:@"%d", denominator];
	NSLog(@"%@/%@", numeratorString, denominatorString);
	[denominatorString release];
	[numeratorString release];
}

@end

Chewing through this code, the first two methods should not present anything new. The last method does warrant some discussion, however.

If you refer back to Lesson 3, you’ll notice that we defined the display method (we called it showResults there) as

- (void)showResults {
	NSLog(@"This is a fraction with a value of %d/%d", numerator, denominator);
}

Our display method shows a different way to do this. First, we highlight NSString’s initWithFormat: method, which works like NSLog() does, except that instead of outputting, it is saved as a string. In the actual NSLog(), we use the %@ format specifier, which takes an NSString as an argument. Finally, we have to release the NSStrings that we’ve created…again, don’t worry about the memory management at the moment.

If we Build and Run now, we get the following output:

myFraction has a value of:
2/5

This is exactly what we’re looking for.

You’ll notice that we haven’t really done anything new since Lesson 3. In fact, that is true, except that we have created a Fraction class in separate files. Looking back over the code entries, the bold lines show where the dependencies lie—in a class’s .m file, it #imports the correspond .h (known as the ‘header’) file. In any file that uses the class you’ve created, you also need to import the header. Here, you’ve made it easier to maintain a larger project; as we add more classes, you won’t be working with one gigantic file.

Extension 5: The switch Statement


The switch() statement is used in place of a chain of if()else if()else if()else if()else construct, where such a chain does not lead to very readable, follow-able code. The switch() statement is designed for this situation. Here is the general format:

switch(expression or variable)
{
     case value1:
          // Program statement
          // Program statement
          ...
          break;
     case value2:
          // Program statement
          // Program statement
          ...
          break;
     case value3:
          // Program statement
          // Program statement
          ...
          break;
     ...
     case valueN:
          // Program statement
          // Program statement
          ...
          break;
     default:
          // Program statement
          // Program statement
          ...
          break;
}

The expression value in the parentheses at the beginning of the statement is compared to each of the values, and when one of them matches, the following code (note the colon, and the lack of braces around each case), the code below is executed. It then breaks out of the rest of the switch, to avoid executing the rest of it (“overflowing” into the code for the next condition). This can sometimes be used intentionally, but for most of the time make sure to use the break; statement.

If none of the conditions match (the else of an if()else block), the code under the default condition is executed.

The following is an example of a switch() statement and the equivalent if()else block:

// This is an example of a switch statement.
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSString *operator = [[NSString alloc] init];     // We will talk in depth about NSString later on down the road.
	// Assume operator has been initialized to a valid value
	// Valid values for operator are @"+", @"-", @"*", and @"/"

	switch (operator) {
		case @"+":
			NSLog(@"Operator is for addition.");
			break;
		case @"-":
			NSLog(@"Operator is for subtraction.");
			break;
		case @"*":
			NSLog(@"Operator is for multiplication.");
			break;
		case @"/":
			NSLog(@"Operator is for division.");
			break;
		default:
			NSLog(@"Unknown operator.");
			break;
	}

    [pool drain];
    return 0;
}

This code should be rather self-explanatory; operator is compared to the values after each case, and if one of them matches, the executes the corresponding NSLog and breaks out of the switch. If none of them match, then it hits the default statement.

The equivalent if()else block follows:

// This is an example of a switch statement.
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSString *operator = [[NSString alloc] init];
	// Assume operator has been initialized to a valid value
	// Valid values for operator are @"+", @"-", @"*", and @"/"

	/* Note that NSString actually has a comparison method, and that
	   this method of comparison is not guaranteed to work. We are
	   overlooking that at the moment for the sake of education. */
	if (operator == @"+")
		NSLog(@"Operator is for addition.");
	else if (operator == @"-")
		NSLog(@"Operator is for subtraction.");
	else if (operator == @"*")
		NSLog(@"Operator is for multiplication.");
	else if (operator == @"/")
		NSLog(@"Operator is for division.");
	else
		NSLog(@"Unknown operator.");    [pool drain];
    return 0;
}

This code does the same thing as the switch statement above (bar the comment in bold).

The switch() statement is makes more logical sense, but some people find it annoying. It all comes down to a matter of personal preference. No big deal.

BTW less than a month after the previous milestone we are at 2000 views! Thanks to everyone who stopped by, and I hope to see you back!

Postscript: Wikipedia has a nice article on controlling program flow. It is a bit dense, but for anyone who is interested, go check it out! And while you’re there, you might as well see the article on the switch statement as well.

Extension 4: What goes Inside the if() Statement


The if() statement tests for a boolean (true or false) condition, and executes the following code accordingly. The condition that falls within the parentheses is the boolean condition that determines which code path your program will take. But what exactly can go inside the inside the parentheses? As it turns out, any operator-based expression can be used:

  • The double-equals (==): The double-equals is used for comparison (x==5 is logically the same as “x is equal in value to 5”, while the single equals, x=5, assigns the value of 5 to the variable x). This can be used to test for the result of an expression:
    if(x % 2 == 0)     // If x is even
        NSLog(@"x is even.");
    else
        NSLog(@"x is odd.");
    

    Make sure that you use the double equals for a comparison; a single equals is only used for assignment, and unless you are assigning zero to a variable, the expression will always be true (because any non-zero expression is considered true).

  • The not equal to (!=): The not equal to operator is the exact opposite of the double-equals; if the left part is not equal to the right, then execute the following code.
    if (x != 5)
         NSLog(@"x does not equal 5.");
    
  • The Greater-than, Less-than (<, >, <=, >=): These operators work just like they do in real life. They are the less than, greater than, less than or equal to, and greater than or equal to operators, which have not changed since high-school algebra.
    if (x > 5)
         NSLog(@"x is greater than 5.");
    else if (x < 5)
         NSLog(@"x is less than 5.");
    else
         NSLog(@"x is equal to 5.");
    
  • Boolean Operators (&&, ||, !): Three symbols (or pairs of symbols) can also be used to express a boolean condition. These are the and (&&), the or (||), and the not (!). These are just as logical as the if() statement itself:
    if ((x >= 5) && (y < 10))
     	NSLog(@"x is greater than or equal to 5, AND y is less than 10.");
     if (x == 3 || y == 6)
     	NSLog(@"x is equal to 3 OR y is equal to 6");
     if (!(x > 2 && y < 5))
    	NSLog(@"x is NOT greater than 2 AND y is NOT less than 5");
    

    See also this excellent document on Scribd, and of the course the Wikipedia entry for a more technical description of what can be achieved with boolean operators.

When using these expressions in conjunction, don’t hesitate to use parentheses or spaces to make your purpose clear. Although the operator precedence table tells us that the internal parentheses were not needed in the last example, their presence helps clarify the logical intent.

By the way, the Conditional Operator is an oddity (among operators) that could save you a bit of typing:
https://cupsofcocoa.wordpress.com/2010/10/26/oddities-conditional-operator/

Objective-C Lesson 4: if() statements and Booleans


As mentioned before, boolean values are simply true-or-false. In Objective-C, unlike many other languages, they are represented as YES or NO:

BOOL trueOrFalse = YES;
BOOL gameOver = NO;

Internally, however, they are stored as zero and one.

if() Statements

The if() statement is used to check for conditions. Just like we use if in normal English, if() in code is used to test for a condition—they test for the value of a boolean (or any int—in this case, a zero is considered false; any non-zero value is true).

Here is a simple example of booleans:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	BOOL trueOrFalse = YES;
	if (trueOrFalse)
		NSLog(@"trueOrFalse is true.");
	if (1)
		NSLog(@"1 is considered to be true.");
    [pool drain];
    return 0;
}

The output is:

trueOrFalse is true.
1 is considered to be true.

Simple enough, and quite logical.

Obviously, if the condition was false, the statements following would not be executed. The following example demonstrates:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	BOOL trueOrFalse = YES;
	if (trueOrFalse)
		NSLog(@"trueOrFalse is true.");
	if (1)
		NSLog(@"1 is considered to be true.");	// If false, statement following is not executed
	trueOrFalse = NO;
	if (trueOrFalse)
		NSLog(@"I lied. trueOrFalse is not true.");
	if (0)
		NSLog(@"This line should not appear.");
    [pool drain];
    return 0;
}

Unsurprisingly, the results are the same as above.

One important point to make here: if you only have one statement after the if(), you can just leave it like it is above. But if you have more than one statement after the if(), you must enclose them within braces:

if (trueOrFalse) {
	NSLog(@"trueOrFalse is true.");
	NSLog(@"This second line must be within the braces.");
}

Otherwise, the second (or additional) statements will be executed, regardless of if the condition was true or not.

Extending the if() Statement

In real life though, there are often alternatives: if something is true, do “action1“; else, do “action2“. Objective-C lets you model that quite simply:

trueOrFalse = YES;
if (trueOrFalse == YES)          // The double-equals sign is a comparison; versus a single equals, which is an assignment. More on this in the next Extension.
	NSLog(@"If true, print this");     // This gets printed
else
	NSLog(@"Else, print this");        // This does not get printed
trueOrFalse = NO;
if (trueOrFalse)
	NSLog(@"If true, print this");    // This does not get printed
else
	NSLog(@"Else, print this");       // This gets printed
 

Output is:

If true, print this
Else, print this

This makes logical sense.

You can also extend this by using else if(). This is easier to explain with code:

int value = 5;
	if (value > 0)
		NSLog(@"value is greater than zero.");
	else if (value == 0)
		NSLog(@"value is equal to zero.");
	else
		NSLog(@"value is less than zero.");

Output is:

value is greater than zero.

You can have as many else if()s as you want; they simply follow each other:

int value = 5;
if (value == 6)
	NSLog(@"value is equal to 6.");
else if (value == 0)
	NSLog(@"value is equal to 0.");
else if (value == 2)
	NSLog(@"value is equal to 2.");
else if (value == 10)
	NSLog(@"value is equal to 10.");
else
	NSLog(@"value does not equal 6, 0, 2, or 10");     // This line is the output.

Pitfalls

There are a few issues that may arise with if()statements.

  • Forgetting braces: If you have more than one statement that you want to execute given a certain condition, you must enclose them within curly braces.
  • Using too many instances of if(): If you want to have a collection of related paths (if…else if…else), you must remember to use else if(). Using a chain of if()s is a completely different thing, logically. Think about it.
  • Forgetting the last else: The final else is a “catchall” statement that is executed if none of the previous if() or else if() statements are true. Don’t forget the else; otherwise, you may never get any output. For example, in the last code example, the last else statement was needed; otherwise, it might have appeared that the code was broken.

Conclusion

As you can see, the if() statement is quite simple, but very powerful—it defines “paths” down which your code can travel, based on the value of a condition. In the next Extension, we will be looking at what these conditions can be.

Objective-C Lesson 3: Object-Oriented Programming


When object-oriented programming arrived in the programming world, it was considered a savior of software by some and yet another foolish experiment by others. Regardless of the perspective, we need to define some basic concepts and terminology before we begin

A Thing

An object is a thing. In the real world, you have “things,” all of which have certain properties. For example, you probably have a car—a “thing.” The car has properties, such as paint color, total mileage, make, model, and year. You can also do things with the car, or have something done to it—for example, you can drive twenty miles in the car, or wash the car.

In an object-oriented program, your specific car is an instance of a class, generally called Car. A class is the definition of the object, and in most cases can be thought of as a “factory” for its instances. A class can create many instances of the same type of object, although they have to have different names. An object is simply a variable, but it can be (and usually is) of a custom type.

Instance Variables and Methods

As mentioned before, your car, and any other car, has certain properties that are potentially unique to that specific instance. These properties are known as instance variables, or ivars for short. Instance variables are variables, of either the standard data types, or of any other object, but they are private to the object—that is, every single instance of Car has its own identical set of instance variables; although the variables may be of the same type and number, they can (and usually do) contain different values across different instances.

A method is the proper term for a function, or simply a piece of code that is called upon to perform some action. In Objective-C, there are two types of methods—class methods and instance methods. Class methods are performed directly on the class that an object belongs to—for example, a class methods might ask the car factory how many cars it produced the previous year. Instance methods are performed on specific instances of a class—for example, you might ask one specific car to drive twenty miles, or you might wash one specific car; you wouldn’t do those things to the entire factory. Instance methods affect the state or condition of the object. Just like two identical cars adopt different characteristics over their lifetime, different instances of Car can take on different traits as well.

Message Objects

In Objective-C, there is a specific syntax for calling methods:

[ClassOrInstance method];

The method call begins with an open bracket. This is followed by the name of the class or instance, depending on whether the method belongs to a class or instance. This is followed by a space, and then the name of the method. This is followed by a closing bracket, and the all-important semicolon.
In more formal terminology, the following message call might be described as

[receiver message];

The meaning is the same.

Sample Program

Now, with the theory cleared up, we can move on to our first program involving classes.

Program 3.1

// A simple implementation of a Fraction
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

	int numerator = 2;
	int denominator = 5;
	NSLog(@"This is a fraction with a value of %d/%d", numerator, denominator);

	[pool drain];
	return 0;
}

The output is

This is a fraction with a value of 2/5

In Program 3.1, we defined a numerator and denominator variable, and set them to integer values. We then printed the result of this simple fraction.

This program is short and condensed, and seems to be pretty simple—and it is. But what if we had a hundred fractions that we wanted to store? We’d have to keep track of two hundred variables. And performing operations on those variables would not be any easier.

As a matter of fact, Program 3.1 is not a true object-oriented program. It is still written using C-style code. We have not created any objects in the code; our Fraction object still exists only psychologically.

Program 3.2 presents the exact same functionality, except that we actually define this object in code. We then refer to the object as Fraction throughout the program. Don’t worry if it looks daunting; an explanation follows.

Program 3.2

// A Fraction class
#import <Foundation/Foundation.h>

//———————— Interface ————————

@interface Fraction : NSObject
{
	int numerator;
	int denominator;
}

- (void)showResults;
- (void)setNumerator:(int)n;
- (void)setDenominator:(int)d;

@end

//———————— Implementation ————————

@implementation Fraction

- (void)showResults {
	NSLog(@"This is a fraction with a value of %d/%d", numerator, denominator);
}

- (void)setNumerator:(int)n {
	numerator = n;
}

- (void)setDenominator:(int)d {
	denominator = d;
}

@end

//———————— Main Program ————————

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Create an instance of Fraction
	Fraction *myFraction;

	myFraction = [[Fraction alloc] init];

	// Set myFraction to 2/5
	[myFraction setNumerator:2];
	[myFraction setDenominator:5];

	// Display the value of myFraction
	[myFraction showResults];

	// Clear up memory
	[myFraction release];

    [pool drain];
    return 0;
}

The output is

This is a fraction with a value of 2/5

Code, Demystified

Program 3.2 is divided into three logical sections. These are known as the interface, implementation, and program section, respectively.

The interface section (delineated by @interface in the code) provides basic program-wide definitions, the implementation section (delineated by @implementation) provides the implementation of the methods, and the program section contains the main code that does something.

The @interface Section

Every class in Objective-C has a single parent, or superclass, from which the class inherits. Next, you have to declare the instance variables that belong to the class. Finally, you declare the methods, or actions, that the class can perform. This is all done in the @interface section, which looks like this:

@interface ClassName : ParentClassName
{
	instanceVariableDeclarations;
}
methodDeclarations
@end

Remember that the compiler ignores spaces, so you may put line breaks and spaces anywhere within the code above.
By convention, the name of a class begins with a capital letter, as in the Fraction class.

You can tell that our Fraction class is a subclass of NSObject, which is the root object that almost everything else inherits from, directly or indirectly. NSObject is declared in the Foundation files which you imported.

Fraction contains two instance variables; both are ints. They are called instance variables because every instance of Fraction creates a new set of these variables, unique to that specific instance. So, FractionA’s numerator is a different variable than FractionB’s numerator. Objective-C automatically keeps track of this for you.

Currently, our Fraction class declares (and later implements) three methods. All are instance methods, as noted by the minus sign () preceding each method name. A class method is delineated by a plus sign (+).

Before we discuss the method declaration, we must remember than an object is considered a “black box.” Ideally, objects encapsulate, or hide, their instance variables, from anything except itself. The object exists as a single entity, and anything that works with the object does not need to know, and should not know, about the object’s inner workings. Therefore, we need to declare specific methods to set the variables, because the program should not directly manipulate them. We also need a separate method to print the values, because, once again, the program should not be able to directly access the variables. This is a fundamental concept in Objective-C, and is observed throughout the libraries and code.

The Fraction class defines three methods, all of which return nothing. The value in parentheses before the method name specifies the return type of the method. void is programming parlance for “nothing,” or nil. Any data type or object can be a return value; a method might return a float, int, or another Fraction, as illustrated by the following methods:

- (int)numerator;
- (float)divide;
- (Fraction *)randomFraction;

The asterisk after the Fraction is used to delineate a pointer; this is not an important concept at the moment. For now, simply remember that anytime you create an instance of a custom object, the name of the instance should be prefixed with an asterisk.

All of these methods must return a value somewhere in the method. Just as main returns 0 at the end, these methods must return an int value, a float value, and another instance of Fraction, respectively. The compiler will complain if you do not return a value.

The latter two methods declared in Fraction return no value, but they do each take an integer value as an argument. In the case of setNumerator:, the name of the argument is n. This name is arbitrary, as long as it follows the standard naming conventions, and is used only within the method to refer to the argument. The argument itself exists only within the method; you cannot access n anywhere else in Fraction.

Arguments are values that are passed into a method, which the method would not be able to obtain otherwise. For example, setNumerator: requires a value to set to the numerator, but it would not receive a custom value without an argument.

Note the syntax of these method declarations. The method name begins with the minus or plus, signifying the method type. This is followed by the return type in parentheses, the name of the method, and a colon. This colon is followed by an argument type in parentheses, a name for the argument, and a semicolon. In a method that takes an argument, the colon is considered part of the method name.

A method can take multiple arguments; they are delineated by a space, a new section of the method name, another colon, an argument type, and name. This will be covered in a later chapter.

The @implementation Section

In the implementation section, you define the code that each method implements. The general appearance of the @implementation section is similar to this:

@implementation ClassName
	methodDefinitions;
@end

In the implementation of Fraction, you also declare the method types and names, followed by an open brace. Between the opening and closing brace, you insert the code that the method will execute when it is called.

The program Section

In this program, the main program section contains the all-important main function that is the first thing to be executed.

In Program 3.2, we first create an instance of Fraction:

 Fraction *myFraction;

Again, don’t worry about the asterisk. From a technical perspective, it says that myFraction is a pointer to a Fraction.

Now that you’ve created an object “container” to store a Fraction, you have to actually create a Fraction to fill that space. You do that in the next line,

myFraction = [[Fraction alloc] init];

In this line, you call the alloc method on Fraction; alloc is a class method. Although you never defined the alloc method, it is inherited from NSObject. Inheritance will be discussed in a later lesson.

After you allocate a Fraction, you have to actually initialize it. Therefore, you pass the value of the alloc method to NSObject’s init method, and the resulting Fraction is assigned to myFraction. This nested sequence of messages is used almost every time you create a new object.

Next, you set the values of myFraction to 2 and 5 by using the proper method calls.

[myFraction setNumerator:2];
[myFraction setDenominator:5];

You pass the integers 2 and 5 as arguments to the method. The method then takes these arguments and sets the numerator and denominator variables of myFraction.

You then call myFraction’s showResults method to print the value of the fraction.

We then free up the memory that Fraction uses by calling the release method:

[myFraction release];

This is a critical part of programming for iOS. Whenever you create a new object through alloc/init, you have to release it—in other words, every alloc/init call is balanced by a release call. Otherwise, the now-useless object will still sit in memory, taking up space; in a memory-constrained environment such as the iPhone, you want to use as little memory as you can.

Messaging Receivers

In every message, you send the message to a specific receiver—the object or class which implements the method. However, instance methods are sent to specific instances, so that the same method call to two different Fractions will result in two Fractions with potentially different values. For example,

[fraction1 setNumerator:2];
[fraction1 setDenominator:5];

[fraction2 setNumerator:3];
[fraction2 setDenominator:4];

Will result in two separate fractions, one with a value of 2/5 and another with a value of 3/4. Although you are calling the same methods on both, they are received by different objects, with their own set of numerator and denominator variables.

Data Encapsulation

As mentioned before, you shouldn’t directly access the instance variables of an object. Data encapsulation provides some security against people working with the class, to prevent them from tinkering with the inner workings. So in the main function, how would you access these values?

Generally, you access these values by writing special methods, known as getter methods (the set methods that we’ve already wrote for Fraction are known as setter methods; they are generally written in pairs).

The getter methods for the Fraction class look something like this:

- (int)numerator;
- (int)denominator;

- (int)numerator {
	return numerator;
}
- (int)denominator {
	return denominator;
}

It doesn’t matter if the method name is the same as the variable name; in fact, it is common practice.

Program 3.3 contains the main function that tests these new methods.

Program 3.3

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Create an instance of Fraction
	Fraction *myFraction;

	myFraction = [[Fraction alloc] init];

	// Set myFraction to 2/5
	[myFraction setNumerator:2];
	[myFraction setDenominator:5];

	// Display the value of myFraction
	NSLog (@"The value of myFraction is %d/%d", [myFraction numerator], [myFraction denominator]);

	// Clear up memory
	[myFraction release];    [pool drain];
    return 0;
}

The output is

The value of myFraction is 2/5

Objective-C 2.0 introduces properties, which provide an easy way to create getter and setter methods. This will also be covered in a later lesson.

What You Will Learn About Objective-C


So, having decided on doing a course on Objective-C, I’d like to set down some goals.

  1. As I mentioned before, I will attempt to teach C and Objective-C as one language. Obj-C is a strict superset of plain C, which means that any valid C is also valid Obj-C. The reason for this decision is that C is a procedural language, where you worry about how you do a task, whereas Obj-C is an object-orientated language, where you worry about what you use to do a task. It’s a radical shift in mindset. As a result, although Obj-C builds smoothly off of plain C, not all C styles and procedures work with Obj-C.
  2. I want to engage, not just present the facts. As a result, I will supply plenty of screenshots, and include exercises at the end of each lesson. I will also post the source code to each lesson on this blog—stay tuned for more.
  3. I want to create a solid understanding that frees you from having to go back to a reference every other line of code. That gets annoying, and you won’t get much respect in programming circles. 😛
  4. I want to make it an easy and fluid learning environment. People learn better when they are subject to less stress. In fact, I’m not going to stress you at all—you’ll be your own motivator. You want to build the next great iPhone app—so put in the effort!

In this course, I hope to build up a small code library, and have each lesson build up off the previous. I still need to plan out the order of the lessons and their content…stay tuned!

  • 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: