Basics of iOS
The term "iOS" was originally know as "iPhone OS" and was introduced in 2007 along with the first iPhone hardware device Apple released. It was the term used to describe the software that would operate the iPhone and is derived from the term "OS X", which is how Apple describes its "operating system" for its Macintosh computers. The "X" stands for 10 which is the newest version of the computer software Apple created to operate the desktop and laptop computers they design. The "iOS" platform is a mobile-device-based software system that works like a computer system, but on mobile devices like portable phones. It is designed to be smaller, faster and use less power. It also has a "touch" friendly user interface so it works better when a finger is used to interface with the system instead of a mouse or stylus that has been used in the past to interact with operating systems. The iPhone has run on iOS since its release in 2007.
Getting Started
- Linux/FreeBSD: Install GNUStep
- In order to build GNUstep applications one
must first execute the GNUstep.sh file in
/usr/GNUstep/System/Makefiles/GNUstep.sh. This path depends on your
system. Some put it in /usr, some /usr/lib, some /usr/local. If your
shell is a csh/tcsh based shell, you'll want to execute GNUStep.csh
instead. It's recommended that you put this script in your .bashrc or
.cshrc.
- Mac OS X: Install XCode
- Windows NT 5.X: Install cygwin or mingw and then install GNUStep
Creating Classes
@interface
Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
Fraction.h
#import <Foundation/NSObject.h>
@interface Fraction: NSObject {
int numerator;
int denominator;
}
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end
NSObject: Short for NeXTStep Object. Although this is less meaningful today since it's really OpenStep.
Inheritance is specified as Class: Parent, as seen with Fraction: NSObject.
Instance variables go between @interface Class: Parent { .... }
No access is set (protected, public, private). Default is protected. Setting the access will be shown later
Instance methods follow after the member variables. The format is: scope (returnType) methodName: (parameter1Type) parameter1Name;
scope refers to class or instance. instance methods begin with - class level methods begin with +
Interface ends with @end
@implementation
Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
Fraction.m
#import "Fraction.h"
#import <stdio.h>
@implementation Fraction
-(void) print {
printf( "%i/%i", numerator, denominator );
}
-(void) setNumerator: (int) n {
numerator = n;
}
-(void) setDenominator: (int) d {
denominator = d;
}
-(int) denominator {
return denominator;
}
-(int) numerator {
return numerator;
}
@end
@implementation ClassName starts the implementation @end ends it
All the defined methods are implemented very simlar to how they are declared in the interface
--------------------------------------------------------------------------------
Piecing it together
Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
main.m
#import <stdio.h>
#import "Fraction.h"
int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] init];
// set the values
[frac setNumerator: 1];
[frac setDenominator: 3];
// print it
printf( "The fraction is: " );
[frac print];
printf( "\n" );
// free memory
[frac release];
return 0;
}
output
The fraction is: 1/3
Fraction *frac = [[Fraction alloc] init];
There are several important things in this one line.
The way methods in Objective-C are called is [object method], which is similar to object->method() in C++
Objective-C doesn't have value types, so there is nothing similar to C++'s: Fraction frac; frac.print();. You always deal with objects as pointers in Objective-C.
What this line is really doing is two things: [Fraction alloc] is calling the alloc method on the Fraction class. This is similar to mallocing memory, because that is all that is done in this operation.
[object init] is the constructor call, which initializes any variables in the object. This method is called on the instance returned from [Fraction alloc]. This operation is so common it's usually just done in one line as Object *var = [[Object alloc] init];
[frac setNumerator: 1] is quite simple. It's calling the setNumerator method on frac, and passing it the parameter 1.
Like every c variant, there's a construct for freeing memory. This is done via release, which is inherited from NSObject. This method will be explainted in greater detail later.
The details...
Multiple Parameters
Up until this point I haven't showed any way to specify multiple parameters. It's not as intuitive at first, but it's syntax is a welcome addition from Smalltalk
Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
Fraction.h
...
-(void) setNumerator: (int) n andDenominator: (int) d;
...
Fraction.m
...
-(void) setNumerator: (int) n andDenominator: (int) d {
numerator = n;
denominator = d;
}
...
main.m
#import <stdio.h>
#import "Fraction.h"
int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
// set the values
[frac setNumerator: 1];
[frac setDenominator: 3];
// combined set
[frac2 setNumerator: 1 andDenominator: 5];
// print it
printf( "The fraction is: " );
[frac print];
printf( "\n" );
// print it
printf( "Fraction 2 is: " );
[frac2 print];
printf( "\n" );
// free memory
[frac release];
[frac2 release];
return 0;
}
output
The fraction is: 1/3
Fraction 2 is: 1/5
The method is actually called setNumerator:andDenominator:
Additional parameters are added the same was as the 2nd, such that you'd have method:label1:label2:label3: and you'd call it with [obj method: param1 label1: param2 label2: param3 label3: param4]
Labels are optional. It's possible to have a method named method:::. This is done by simply not specifing label names, but just a : to separate the parameters. This is however not advised.
Constructors
Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
Fraction.h
...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
...
Fraction.m
...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d {
self = [super init];
if ( self ) {
[self setNumerator: n andDenominator: d];
}
return self;
}
...
main.m
#import <stdio.h>
#import "Fraction.h"
int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
Fraction *frac3 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
// set the values
[frac setNumerator: 1];
[frac setDenominator: 3];
// combined set
[frac2 setNumerator: 1 andDenominator: 5];
// print it
printf( "The fraction is: " );
[frac print];
printf( "\n" );
printf( "Fraction 2 is: " );
[frac2 print];
printf( "\n" );
printf( "Fraction 3 is: " );
[frac3 print];
printf( "\n" );
// free memory
[frac release];
[frac2 release];
[frac3 release];
return 0;
}
output
The fraction is: 1/3
Fraction 2 is: 1/5
Fraction 3 is: 3/10
@interface declaration is identical to a regular function
@implementation shows a new keyword: super
Similar to Java, Objective-C only has one parent class.
Accessing it's super constructor is done through [super init] and this is required for proper inheritance.
This returns an instance which you assign to another new keyword, self. Self is similar to this in Java and C++.
if ( self ) is the same as if ( self != nil ) to make sure that the super constructor successfully returned a new object. nil is Objective-C's form of NULL from C/C++. This is gotten from including NSObject.
After you've initialized the varialbes, you return yourself with return self;
The deafult constructor is -(id) init;
Constructors in Objective-C are technically just "init" methods, they aren't a special construct like they are in C++ and Java.
Access Privledges
The default access is @protected
Java implements this with public/private/protected modifiers infront of methods and variables. Objective-C's approach is much more similar to C++'s for instance variables
Access.h
#import <Foundation/NSObject.h>
@interface Access: NSObject {
@public
int publicVar;
@private
int privateVar;
int privateVar2;
@protected
int protectedVar;
}
@end
Access.m
#import "Access.h"
@implementation Access
@end
main.m
#import "Access.h"
#import <stdio.h>
int main( int argc, const char *argv[] ) {
Access *a = [[Access alloc] init];
// works
a->publicVar = 5;
printf( "public var: %i\n", a->publicVar );
// doesn't compile
//a->privateVar = 10;
//printf( "private var: %i\n", a->privateVar );
[a release];
return 0;
}
output
public var: 5
As you an see, instead of private: [list of vars] public: [list of vars] like in C++, it's just @private, @protected, etc.
Class level access
Often it's nice to have class level variables and functions, for instance when keeping track of the # of times an object has been instanciated.
ClassA.h
#import <Foundation/NSObject.h>
static int count;
@interface ClassA: NSObject
+(int) initCount;
+(void) initialize;
@end
ClassA.m
#import "ClassA.h"
@implementation ClassA
-(id) init {
self = [super init];
count++;
return self;
}
+(int) initCount {
return count;
}
+(void) initialize {
count = 0;
}
@end
main.m
#import "ClassA.h"
#import <stdio.h>
int main( int argc, const char *argv[] ) {
ClassA *c1 = [[ClassA alloc] init];
ClassA *c2 = [[ClassA alloc] init];
// print count
printf( "ClassA count: %i\n", [ClassA initCount] );
ClassA *c3 = [[ClassA alloc] init];
// print count again
printf( "ClassA count: %i\n", [ClassA initCount] );
[c1 release];
[c2 release];
[c3 release];
return 0;
}
output
ClassA count: 2
ClassA count: 3
static int count = 0; This is how the class variable is declared. This is not the ideal place for such a variable. A nicer solution would have been like Java's implementation of static class variables. However this works
+(int) initCount; This is the actual method that returns the count. Notice the subtle difference. Instead of using a - infront of the type, a + is used. The + denotes a class level function.
Accessing the variable is no different than member variables, as seen by count++ in the constructor of ClassA.
The +(void) initialize method is called when Objective-C starts your program, and it's called for every class. This is a good place to initialize class level variables like our count.
Exceptions
NOTE: Exception handling is only supported in Mac OS X 10.3
Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
CupWarningException.h
#import <Foundation/NSException.h>
@interface CupWarningException: NSException
@end
CupWarningException.m
#import "CupWarningException.h"
@implementation CupWarningException
@end
CupOverflowException.h
#import <Foundation/NSException.h>
@interface CupOverflowException: NSException
@end
CupOverflowException.m
#import "CupOverflowException.h"
@implementation CupOverflowException
@end
Cup.h
#import <Foundation/NSObject.h>
@interface Cup: NSObject {
int level;
}
-(int) level;
-(void) setLevel: (int) l;
-(void) fill;
-(void) empty;
-(void) print;
@end
Cup.m
#import "Cup.h"
#import "CupOverflowException.h"
#import "CupWarningException.h"
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
@implementation Cup
-(id) init {
self = [super init];
if ( self ) {
[self setLevel: 0];
}
return self;
}
-(int) level {
return level;
}
-(void) setLevel: (int) l {
level = l;
if ( level > 100 ) {
// throw overflow
NSException *e = [CupOverflowException
exceptionWithName: @"CupOverflowException"
reason: @"The level is above 100"
userInfo: nil];
@throw e;
} else if ( level >= 50 ) {
// throw warning
NSException *e = [CupWarningException
exceptionWithName: @"CupWarningException"
reason: @"The level is above or at 50"
userInfo: nil];
@throw e;
} else if ( level < 0 ) {
// throw exception
NSException *e = [NSException
exceptionWithName: @"CupUnderflowException"
reason: @"The level is below 0"
userInfo: nil];
@throw e;
}
}
-(void) fill {
[self setLevel: level + 10];
}
-(void) empty {
[self setLevel: level - 10];
}
-(void) print {
printf( "Cup level is: %i\n", level );
}
@end
main.m
#import "Cup.h"
#import "CupOverflowException.h"
#import "CupWarningException.h"
#import <Foundation/NSString.h>
#import <Foundation/NSException.h>
#import <Foundation/NSAutoreleasePool.h>
#import <stdio.h>
int main( int argc, const char *argv[] ) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Cup *cup = [[Cup alloc] init];
int i;
// this will work
for ( i = 0; i < 4; i++ ) {
[cup fill];
[cup print];
}
// this will throw exceptions
for ( i = 0; i < 7; i++ ) {
@try {
[cup fill];
} @catch ( CupWarningException *e ) {
printf( "%s: ", [[e name] cString] );
} @catch ( CupOverflowException *e ) {
printf( "%s: ", [[e name] cString] );
} @finally {
[cup print];
}
}
// throw a generic exception
@try {
[cup setLevel: -1];
} @catch ( NSException *e ) {
printf( "%s: %s\n", [[e name] cString], [[e reason] cString] );
}
// free memory
[cup release];
[pool release];
}
output
Cup level is: 10
Cup level is: 20
Cup level is: 30
Cup level is: 40
CupWarningException: Cup level is: 50
CupWarningException: Cup level is: 60
CupWarningException: Cup level is: 70
CupWarningException: Cup level is: 80
CupWarningException: Cup level is: 90
CupWarningException: Cup level is: 100
CupOverflowException: Cup level is: 110
CupUnderflowException: The level is below 0
NSAutoreleasePool is a memory management class. Don't worry about what this does right now.
Exceptions that are thrown don't have to extend NSException. You can just as easily use an id as well: @catch ( id e ) { ... }
There is also a finally block, which behaves just like Java's. The contents of a finally block are guaranteed to be called.
The string as show in Cup.m, @"CupOverflowException", is a constant NSString object. The @ sign is used often in Objective-C to denote extentions to the language. A C string is just like C and C++, "String constant", and is of type char *.
No comments:
Post a Comment