Prehistory
Inspired by the fact that in recent times I have stocked i devices, I decided to learn how to program for them. Of course, in my chosen way of a web developer, this will not help much, but I have always been interested in new languages.
The first thing that fell my gaze is the iTunesU virtual school. Here I found the lectures of the CS 193P course conducted by the developers of the epl for students of Stanford University. Lectures cover the basic features of the language and native frameworks quite well, however, there are one BUT lectures in English and there is no translation to them. For me personally, it didn’t cause any problems, because Aple apparently chooses only candidates with a good speech for these lectures, and the 8 months in the US gave me the opportunity to watch original lectures and learn from "native speakers" (just kidding) .
Since every year a new version of Xcode comes out, and Stanford's lectures in which the current version is being considered are becoming available late in the semester, I decided to write a series of articles that will cover the practical part (!) Of this course. Since I listened to lectures from the fall of 2010, it would be practical for me to write a program in xcode 4.2 which was originally developed for the 3rd version. Here I will not go deep into the features of ObjC, but will give bare practice.
So let's start
For work, I will use Xcode 4.2, iOS SDK 5 and all this will work under Mac OS X 10.7.2 Lion.
As you say from the headline, I (read lecturer) will use the MVC data model. In general, honestly, I don’t understand how I can code for iOS differently. We write a program calculator. A simple calculator that will add, subtract, multiply, divide and extract the square root of numbers.
The program structure will be as follows:
1. we will have calculator brains that will perform all actions (brain class) - model;
2. we will have a controller that will handle button presses;
3. we will have a View, in which new iOS coders always have problems. More on this further.
')
New project
So let's start by creating a project. To do this, go File - New - New project. Among the total set of templates, select "Single View Application". I will call the application Calc. It is also worth noting that when creating the project I removed the tick "Use Storyboard". What it is for: in SDK 5 instead of the former .xib a new format .storyboard appeared. I don’t understand how they differ, so I use xib files for IB in the old way (hereinafter Interface Builder).
So we have a project. It already has a controller and view. To check the performance of the entire system, you can make a trial build. If everything is ok, then an iPhone emulator will appear on the screen and our application with a gray screen will start.
First we need the brains of a calculator (processor) that will perform all the operations. Press CMD + N and select the Objective-C class and call it CalcBrain a subclass of the NSObject class so that our brains inherit the basic methods. Now there are two more files in the project: CalcBrain.h and CalcBrain.m
Let's go to ViewController.h. There you will not see anything except the import of the standard UIKit library and the declaration of the controller itself. Here we will need to declare the following things:
- outlets: variables that will be pointed to certain Interface Builder elements;
- actions: proper methods that will be called when certain elements are performed by IB elements.
- we also need to declare the variable of our new class CalcBrain to make this whole thing work.
So let's go.
#import <UIKit/UIKit.h> #import "CalcBrain.h" @interface ViewController : UIViewController { IBOutlet UILabel *display; CalcBrain *brain; } -(IBAction)digitPressed:(UIButton *)sender; //++ -(IBAction)operationPressed:(UIButton *)sender; //++ @end
Here I will not explain anything, because the code can be intuitively understood (if not - alas, I advise you first to read about OOP and other goodies of the programmer world).
Interface building
Now we digress a bit from the code and build the interface. I think that Sach needs to focus all its attention, because in my experience a lot of novice coders without direct demonstration of actions just collapsed
at this stage and lowered their hands. Open ViewController.xib and see already existing objects:
Files's Owner is an object pointing to the class to which this xib belongs (in our case, it is a ViewController, which means that we can only use actions and outlets of this controller only);
First Responder;
View is directly the view of our controller itself.
First create the buttons. Let's start with numbers.

We create the first digit which in the future will be the seven.

In order not to suffer any further, we will immediately tie digitPressed to our action button. To do this, select our button and in the Connections Inspector take the cup that is opposite the Touch Down event and drag it to the File's Owner object.

A window will appear in which you can select an action to which the controller will respond when the button is touched.

We will need digitPressed.
All we have left is to breed our "button template" with Alt (options) clamped. Now you can set our label numbers. This can be done either through the Attribute inspector or by double clicking on the button. Also, do not forget that we have one button for separating the whole part from the fractional part (and this is done with the symbol "." And not "," as we do in Russia).

In the same way, we will do the operation buttons. We need addition, subtraction, division, multiplication and square root extraction. And an equal sign that will display the result of our action. Everything. Now we have an input device. By the output device, ie the display. It is necessary to create a Label object, make it left justified, set the font to 26 and default text "0". Nothing complicated.


We continue to code
We will not have more business with interfaces. Remained clean code.
By the way, if you're interested, you can start the application and see how it will look on the emulator.
Let's start writing our brains. They will work like this:
1 The object will receive the first operand;
2 The object receives the action;
3 If the action is not square root, we are preparing to receive the next operand;
4 If this is a root or equivalent result.
CalcBrain.h text
#import <Foundation/Foundation.h> @interface CalcBrain : NSObject { double operand; } -(void)setOperand:(double)aDouble; -(double)performOperation:(NSString *)operation; @end
With the variable operand I hope there is no need to explain. The class methods here are all just setOperand is the usual setter for the operand variable. It would be possible to use @syntesuze but then a getter will be generated which is useless to us. So we will manage also such crutch. Now we will describe all our methods.
- (void)setOperand:(double)aDouble{ operand = aDouble; } - (double)performOperation:(NSString *)operation{ if ([operation isEqual:@"sqrt"]) { operand = sqrt(operand); } return operand; }
A little about the second method. The second method will process our action (the operation request is actually called this). For now, we are just processing the square root. The input to this method will be the text from the operation button. Now we will struggle with the fact that the brain needs to memorize the first operand and the pressed operation before starting to memorize the second operand.
Let's add the class:
@interface CalcBrain : NSObject { double operand; NSString *waitingOperation; double waitingOperand; }
And the description:
- (double)performOperation:(NSString *)operation{ if ([operation isEqual:@"sqrt"]) { operand = sqrt(operand); } else { [self performWaitingOperation]; waitingOperation = operation; waitingOperand = operand; } return operand; }
The performWaitingOperation method will directly perform the action itself by the operands in the event that we have an action not on one operand (sqrt).
-(void)performWaitingOperation { if ([@"+" isEqual:waitingOperation]) { operand = waitingOperand + operand; } else if ([@"*" isEqual:waitingOperation]) { operand = waitingOperand * operand; } else if ([@"-" isEqual:waitingOperation]) { operand = waitingOperand - operand; } else if ([@"/" isEqual:waitingOperation]) { if (operand) { operand = waitingOperand / operand; } } }
Unforgettable to declare this method in CalcBrain.h
We program the controller
How proud it sounds. But to go to our controller and specifically to the header file. We begin to describe our already declared methods. By the way, everything that Xcode created in the ViewController.m file can be erased. Until. For this application, we will not need them. All we need is:
#import "ViewController.h" @implementation ViewController -(IBAction)digitPressed:(UIButton *)sender { } -(IBAction)operationPressed:(UIButton *)sender { } @end
Now let's go by the methods. When you click on the operation, we need to get the text from the button. This is done simply: the button drops to the method as an object with all the parameters:
-(IBAction)operationPressed:(UIButton *)sender { NSString *operation = [[sender titleLabel] text]; }
Now we need to request our brains to perform this operation. But first, we need to create these brains. We have identified the variable for them but have not yet announced:
-(CalcBrain *)brain { if (!brain) brain = [[CalcBrain alloc] init]; return brain; }
And we will add a method of clicking on the operation, make a request for support and display the result on the display:
-(IBAction)operationPressed:(UIButton *)sender { NSString *operation = [[sender titleLabel] text]; double result = [[self brain] performOperation:operation]; [display setText: [NSString stringWithFormat:@"%g", result]]; }
Now a logical problem arises- when the user presses "5", "5", then he means "55" and not "5" as our brains understand now. Ie, we need a Boolean variable that will identify whether the user is in the input process or not.
@interface ViewController : UIViewController { IBOutlet UILabel *display; CalcBrain *brain; BOOL userIsInTheMiddleOfTypingANumber; }
Now you can describe the operand declaration when you press the operation key:
-(IBAction)operationPressed:(UIButton *)sender { if (userIsInTheMiddleOfTypingANumber) { [[self brain] setOperand:[[display text] doubleValue]]; userIsInTheMiddleOfTypingANumber = NO; } NSString *operation = [[sender titleLabel] text]; double result = [[self brain] performOperation:operation]; [display setText: [NSString stringWithFormat:@"%g", result]]; }
Now we describe the click on the number:
-(IBAction)digitPressed:(UIButton *)sender { NSString *digit = [[sender titleLabel] text]; if (userIsInTheMiddleOfTypingANumber) { [display setText:[[display text] stringByAppendingString:digit]]; } else { [display setText:digit]; userIsInTheMiddleOfTypingANumber = YES; } }
Here the logic is simple: we get a digit from the label of the sender, if stringByAppendingString is true, then we need to append the entered digit to the display. If not, just add a number to the display and flip the stringByAppendingString parameter.
Now only Build and Run is left.

Homework
You can add three functions:
The function ± which will turn the cislo from negative to positive;
Result reset function (C);
And the function to repeat the operation (when I did the operation and repeatedly pressed on = the last operation is repeated with the last operand);