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.

alloc 하면 1, retain 하면 +1, release -1, 0 되면 자동 dealloc 콜.
주소만 참조하는 걸로는 +1 안됨.

Fraction.h
#import <Foundation/NSObject.h>

@interface Fraction: NSObject {
    int numerator;
    int denominator;
}

-(Fraction*) initWithNumerator: (int) n andDenominator: (int) d;
-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
-(void) print;
-(void) setNumerator: (int) n;
-(void) setNumerator: (int) n andDenominator: (int) d;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end


Fraction.m
#import "Fraction.h"
#import <stdio.h>

@implementation Fraction
-(Fraction*) initWithNumerator: (int) n andDenominator: (int) d {
    self = [super init];
   
    if(self) {
        [self setNumerator: n andDenominator: d];
    }
   
    return self;
}

-(Fraction*) initWithNumerator: (int) n denominator: (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) setNumerator: (int) n andDenominator: (int) d {
    numerator = n;
    denominator = d;
}

-(void) setDenominator: (int) d {
    denominator = d;
}

-(int) denominator {
    return denominator;
}

-(int) numerator {
    return numerator;
}

// dealloc
-(void) dealloc {
    printf( "Deallocing fraction\n" );
    [super dealloc];
}
@end


main.m
#import "Fraction.h"
#import <stdio.h>

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
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );
   
    // release them until they dealloc themselves
    [frac1 release]; // 1
    [frac1 release]; // 0
    [frac2 release]; // 0
   
    // 다른 변수가 참조하면?
    Fraction *frac3 = [[Fraction alloc] init];
    printf( "Fraction 3 retain count: %i\n", [frac3 retainCount] );
    [frac3 retain]; // 2
    printf( "Fraction 3 retain count: %i\n", [frac3 retainCount] );
    Fraction* frac4 = frac3; // 참조해도 retainCount가 늘어나지는 않음.
    printf( "Fraction 3 retain count: %i\n", [frac3 retainCount] );
    [frac3 release]; // 1
    printf( "Fraction 3 retain count: %i\n", [frac3 retainCount] ); // 1
    printf( "Fraction 4 retain count: %i\n", [frac4 retainCount] ); // 1
    system("PAUSE");
    [frac4 release]; // 0 - frac3 또는 frac4 둘 중 하나만 release 해도 retainCount가 감소. 같은 주소이므로 당연.
    system("PAUSE"); // retainCount가 0이 되었으므로 dealloc 됨.
    printf( "Fraction 3 retain count: %i\n", [frac3 retainCount] ); // dealloc된 frac3을 참조하려하므로 런타임 예외 발생
//    system("PAUSE");
//    printf( "Fraction 4 retain count: %i\n", [frac4 retainCount] );
    system("PAUSE");
    [frac3 release]; // 0
   
    system("PAUSE");
    return 0;
}


결과
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 fraction
Deallocing fraction
Fraction 3 retain count: 1
Fraction 3 retain count: 2
Fraction 3 retain count: 2
Fraction 3 retain count: 1
Fraction 4 retain count: 1
계속하려면 아무 키나 누르십시오 . . .
Deallocing 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."

'프로그래밍 > iPhone Dev' 카테고리의 다른 글

[Objective C] 13 Autorelease Pool  (1) 2009.11.13
[Objective C] 12 Dealloc  (1) 2009.11.12
[Objective C] 10 Protocols  (0) 2009.11.11
[Objective C] 09 Posing  (0) 2009.11.10
[Objective C] 08 Categories  (0) 2009.11.09