objective c here
-
Upload
dina-mostafa -
Category
Documents
-
view
214 -
download
0
Transcript of objective c here
-
8/7/2019 objective c here
1/45
Translations: English | Chinese | Korean
Outline
Getting Startedo Downloading this tutorial
o Setting up the environment
o Preamble
o Making hello world
Creating Classes
o @interface
o @implementation
o Piecing it together
The Details...
o Multiple Parameters
o Constructors
o Access Privledges
o Class level access
o Exceptions
Inheritance, Polymorphism, and other OOP features
o The id type
o Inheritance
o Dynamic types
o Categories
o Posing
o Protocols Memory Management
o Retain and Release
o Dealloc
o Autorelease Pool
Foundation Framework Classes
o NSArray
o NSDictionary
Pros and Cons
More Information
Getting Startedo Downloading this tutorial
All the source code for this beginners guide including
makefiles is available by downloadingobjc.tar.gz. Many of the
examples in this tutorial were written by Steve Kochan in the
bookProgramming in Objective-C. If you want more detailed
information and examples, feel free to check out his book. The
examples on this site were used with his permission, so please
don't copy them.
http://www.otierney.net/objective-c.html.zh-tw.big5http://www.otierney.net/objective-c.html.kohttp://www.otierney.net/objective-c.html#gettingstartedhttp://www.otierney.net/objective-c.html#downloadinghttp://www.otierney.net/objective-c.html#settinguphttp://www.otierney.net/objective-c.html#preamblehttp://www.otierney.net/objective-c.html#helloworldhttp://www.otierney.net/objective-c.html#creatingclasseshttp://www.otierney.net/objective-c.html#interfacehttp://www.otierney.net/objective-c.html#implementationhttp://www.otierney.net/objective-c.html#piecinghttp://www.otierney.net/objective-c.html#thedetailshttp://www.otierney.net/objective-c.html#thedetailshttp://www.otierney.net/objective-c.html#multiplehttp://www.otierney.net/objective-c.html#constructorshttp://www.otierney.net/objective-c.html#accesshttp://www.otierney.net/objective-c.html#classhttp://www.otierney.net/objective-c.html#exceptionshttp://www.otierney.net/objective-c.html#inheritancehttp://www.otierney.net/objective-c.html#idtypehttp://www.otierney.net/objective-c.html#subinheritancehttp://www.otierney.net/objective-c.html#dynamictypeshttp://www.otierney.net/objective-c.html#categorieshttp://www.otierney.net/objective-c.html#posinghttp://www.otierney.net/objective-c.html#protocolshttp://www.otierney.net/objective-c.html#memorymanagementhttp://www.otierney.net/objective-c.html#retainhttp://www.otierney.net/objective-c.html#deallochttp://www.otierney.net/objective-c.html#autoreleasehttp://www.otierney.net/objective-c.html#foundationhttp://www.otierney.net/objective-c.html#nsarrayhttp://www.otierney.net/objective-c.html#nsdictionaryhttp://www.otierney.net/objective-c.html#prosandconshttp://www.otierney.net/objective-c.html#moreinfohttp://www.otierney.net/files/objc.tar.gzhttp://www.otierney.net/files/objc.tar.gzhttp://www.otierney.net/files/objc.tar.gzhttp://www.amazon.com/gp/product/0321566157?ie=UTF8&tag=tristanshomep-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0321566157http://www.otierney.net/objective-c.html.kohttp://www.otierney.net/objective-c.html#gettingstartedhttp://www.otierney.net/objective-c.html#downloadinghttp://www.otierney.net/objective-c.html#settinguphttp://www.otierney.net/objective-c.html#preamblehttp://www.otierney.net/objective-c.html#helloworldhttp://www.otierney.net/objective-c.html#creatingclasseshttp://www.otierney.net/objective-c.html#interfacehttp://www.otierney.net/objective-c.html#implementationhttp://www.otierney.net/objective-c.html#piecinghttp://www.otierney.net/objective-c.html#thedetailshttp://www.otierney.net/objective-c.html#multiplehttp://www.otierney.net/objective-c.html#constructorshttp://www.otierney.net/objective-c.html#accesshttp://www.otierney.net/objective-c.html#classhttp://www.otierney.net/objective-c.html#exceptionshttp://www.otierney.net/objective-c.html#inheritancehttp://www.otierney.net/objective-c.html#idtypehttp://www.otierney.net/objective-c.html#subinheritancehttp://www.otierney.net/objective-c.html#dynamictypeshttp://www.otierney.net/objective-c.html#categorieshttp://www.otierney.net/objective-c.html#posinghttp://www.otierney.net/objective-c.html#protocolshttp://www.otierney.net/objective-c.html#memorymanagementhttp://www.otierney.net/objective-c.html#retainhttp://www.otierney.net/objective-c.html#deallochttp://www.otierney.net/objective-c.html#autoreleasehttp://www.otierney.net/objective-c.html#foundationhttp://www.otierney.net/objective-c.html#nsarrayhttp://www.otierney.net/objective-c.html#nsdictionaryhttp://www.otierney.net/objective-c.html#prosandconshttp://www.otierney.net/objective-c.html#moreinfohttp://www.otierney.net/files/objc.tar.gzhttp://www.amazon.com/gp/product/0321566157?ie=UTF8&tag=tristanshomep-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0321566157http://www.otierney.net/objective-c.html.zh-tw.big5 -
8/7/2019 objective c here
2/45
-
8/7/2019 objective c here
3/45
that the object implements that message, just that it knows how
to respond to it somehow via directly implementing it or
forwarding the message to an object that does know how to.
o Making hello world hello.m
#import
int main( int argc, const char *argv[] ) {
printf( "hello world\n" );
return 0;}
output
hello world
You use #import instead of #include in Objective-C
The default file extention for Objective-C is .m
Creating classeso @interface
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
Fraction.h
#import
@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;
-
8/7/2019 objective c here
4/45
scope refers to class or instance. instance
methods begin with - class level methods begin with +
Interface ends with @end
o @implementation Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
Fraction.m
#import "Fraction.h"
#import
@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
o Piecing it together Based on an example in "Programming in Objective-C,"Copyright 2004 by Sams Publishing. Used with permission
main.m
#import
#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];
-
8/7/2019 objective c here
5/45
// 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 freeingmemory. This is done via release, which is inherited from
NSObject. This method will be explainted in greater detail
later.
The details...o 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
-
8/7/2019 objective c here
6/45
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
#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
-
8/7/2019 objective c here
7/45
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.
o Constructors Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
Fraction.h
...
-(Fraction*) initWithNumerator: (int) ndenominator: (int) d;...
Fraction.m
...
-(Fraction*) initWithNumerator: (int) ndenominator: (int) d {
self = [super init];
if ( self ) {
[self setNumerator: n andDenominator:d];
}
return self;
}...
main.m #import
#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];
-
8/7/2019 objective c here
8/45
[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/5Fraction 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 Javaand 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.
-
8/7/2019 objective c here
9/45
o 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
@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
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
-
8/7/2019 objective c here
10/45
As you an see, instead of private: [list of vars] public:
[list of vars] like in C++, it's just @private, @protected, etc.
o 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
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
int main( int argc, const char *argv[] ) {
ClassA *c1 = [[ClassA alloc] init];
ClassA *c2 = [[ClassA alloc] init];
// print count
printf( "ClassA count: %i\n", [ClassAinitCount] );
ClassA *c3 = [[ClassA alloc] init];
// print count again
-
8/7/2019 objective c here
11/45
printf( "ClassA count: %i\n", [ClassAinitCount] );
[c1 release];
[c2 release];
[c3 release];
return 0;}
output
ClassA count: 2ClassA 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 nicersolution 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.o 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
@interface CupWarningException: NSException@end
CupWarningException.m
#import "CupWarningException.h"
@implementation CupWarningException@end
CupOverflowException.h
#import
@interface CupOverflowException: NSException
-
8/7/2019 objective c here
12/45
@end
CupOverflowException.m
#import "CupOverflowException.h"
@implementation CupOverflowException@end
Cup.h
#import
@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
#import
@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
-
8/7/2019 objective c here
13/45
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 at50"
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
#import
#import
#import
int main( int argc, const char *argv[] ) {
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
Cup *cup = [[Cup alloc] init]; int i;
-
8/7/2019 objective c here
14/45
// 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: 110CupUnderflowException: The level is below 0
NSAutoreleasePool is a memory management class.Don't worry about what this does right now.
-
8/7/2019 objective c here
15/45
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 *.
Inheritance, Polymorphism, and
other OOP features
o The id type Objective-C has a type called id, that acts in some wayslike a void*, though it's meant strictly for objects. Objective-C
differs from Java and C++ in that when you call a method on an
object, it doesn't need to know the type. That method simply
just has to exist. This is refered to as message pasing in
Objective-C.
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
Fraction.h
#import
@interface Fraction: NSObject {
int numerator;
int denominator;
}
-(Fraction*) initWithNumerator: (int) ndenominator: (int) d;
-(void) print;
-(void) setNumerator: (int) d;
-(void) setDenominator: (int) d;
-(void) setNumerator: (int) n andDenominator:(int) d;
-(int) numerator;
-(int) denominator;@end
Fraction.m
#import "Fraction.h"
#import
@implementation Fraction
-(Fraction*) initWithNumerator: (int) ndenominator: (int) d {
-
8/7/2019 objective c here
16/45
self = [super init];
if ( self ) {
[self setNumerator: n andDenominator:d];
}
return self;
}
-(void) print {
printf( "%i / %i", numerator,denominator );
}
-(void) setNumerator: (int) n {
numerator = n;
}
-(void) setDenominator: (int) d {
denominator = d;
}
-(void) setNumerator: (int) n andDenominator:(int) d {
numerator = n;
denominator = d;
}
-(int) denominator {
return denominator;
}
-(int) numerator {
return numerator;
}@end
Complex.h
#import
@interface Complex: NSObject {
double real;
double imaginary;
}
-(Complex*) initWithReal: (double) randImaginary: (double) i;
-(void) setReal: (double) r;
-(void) setImaginary: (double) i;
-(void) setReal: (double) r andImaginary:(double) i;
-
8/7/2019 objective c here
17/45
-(double) real;
-(double) imaginary;
-(void) print;
@end
Complex.m
#import "Complex.h"
#import
@implementation Complex
-(Complex*) initWithReal: (double) randImaginary: (double) i {
self = [super init];
if ( self ) {
[self setReal: r andImaginary: i];
}
return self;
}
-(void) setReal: (double) r {
real = r;
}
-(void) setImaginary: (double) i {
imaginary = i;
}
-(void) setReal: (double) r andImaginary:(double) i {
real = r;
imaginary = i;
}
-(double) real {
return real;
}
-(double) imaginary {
return imaginary;
}
-(void) print {
printf( "%_f + %_fi", real, imaginary );
}
@end
main.m
-
8/7/2019 objective c here
18/45
#import
#import "Fraction.h"
#import "Complex.h"
int main( int argc, const char *argv[] ) {
// create a new instance Fraction *frac = [[Fraction alloc]initWithNumerator: 1 denominator: 10];
Complex *comp = [[Complex alloc]initWithReal: 10 andImaginary: 15];
id number;
// print fraction
number = frac;
printf( "The fraction is: " );
[number print];
printf( "\n" );
// print complex
number = comp;
printf( "The complex number is: " );
[number print];
printf( "\n" );
// free memory
[frac release];
[comp release];
return 0;}
output
The fraction is: 1 / 10The complex number is: 10.000000 + 15.000000i
There are obvious benefits to this type of dynamic
binding. You don't have to know the type of something to call a
method on it. If the object responds to a message, it will invoke
that method. Lots of nasty casting isn't involved in this either,such as in Java to call .intValue() on an integer object would
involve casting first, then calling the method.
o Inheritance Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
Rectangle.h
#import
@interface Rectangle: NSObject {
int width;
int height;
-
8/7/2019 objective c here
19/45
}
-(Rectangle*) initWithWidth: (int) w height:(int) h;
-(void) setWidth: (int) w;
-(void) setHeight: (int) h;
-(void) setWidth: (int) w height: (int) h;
-(int) width;
-(int) height;
-(void) print;@end
Rectangle.m
#import "Rectangle.h"
#import
@implementation Rectangle
-(Rectangle*) initWithWidth: (int) w height:(int) h {
self = [super init];
if ( self ) {
[self setWidth: w height: h];
}
return self;
}
-(void) setWidth: (int) w {
width = w;
}
-(void) setHeight: (int) h {
height = h;
}
-(void) setWidth: (int) w height: (int) h {
width = w;
height = h;
}
-(int) width {
return width;
}
-(int) height {
return height;
}
-(void) print {
printf( "width = %i, height = %i", width,height );
-
8/7/2019 objective c here
20/45
}@end
Square.h
#import "Rectangle.h"
@interface Square: Rectangle
-(Square*) initWithSize: (int) s;
-(void) setSize: (int) s;
-(int) size;@end
Square.m
#import "Square.h"
@implementation Square -(Square*) initWithSize: (int) s {
self = [super init];
if ( self ) {
[self setSize: s];
}
return self;
}
-(void) setSize: (int) s { width = s;
height = s;
}
-(int) size {
return width;
}
-(void) setWidth: (int) w {
[self setSize: w];
}
-(void) setHeight: (int) h {
[self setSize: h];
}@end
main.m
#import "Square.h"
#import "Rectangle.h"
#import
int main( int argc, const char *argv[] ) {
-
8/7/2019 objective c here
21/45
Rectangle *rec = [[Rectangle alloc]initWithWidth: 10 height: 20];
Square *sq = [[Square alloc] initWithSize:15];
// print em printf( "Rectangle: " );
[rec print];
printf( "\n" );
printf( "Square: " );
[sq print];
printf( "\n" );
// update square
[sq setWidth: 20];
printf( "Square after change: " );
[sq print];
printf( "\n" );
// free memory
[rec release];
[sq release];
return 0;}
output
Rectangle: width = 10, height = 20
Square: width = 15, height = 15Square after change: width = 20, height = 20
Inheritance in Objective-C is similar to Java. When you
extend your super class (of which you can only have one
parent) you can override the methods of your super class by
simply putting the new implementations in the child classes
implementation. No fooling with virtual tables like C++.
One thing left out here that is worth nothing is what
would happen if you attempted to call the constructor forrectangle like: Square *sq = [[Square alloc] initWithWidth: 10
height: 15]. The answer is it will throw a compile error. Since
the return type of the rectangle constructor is Rectangle*, not
Square* this would not work. In such a case if you want this to
occur, that's what the id variable is good for. Just change the
Rectangle* return type to id if you wish to use your parent's
constructors in a subclass.
o Dynamic types There are several methods for working with dynamic
types in Objective-C-(BOOL) isKindOfClass: classObj is object a
-
8/7/2019 objective c here
22/45
descendent
or member
of classObj
-(BOOL) isMemberOfClass: classObj
is object a
member of
classObj
-(BOOL) respondsToSelector: selector
does the
object have
a method
named
specifiec by
the selector
+(BOOL) instancesRespondToSelector:
selector
does an
object
created by
this class
have the
ability to
respond to
the
specified
selector
-(id) performSelector: selector
invoke the
specified
selector on
the object Every object inherited from NSObject has a class
method that returns a class object. This is very similar to Java's
getClass() method. This class object is used in the methods
above.
Selectors are used to represent a message in Objective-
C. The syntax for creating a selector is shown in the next
example
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
main.m
#import "Square.h"
#import "Rectangle.h"
#import
int main( int argc, const char *argv[] ) {
Rectangle *rec = [[Rectangle alloc]initWithWidth: 10 height: 20];
Square *sq = [[Square alloc] initWithSize:15];
// isMemberOfClass
// true
-
8/7/2019 objective c here
23/45
if ( [sq isMemberOfClass: [Square class]]== YES ) {
printf( "square is a member of squareclass\n" );
}
// false
if ( [sq isMemberOfClass: [Rectangleclass]] == YES ) {
printf( "square is a member ofrectangle class\n" );
}
// false
if ( [sq isMemberOfClass: [NSObjectclass]] == YES ) {
printf( "square is a member of object
class\n" ); }
// isKindOfClass
// true
if ( [sq isKindOfClass: [Square class]] ==YES ) {
printf( "square is a kind of squareclass\n" );
}
// true
if ( [sq isKindOfClass: [Rectangle class]]== YES ) {
printf( "square is a kind of rectangleclass\n" );
}
// true
if ( [sq isKindOfClass: [NSObject class]]== YES ) {
printf( "square is a kind of objectclass\n" );
}
// respondsToSelector
// true
if ( [sq respondsToSelector:@selector( setSize: )] == YES ) {
printf( "square responds to setSize:method\n" );
}
// false
-
8/7/2019 objective c here
24/45
if ( [sq respondsToSelector:@selector( nonExistant )] == YES ) {
printf( "square responds tononExistant method\n" );
}
// true
if ( [Square respondsToSelector:@selector( alloc )] == YES ) {
printf( "square class responds toalloc method\n" );
}
// instancesRespondToSelector
// false
if ( [Rectangle
instancesRespondToSelector: @selector( setSize: )]== YES ) {
printf( "rectangle instance respondsto setSize: method\n" );
}
// true
if ( [Square instancesRespondToSelector:@selector( setSize: )] == YES ) {
printf( "square instance responds tosetSize: method\n" );
}
// free memory
[rec release];
[sq release];
return 0;}
output
square is a member of square class
square is a kind of square class
square is a kind of rectangle class
square is a kind of object class
square responds to setSize: method
square class responds to alloc methodsquare instance responds to setSize: method
o Categories When you want to add methods to a class, you typically
extend it. However this solution isn't always perfect, especially
if you want to rewrite the functionality of a class that you don't
have the source code to. Categories allow you to add
-
8/7/2019 objective c here
25/45
functionality to already existing classes without extending
them. Ruby also has similar functionality to this.
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
FractionMath.h
#import "Fraction.h"
@interface Fraction (Math)
-(Fraction*) add: (Fraction*) f;
-(Fraction*) mul: (Fraction*) f;
-(Fraction*) div: (Fraction*) f;
-(Fraction*) sub: (Fraction*) f;@end
FractionMath.m
#import "FractionMath.h"
@implementation Fraction (Math)
-(Fraction*) add: (Fraction*) f {
return [[Fraction alloc]initWithNumerator: numerator * [f denominator] +
denominator * [f numerator]
denominator:denominator * [f denominator]];
}
-(Fraction*) mul: (Fraction*) f {
return [[Fraction alloc]initWithNumerator: numerator * [f numerator]
denominator:denominator * [f denominator]];
}
-(Fraction*) div: (Fraction*) f {
return [[Fraction alloc]initWithNumerator: numerator * [f denominator]
denominator:
denominator * [f numerator]]; }
-(Fraction*) sub: (Fraction*) f {
return [[Fraction alloc]initWithNumerator: numerator * [f denominator] -
denominator * [f numerator]
denominator:denominator * [f denominator]];
}@end
main.m
-
8/7/2019 objective c here
26/45
#import
#import "Fraction.h"
#import "FractionMath.h"
int main( int argc, const char *argv[] ) {
// create a new instance Fraction *frac1 = [[Fraction alloc]initWithNumerator: 1 denominator: 3];
Fraction *frac2 = [[Fraction alloc]initWithNumerator: 2 denominator: 5];
Fraction *frac3 = [frac1 mul: frac2];
// print it
[frac1 print];
printf( " * " );
[frac2 print];
printf( " = " );
[frac3 print];
printf( "\n" );
// free memory
[frac1 release];
[frac2 release];
[frac3 release];
return 0;}
output
1/3 * 2/5 = 2/15
The magic here is the two @implementation and
@interface lines: @interface Fraction (Math) and
@implementation Fraction (Math).
There can only be one category with the same name.
Additional cateogies may be added on with different but unqiue
names.
Categories can't add instance variables. Categories are useful for creating private methods.
Since Objective-C has no notion of private/protected/public
methods like java does, one has to create categories that hide
such functionality. The way this is done is by moving the
private methods from your class's header (.h) file to the
implementation file (.m). The following is a very brief example
of what I mean.
MyClass.h
#import
@interface MyClass: NSObject
-
8/7/2019 objective c here
27/45
-(void) publicMethod;@end
MyClass.m
#import "MyClass.h" #import
@implementation MyClass
-(void) publicMethod {
printf( "public method\n" );
}
@end
// private methods
@interface MyClass (Private)
-(void) privateMethod;
@end
@implementation MyClass (Private)
-(void) privateMethod {
printf( "private method\n" );
}@end
main.m
#import "MyClass.h"
int main( int argc, const char *argv[] ) {
MyClass *obj = [[MyClass alloc] init];
// this compiles
[obj publicMethod];
// this throws errors when compiling
//[obj privateMethod];
// free memory
[obj release];
return 0;}
output
public method
o Posing
Posing is similar to categories, but with a twist. Itallows you to extend a class, and make your subclass pose (in
-
8/7/2019 objective c here
28/45
place of) the super class globally. For instance: Say you have
NSArrayChild that extends NSArray. If you made
NSArrayChild pose for NSArray all your code would begin
using the NSArrayChild instead of NSArray automatically.
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission FractionB.h
#import "Fraction.h"
@interface FractionB: Fraction
-(void) print;
@end
FractionB.m
#import "FractionB.h"
#import
@implementation FractionB
-(void) print {
printf( "(%i/%i)", numerator,denominator );
}@end
main.m
#import
#import "Fraction.h"
#import "FractionB.h"
int main( int argc, const char *argv[] ) {
Fraction *frac = [[Fraction alloc]initWithNumerator: 3 denominator: 10];
// print it
printf( "The fraction is: " );
[frac print];
printf( "\n" );
// make FractionB pose as Fraction
[FractionB poseAsClass: [Fraction class]];
Fraction *frac2 = [[Fraction alloc]initWithNumerator: 3 denominator: 10];
// print it
printf( "The fraction is: " );
[frac2 print];
printf( "\n" );
// free memory
[frac release]; [frac2 release];
-
8/7/2019 objective c here
29/45
return 0;}
output
The fraction is: 3/10The fraction is: (3/10)
The output from this program would print the first
fraction s 3/10. The second would output (3/10), which is
implemented by FractionB.
The method poseAsClass is part of NSObject. This
allows a subclass to pose as a superclass.
o Protocols A Protocol in Objective-C is identical in functionality to
an interface in Java, or a purely virtual class in C++.
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
Printing.h
@protocol Printing
-(void) print;@end
Fraction.h
#import
#import "Printing.h"
@interface Fraction: NSObject {
int numerator;
int denominator;
}
-(Fraction*) initWithNumerator: (int) ndenominator: (int) d;
-(void) setNumerator: (int) d;
-(void) setDenominator: (int) d;
-(void) setNumerator: (int) n andDenominator:(int) d;
-(int) numerator;
-(int) denominator;@end
Fraction.m
#import "Fraction.h"
#import
@implementation Fraction
-
8/7/2019 objective c here
30/45
-(Fraction*) initWithNumerator: (int) ndenominator: (int) d {
self = [super init];
if ( self ) {
[self setNumerator: n andDenominator:
d];
}
return self;
}
-(void) print {
printf( "%i/%i", numerator, denominator );
}
-(void) setNumerator: (int) n {
numerator = n;
}
-(void) setDenominator: (int) d {
denominator = d;
}
-(void) setNumerator: (int) n andDenominator:(int) d {
numerator = n;
denominator = d;
}
-(int) denominator {
return denominator;
}
-(int) numerator {
return numerator;
}
-(Fraction*) copyWithZone: (NSZone*) zone {
return [[Fraction allocWithZone: zone]initWithNumerator: numerator
denominator: denominator];
}@end
Complex.h
#import
#import "Printing.h"
@interface Complex: NSObject { double real;
-
8/7/2019 objective c here
31/45
double imaginary;
}
-(Complex*) initWithReal: (double) randImaginary: (double) i;
-(void) setReal: (double) r;
-(void) setImaginary: (double) i;
-(void) setReal: (double) r andImaginary:(double) i;
-(double) real;
-(double) imaginary;@end
Complex.m
#import "Complex.h"
#import
@implementation Complex
-(Complex*) initWithReal: (double) randImaginary: (double) i {
self = [super init];
if ( self ) {
[self setReal: r andImaginary: i];
}
return self;
}
-(void) setReal: (double) r {
real = r;
}
-(void) setImaginary: (double) i {
imaginary = i;
}
-(void) setReal: (double) r andImaginary:(double) i {
real = r; imaginary = i;
}
-(double) real {
return real;
}
-(double) imaginary {
return imaginary;
}
-(void) print {
-
8/7/2019 objective c here
32/45
printf( "%_f + %_fi", real, imaginary );
}@end
main.m
#import
#import "Fraction.h"
#import "Complex.h"
int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc]initWithNumerator: 3 denominator: 10];
Complex *comp = [[Complex alloc]initWithReal: 5 andImaginary: 15];
id printable;
id copyPrintable;
// print it
printable = frac;
printf( "The fraction is: " );
[printable print];
printf( "\n" );
// print complex
printable = comp;
printf( "The complex number is: " );
[printable print];
printf( "\n" );
// this compiles because Fraction comformsto both Printing and NSCopyable
copyPrintable = frac;
// this doesn't compile because Complexonly conforms to Printing
//copyPrintable = comp;
// test conformance
// true
if ( [frac conformsToProtocol:@protocol( NSCopying )] == YES ) {
printf( "Fraction conforms toNSCopying\n" );
}
// false
if ( [comp conformsToProtocol:@protocol( NSCopying )] == YES ) {
printf( "Complex conforms toNSCopying\n" );
-
8/7/2019 objective c here
33/45
}
// free memory
[frac release];
[comp release];
return 0;}
output
The fraction is: 3/10
The complex number is: 5.000000 + 15.000000iFraction conforms to NSCopying
The protocol specification is quite simple. it is basically
@protocol ProtocolName (methods you must implement)@end.
To conform to a protocol, you put the protocols you're
conforming to in 's, and comma separate them. Example:
@interface SomeClass
The methods that the protocol requires to be
implemented are not required to be in the list of methods for the
header file. As you can see, Complex.h doesn't have a
definition for -(void) print, but it still implements it since it
conforms to the protocol.
One unique aspect of Objective-C's interface system is
how you specify types. Rather than specifying it like Java orC++ as: Printing *someVar = ( Printing * ) frac; for example,
you use the id type with a restricted protocol: id var
= frac; This allows you to dynamically specify a type that
requires multiple protocols, all with one variable. Such as: id
var = frac;
Much like using @selector for testing an object's
inheritance, you can use @protocol to test for conformance of
interfaces. [object conformsToProtocol:
@protocol( SomeProtocol )] returns a BOOL if the object
conforms to that protocol. This works the same for classes as
well: [SomeClass conformsToProtocol:@protocol( SomeProtocol )].
Memory Managemento Up until now I've kind of dodged memory management in
Objective-C. Sure you can call dealloc on an object, but what happens
if the object contains pointers to other objects? One has to be
concerned about freeing the memory of those objects as well. Also
how does the Foundation framework manage memory when you create
classes from it? This will all be explained.
o Note: everything up until this point has been properly memory
managed, incase you're wondering.
-
8/7/2019 objective c here
34/45
o Retain and Release Retain and release are two methods inherited from any
object that has NSObject as a parent. Each object has an
internal counter that can be used to keep track of the number
references an object has. So if you have 3 referneces, you don't
want to dealloc yourself. However once you reach 0, you
should dealloc yourself. [object retain] increments the counter
by 1 (which starts at 1) and [object release] decrements it by 1.
If the [object release] invocation causes the count to reach 0,
dealloc is then called.
Fraction.m
...
-(void) dealloc {
printf( "Deallocing fraction\n" );
[super dealloc];
}
...
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
main.m
#import "Fraction.h"
#import
int main( int argc, const char *argv[] ) {
Fraction *frac1 = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
// print current counts
printf( "Fraction 1 retain count: %i\n",[frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n",[frac2 retainCount] );
// increment them
[frac1 retain]; // 2
[frac1 retain]; // 3
[frac2 retain]; // 2
// print current counts
printf( "Fraction 1 retain count: %i\n",[frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n",[frac2 retainCount] );
// decrement
[frac1 release]; // 2
[frac2 release]; // 1
// print current counts
-
8/7/2019 objective c here
35/45
printf( "Fraction 1 retain count: %i\n",[frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n",[frac2 retainCount] );
// release them until they deallocthemselves
[frac1 release]; // 1
[frac1 release]; // 0
[frac2 release]; // 0}
output
Fraction 1 retain count: 1
Fraction 2 retain count: 1
Fraction 1 retain count: 3
Fraction 2 retain count: 2 Fraction 1 retain count: 2
Fraction 2 retain count: 1
Deallocing fractionDeallocing fraction
The retain calls increment the counter. The release calls
decrement it. One can get the count as an int by calling [obj
retainCount]. Once the retainCount reaches 0, both objects
dealloc themselves and you can see this when both print out
"Deallocing fraction."
o Dealloc When your object contains other objects, you must free
them whenever you yourself dealloc. One of the nice
advantages to Objective-C is you can pass messages to nil, so
there isn't a lot of error checking to release an object.
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
AddressCard.h
#import
#import
@interface AddressCard: NSObject {
NSString *first;
NSString *last;
NSString *email;
}
-(AddressCard*) initWithFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e;
-(NSString*) first;
-(NSString*) last; -(NSString*) email;
-
8/7/2019 objective c here
36/45
-(void) setFirst: (NSString*) f;
-(void) setLast: (NSString*) l;
-(void) setEmail: (NSString*) e;
-(void) setFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e; -(void) setFirst: (NSString*) f last:(NSString*) l;
-(void) print;@end
AddressCard.m
#import "AddressCard.h"
#import
@implementation AddressCard
-(AddressCard*) initWithFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e {
self = [super init];
if ( self ) {
[self setFirst: f last: l email: e];
}
return self;
}
-(NSString*) first {
return first;
}
-(NSString*) last {
return last;
}
-(NSString*) email {
return email;
}
-(void) setFirst: (NSString*) f {
[f retain];
[first release];
first = f;
}
-(void) setLast: (NSString*) l {
[l retain];
[last release];
last = l;
}
-
8/7/2019 objective c here
37/45
-(void) setEmail: (NSString*) e {
[e retain];
[email release];
email = e;
}
-(void) setFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e {
[self setFirst: f];
[self setLast: l];
[self setEmail: e];
}
-(void) setFirst: (NSString*) f last:
(NSString*) l { [self setFirst: f];
[self setLast: l];
}
-(void) print {
printf( "%s %s ", [first cString],
[lastcString],
[emailcString] );
}
-(void) dealloc {
[first release];
[last release];
[email release];
[super dealloc];
}@end
main.m
#import "AddressCard.h"
#import
#import
int main( int argc, const char *argv[] ) {
NSString *first =[[NSString alloc]initWithCString: "Tom"];
NSString *last = [[NSString alloc]initWithCString: "Jones"];
NSString *email = [[NSString alloc]initWithCString: "[email protected]"];
AddressCard *tom = [[AddressCard alloc]initWithFirst: first
-
8/7/2019 objective c here
38/45
last: last
email: email];
// we're done with the strings, so we mustdealloc them
[first release];
[last release];
[email release];
// print to show the retain count
printf( "Retain count: %i\n", [[tom first]retainCount] );
[tom print];
printf( "\n" );
// free memory [tom release];
return 0;}
output
Retain count: 1Tom Jones
This example shows not only how to make a deallocmethod, as shown in AddressCard.m, but one way to do
member variables.
The order of the 3 operations in each set method is very
important. Lets say you'return passing a parameter of yourself
to one of your methods (a bit of an odd example, but this can
happen). If you release first, THEN retain you will destruct
yourself! That's why you should always 1) retain 2) release 3)
set the value.
Normally one wouldn't initialize variables with C
strings because they don't support unicode. The next example,
with NSAutoreleasePool shows the proper way to do stringsand initializing.
This is just one way of handling member variable
memory management. One way to handle this is to create
copies inside your set methods.
o Autorelease Pool When you want to start doing more programming using
NSString and other Foundation framework classes you need a
more flexible system. This system is using Autorelease pools.
When developing Mac Cocoa applications, the auto
release pool is setup automatically for you.
-
8/7/2019 objective c here
39/45
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
main.m
#import
#import
#import
int main( int argc, const char *argv[] ) {
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
NSString *str1 = @"constant string";
NSString *str2 = [NSStringstringWithString: @"string managed by the pool"];
NSString *str3 = [[NSString alloc]initWithString: @"self managed string"];
// print the strings
printf( "%s retain count: %x\n", [str1cString], [str1 retainCount] );
printf( "%s retain count: %x\n", [str2cString], [str2 retainCount] );
printf( "%s retain count: %x\n", [str3cString], [str3 retainCount] );
// free memory
[str3 release];
// free pool
[pool release]; return 0;}
output
constant string retain count: ffffffff
string managed by the pool retain count: 1self managed string retain count: 1
If you run this you'll notice a few things. One is that the
retainCount of str1 is ffffffff.
The other is, I only release str3, yet this program is
memory management perfect. The reason is the first constant
string is added to the autorelease pool automatically. The other
string is made using stringWithString. This method creates a
string that is owned by NSString class, which also puts it in the
auto release pool.
It's important to remember, for proper memory
management, that convience methods like [NSString
stringWithString: @"String"] use autorelease pools, but alloc
methods like [[NSString alloc] initWithString: @"String"] do
not use autorelease pools for managing memory.
-
8/7/2019 objective c here
40/45
There are two ways to manage memory in Objective-C:
1) retain and release or 2) retain and release/autorelease.
For each retain, there must be one release OR one
autorelease.
The following example shows what I mean by this
Based on an example in "Programming in Objective-C,"Copyright 2004 by Sams Publishing. Used with permission
Fraction.h
...
+(Fraction*) fractionWithNumerator: (int) ndenominator: (int) d;
...
Fraction.m
...
+(Fraction*) fractionWithNumerator: (int) n
denominator: (int) d { Fraction *ret = [[Fraction alloc]initWithNumerator: n denominator: d];
[ret autorelease];
return ret;
}...
main.m
#import
#import "Fraction.h"
#import
int main( int argc, const char *argv[] ) {
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
Fraction *frac1 = [FractionfractionWithNumerator: 2 denominator: 5];
Fraction *frac2 = [FractionfractionWithNumerator: 1 denominator: 3];
// print frac 1
printf( "Fraction 1: " ); [frac1 print];
printf( "\n" );
// print frac 2
printf( "Fraction 2: " );
[frac2 print];
printf( "\n" );
// this causes a segmentation fault
//[frac1 release];
// release the pool and all objects in it
-
8/7/2019 objective c here
41/45
[pool release];
return 0;}
output
Fraction 1: 2/5Fraction 2: 1/3
In this example, the method is a class level method.
After the object is created, autorelease is called on it. Inside the
body of the main method, I never call release on the object.
The reason this works is because: for every retain, one
release or autorelease must be called. The object's retain count
starts out as 1, and I called autorelease on it once. This means 1
- 1 = 0. Once the autorelease pool is released, it counts the
autorelease calls on all objects and decrements them with [objrelease] with the same number of times autorelease was called
per object.
As the comment says, uncommenting that line causes a
segment fault. Since autorelease was already called on the
object, calling release on it, and then releasing the autorelease
pool would attempt to call dealloc on an object that is nil,
which is not valid. The end math is 1 (creation) - 1 (release) - 1
(autorelease) = -1.
Auto release pools can be dynamically created for large
amounts of temporary objects. All one must do is create a pool,
perform any large chunk of code that creates lots of temporary
objects, then release the pool. As you may wonder, it this
means it is possible to have more than one auto release pool at
a time.
Foundation framework classeso The Foundation framework is similar to C++'s Standard
Template Library. Although since Objective-C has real dynamic types,
the horrible cludge that is C++'s templating is not necessary. This
framework contains collections, networking, threading, and much
more.o NSArray
Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission
main.m
#import
#import
#import
#import
#import
void print( NSArray *array ) {
-
8/7/2019 objective c here
42/45
NSEnumerator *enumerator = [arrayobjectEnumerator];
id obj;
while ( obj = [enumerator nextObject] ) {
printf( "%s\n", [[obj description]
cString] );
}
}
int main( int argc, const char *argv[] ) {
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
NSArray *arr = [[NSArray alloc]initWithObjects:
@"Me", @"Myself", @"I",nil];
NSMutableArray *mutable = [[NSMutableArrayalloc] init];
// enumerate over items
printf( "----static array\n" );
print( arr );
// add stuff
[mutable addObject: @"One"];
[mutable addObject: @"Two"];
[mutable addObjectsFromArray: arr];
[mutable addObject: @"Three"];
// print em
printf( "----mutable array\n" );
print( mutable );
// sort then print
printf( "----sorted mutable array\n" );
[mutable sortUsingSelector:@selector( caseInsensitiveCompare: )];
print( mutable );
// free memory [arr release];
[mutable release];
[pool release];
return 0;}
output
----static array
Me
Myself
-
8/7/2019 objective c here
43/45
I
----mutable array
One
Two
Me
Myself I
Three
----sorted mutable array
I
Me
Myself
One
ThreeTwo
There are two kinds of arrays (and of usually most dataoriented Foundation classes) NSArray and NSMutableArray.
As the name suggests, Mutable is changable, NSArray then is
not. This means you can make an NSArray but once you have
you can't change the length.
You initialize an array via the constructor using Obj,
Obj, Obj, ..., nil. The nil is an ending delimiter.
The sorting shows how to sort an object using a
selector. The selector tells the array to sort using NSString's
case insensitive compare. If your object has several sort
methods, you can choose anyone you want using this selector.
In the print method, I used the method description. This
is similar to Java's toString. It returns an NSString
representation of an object.
NSEnumerator is similar to Java's enumerator system.
The reason why while ( obj = [array objectEnumerator] ) works
is because objectEnumerator returns nil on the last object. Since
in C nil is usually 0, this is the same as false. ( ( obj = [array
objectEnumerator] ) != nil ) might be preferable
o NSDictionary Based on an example in "Programming in Objective-C,"
Copyright 2004 by Sams Publishing. Used with permission main.m
#import
#import
#import
#import
#import
-
8/7/2019 objective c here
44/45
while ( key = [enumerator nextObject] ) {
printf( "%s => %s\n",
[[key description] cString],
[[[map objectForKey: key]
description] cString] ); }
}
int main( int argc, const char *argv[] ) {
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
NSDictionary *dictionary = [[NSDictionaryalloc] initWithObjectsAndKeys:
@"one", [NSNumber numberWithInt: 1],
@"two", [NSNumber numberWithInt: 2],
@"three", [NSNumber numberWithInt: 3],
nil];
NSMutableDictionary *mutable =[[NSMutableDictionary alloc] init];
// print dictionary
printf( "----static dictionary\n" );
print( dictionary );
// add objects
[mutable setObject: @"Tom" forKey:@"[email protected]"];
[mutable setObject: @"Bob" forKey:@"[email protected]" ];
// print mutable dictionary
printf( "----mutable dictionary\n" );
print( mutable );
// free memory
[dictionary release];
[mutable release];
[pool release];
return 0;}
output
----static dictionary
1 => one
2 => two
3 => three
----mutable dictionary
[email protected] => [email protected] => Tom
-
8/7/2019 objective c here
45/45
Pros and Conso Pros
Cateogies
Posing
Dynamic typing
Pointer counting
Flexible message passing
Not an overly complex extention to C
Can interface with C++ via Objective-C++
o Cons No namespaces
No operator overloading (this is often considered a Pro
though, but operator overloading used properly can reduce
code clutter)
Still some cruft in language, although no more than C++
More Informationo Programming in Objective-C 2.0 (2nd Edition)
o Programming in Objective-C
o Learning Cocoa with Objective-C
o Cocoa Programming for Mac OS X
o Object-Oriented Programming and the Objective-C Language
o GNUstep mini tutorials
Last modified: April 13, 2004.
http://www.amazon.com/gp/product/0321566157?ie=UTF8&tag=tristanshomep-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0321566157http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2FProgramming-Objective-C-Stephen-Kochan%2Fdp%2F0672325861%2Fsr%3D8-1%2Fqid%3D1159892836%2Fref%3Dpd_bbs_1%3Fie%3DUTF8%26s%3Dbooks&tag=tristanshomep-20&linkCode=ur2&camp=1789&creative=9325http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2Fexec%2Fobidos%2Ftg%2Fdetail%2F-%2F0596003013%2Fqid%3D1080660707%2Fsr%3D8-1%2Fref%3Dsr_8_xs_ap_i1_xgl14%3Fv%3Dglance%26s%3Dbooks%26n%3D507846&tag=tristanshomep-20&linkCode=ur2&camp=1789&creative=9325http://www.amazon.com/exec/obidos/ASIN/0321503619/tristanshomep-20http://www.toodarkpark.org/computers/objc/http://www.gnustep.it/nicola/Tutorials/index.htmlhttp://www.amazon.com/gp/product/0321566157?ie=UTF8&tag=tristanshomep-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0321566157http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2FProgramming-Objective-C-Stephen-Kochan%2Fdp%2F0672325861%2Fsr%3D8-1%2Fqid%3D1159892836%2Fref%3Dpd_bbs_1%3Fie%3DUTF8%26s%3Dbooks&tag=tristanshomep-20&linkCode=ur2&camp=1789&creative=9325http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2Fexec%2Fobidos%2Ftg%2Fdetail%2F-%2F0596003013%2Fqid%3D1080660707%2Fsr%3D8-1%2Fref%3Dsr_8_xs_ap_i1_xgl14%3Fv%3Dglance%26s%3Dbooks%26n%3D507846&tag=tristanshomep-20&linkCode=ur2&camp=1789&creative=9325http://www.amazon.com/exec/obidos/ASIN/0321503619/tristanshomep-20http://www.toodarkpark.org/computers/objc/http://www.gnustep.it/nicola/Tutorials/index.html