objective c here

download objective c here

of 45

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