Programming in Objective-C Classes, Objects, and Methods

Download Report

Transcript Programming in Objective-C Classes, Objects, and Methods

Writing iOS applications
Copyright © 2012 by Yong-Gu Lee
([email protected])
Introduction to Cocoa and Cocoa Touch
•
•
•
•
•
•
•
•
Framework layers
The kernel provides the low-level communication to the hardware in
the form of device drivers. It manages the system’s resources, which
includes scheduling programs for execution, managing memory and
power, and performing basic I/O operations.
Core Services provides support at a lower or “core” level than that
provided in the layers above it. For example, here you find support
for collections, networking, debugging, file management, folders,
memory management, threads, time, and power.
The Application Services layer includes support for printing and
graphics rendering, including Quartz, OpenGL, and Quicktime.
Directly below your application sits the Cocoa layer. As noted, Cocoa
includes the Foundation, Core Data, and AppKit frameworks.
Foundation offers classes for working with collections, strings,
memory management, the file system, archiving, and so on.AppKit
provides classes for managing views, windows, documents, and the
rich user interface for which Mac OS X is well known.
Duplication of functionality between some of the layers. Collections
exist in both the Cocoa and Core Services layers. However, the
former builds on support of the latter.
A layer can be bypassed. For example, some Foundation classes,
such as those that deal with the file system, rely directly on
functionality in the Core Services layer and so bypass the Application
Services layer.
The Foundation framework defines an object-oriented mapping of
data structures defined in the lower-level Core Services layer (which
is written primarily in the procedural C language).
Cocoa Touch
• iOS devices like the iPhone, the iPod Touch, and the iPad contain a
computer that runs a scaled-down version of Mac OS X. Some
features in the iPhone’s hardware, such as its accelerometer, are
unique to the phone and are not found in other Mac OS X
computers, such as MacBook Pro’s or iMacs.
• Cocoa frameworks are designed for application development for
Mac OS X desktop and notebook computers, the Cocoa Touch
frameworks are for applications targeted for iOS devices.
• Both Cocoa and Cocoa Touch have the Foundation and Core Data
frameworks in common. However, the UIKit replaces the AppKit
framework under Cocoa Touch, providing support for many of the
same types of objects, such as windows, views, buttons, text fields,
and so on. In addition, Cocoa Touch provides classes for working
with the accelerometer, gyroscope, triangulating your location with
GPS and WiFi signals, and the touch-driven interface, and also
eliminates classes that aren’t needed.
First example
Two generated classes
• AppDelegate
– Methods that control the application’s execution. That
includes what to do when the application starts, when it
enters and leaves the background, when the system tells it
is using to much memory, and when it terminates.
• ViewController
– Responsible for managing the display of one or more
“views”on your iPhone’s display.
– Responsible for handling the event of pressing the button
labeled “1.” We will define a method to respond to that
action of pressing the button “1.”
– You will see shortly how you make the connection
between this event to the execution of a specified method.
Outlets
• Your objects can also have instance variables whose
values correspond to some control in your iPhone’s
window, such as the name on a label or the text
displayed in an editable text box .These variables are
known as outlets, and you’ll see how you connect an
instance variable to an actual control in the iPhone’s
window.
• For our first application, we need a method that
responds to the action of the pressing of the button
labeled 1. We also need an outlet variable that
contains (among other information) the text to be
displayed in the label that we create at the top of the
iPhone’s window.
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (nonatomic, retain) IBOutlet UILabel *display;
-(IBAction) click1;
@end
@implementation ViewController
@synthesize display;
-(IBAction) click1
{
display.text = @"1";
}
//Other methods inserted by Xcode not shown
here
Outlet property that will be
connected to a label. When you set
this property’s text field, it updates
the corresponding text for the label
in the window. Other methods
defined for the UILabel class allow
you to set and retrieve other
attributes of a label, such as its
color, the number of lines, and the
size of the font.
Interface
Builder
Attributes
Inspector
Object
Library
Change
background
to black
Label
Remove the
default
string Label
Right justify
Resize the box
Change the
background
to blue
Change
title to
“1"
Button
Scenario
• The user presses the button labeled 1.
• This event causes the click1 method to be
executed.
• The click1 method changes the text property
of the instance variable display to the string 1.
• Because the UILabel object display connects
to the label in the iPhone’s window, this label
updates to the corresponding text value, or to
the value 1.
First, let’s get the source code displayed in the third pane.To do this, first selectView, Utilities, Hide Utilities. Next, select View, Editor, Assistant.
Control drag from Label to display
and button to click1
An iPhone Fraction Calculator
@property (nonatomic, strong) IBOutlet UILabel *display;
-(void) processDigit: (int) digit;
-(void) processOp: (char) theOp;
-(void) storeFracPart;
// Numeric keys
- (IBAction) clickDigit: (UIButton *) sender; // Arithmetic Operation keys
-(IBAction) clickPlus;
-(IBAction) clickMinus;
-(IBAction) clickMultiply;
-(IBAction) clickDivide;
// Misc. Keys
-(IBAction) clickOver;
-(IBAction) clickEquals;
-(IBAction) clickClear;
#import <Foundation/Foundation.h>
@interface Fraction : NSObject
@property int numerator, denominator;
-(void) print;
-(void) setTo: (int) n over: (int) d;
-(Fraction *) add: (Fraction *) f;
-(Fraction *) subtract: (Fraction *) f;
-(Fraction *) multiply: (Fraction *) f;
-(Fraction *) divide: (Fraction *) f;
-(void) reduce;
-(double) convertToNum;
-(NSString *) convertToString;
@end
#import "Fraction.h"
@implementation Fraction
@synthesize numerator, denominator;
-(void) setTo: (int) n over: (int) d
{
numerator = n;
denominator = d;
}
-(void) print
{
NSLog (@"%i/%i", numerator, denominator);
}
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator; else
return NAN;
}
-(NSString *) convertToString
{
if (numerator == denominator)
if (numerator == 0)
return @"0"; else
return @"1";
else
if (denominator == 1)
return [NSString stringWithFormat: @"%i", numerator];
else
return [NSString stringWithFormat: @"%i/%i", numerator, denominator];
}
// add a Fraction to the receiver
-(Fraction *) add: (Fraction *) f
{
// To add two fractions:
// a/b + c/d = ((a*d) + (b*c)) / (b * d)
// result will store the result of the addition
Fraction *result = [[Fraction alloc] init];
result.numerator = numerator * f.denominator + denominator * f.numerator;
result.denominator = denominator * f.denominator;
[result reduce];
return result;
}
-(Fraction *) subtract: (Fraction *) f
{
// To sub two fractions:
// a/b - c/d = ((a*d) - (b*c)) / (b * d)
Fraction *result = [[Fraction alloc] init];
result.numerator = numerator * f.denominator - denominator * f.numerator;
result.denominator = denominator * f.denominator;
[result reduce];
return result;
}
-(Fraction *) multiply: (Fraction *) f
{
Fraction *result = [[Fraction alloc] init];
result.numerator = numerator * f.numerator;
result.denominator = denominator * f.denominator;
[result reduce];
return result;
}
-(Fraction *) divide: (Fraction *) f
{
Fraction *result = [[Fraction alloc] init];
result.numerator = numerator * f.denominator;
result.denominator = denominator * f.numerator;
[result reduce];
- (void) reduce
{
int u = numerator; int v = denominator; int
temp;
if (u == 0) return;
else if (u <0) u = -u;
while (v != 0) { temp = u % v;
u = v;
v = temp; }
numerator /= u;
denominator /= u;
}
@end
#import <UIKit/UIKit.h>
#import "Calculator.h"
@interface ViewController : UIViewController
{
char op;
int currentNumber;
BOOL firstOperand;
BOOL isNumerator;
NSMutableString *displayString;
Calculator *myCalculator;
number-in-progress
whether this is the first or second
operand entered
}
@property (nonatomic, strong) IBOutlet UILabel *display;
-(void) processDigit: (int) digit;
-(void) processOp: (char) theOp;
-(void) storeFracPart;
whether the user is currently
keying in the numerator or
the denominator of that
operand
// Numeric keys
- (IBAction) clickDigit: (UIButton *) sender; // Arithmetic Operation keys
-(IBAction) clickPlus;
-(IBAction) clickMinus;
-(IBAction) clickMultiply;
-(IBAction) clickDivide;
// Misc. Keys
-(IBAction) clickOver;
-(IBAction) clickEquals;
-(IBAction) clickClear;
@end
#import "ViewController.h"
#import "Calculator.h”
@implementation ViewController
@synthesize display;
-(void) viewDidLoad {
// Override point for customization after application launch
firstOperand = YES;
isNumerator = YES;
displayString = [NSMutableString stringWithCapacity: 40];
myCalculator = [[Calculator alloc] init];
}
-(void) processDigit: (int) digit
{
currentNumber = currentNumber * 10 + digit;
[displayString appendString:
[NSString stringWithFormat: @"%i", digit]];
display.text = displayString; }
- (IBAction) clickDigit: (UIButton *) sender
{
int digit = sender.tag;
[self processDigit: digit];
}
-(void) processOp: (char) theOp
{
NSString *opStr;
op = theOp;
switch (theOp) {
case '+':
opStr = @" + ";
break;
case '-':
opStr = @" – ";
break;
case '*':
opStr = @" × ";
break;
case '/':
opStr = @" ÷ ";
break;
}
[self storeFracPart]; firstOperand = NO; isNumerator = YES;
[displayString appendString: opStr];
display.text = displayString;
}
-(void) storeFracPart
{
if (firstOperand) {
if (isNumerator) {
myCalculator.operand1.numerator = currentNumber;
myCalculator.operand1.denominator = 1; // e.g. 3 * 4/5 =
}
else
myCalculator.operand1.denominator = currentNumber;
}
else if (isNumerator) {
myCalculator.operand2.numerator = currentNumber;
myCalculator.operand2.denominator = 1; // e.g. 3/2 * 4 =
}
else {
myCalculator.operand2.denominator = currentNumber;
firstOperand = YES;
}
currentNumber = 0;
}
-(IBAction) clickOver
{
[self storeFracPart];
isNumerator = NO;
[displayString appendString: @"/"]; display.text = displayString;
}
// Arithmetic Operation keys
-(IBAction) clickPlus
{
[self processOp: '+'];
}
-(IBAction) clickMinus
{
[self processOp: '-'];
}
-(IBAction) clickMultiply
{
[self processOp: '*'];
}
-(IBAction) clickDivide
{
[self processOp: '/'];
}
// Misc. Keys
-(IBAction) clickEquals
{
if ( firstOperand == NO ) {
[self storeFracPart];
[myCalculator performOperation: op];
[displayString appendString: @" = "];
[displayString appendString: [myCalculator.accumulator
convertToString]];
display.text = displayString;
currentNumber = 0;
isNumerator = YES; firstOperand = YES; [displayString setString: @""];
}
}
-(IBAction) clickClear
{
isNumerator = YES; firstOperand = YES; currentNumber = 0; [myCalculator
clear];
[displayString setString: @""];
display.text = displayString;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
firstOperand BOOL
YES
isNumerator BOOL
YES
firstOperand BOOL
YES
isNumerator BOOL
NO
firstOperand BOOL
YES
isNumerator BOOL
NO
firstOperand BOOL
YES
isNumerator BOOL
NO
firstOperand BOOL
NO
isNumerator BOOL
Yes
firstOperand BOOL
NO
isNumerator BOOL
Yes
1
firstOperand BOOL
NO
isNumerator BOOL
Yes
isNumerator BOOL
Yes
isNumerator BOOL
NO
isNumerator BOOL
Yes
/
8
-(IBAction) clickEquals
{
if ( firstOperand == NO ) {
[self storeFracPart];
[myCalculator performOperation: op];
[displayString appendString: @" = "];
[displayString appendString:
[myCalculator.accumulator convertToString]];
display.text = displayString;
currentNumber = 0;
isNumerator = YES; firstOperand = YES;
[displayString setString: @""];
}
}