[Objective C] Category

프로그래밍/iPhone Dev 2009. 11. 18. 08:59 Posted by galad
Category

- Objective-C를 보자. B가 ClassC를 확장하는데 Category를 사용했고 그 카테고리 이름을 CategoryB라고 지었다고 하자. 그리고 A는 ClassC를 확장하는데 CategoryA라고 이름을 지었다고 하자. 수평적 확장으므로 레이어가 ClassA에서 두개밖에 없을 뿐 아니라, B가 추가한 부분이 A가 확장한 ClassC 클래스엔 들어 있지 않다!
아.. 얼마나 좋은가? 멋지지 않은가?
 -> Category를 쓰면 수평적 확장이 가능하단 얘기.
 즉, 
                  ClassA
                  I         I
       CategoryA    CategoryB

- 카테고리 안에 정의된 method는 ClassC의 원래 method의 이름과 같은게 있을 수도 있다. 이때는 기존의 것을 override하는 것이 된다!
하지만 이때는 상속 받은 것과 달리 기존의 것을 새로운 것이 invocation을 할 수가 없다.
그냥 완전히 새걸로 바꾸는 것이다. 이것은 장점이기도 하고 경우에 따라 단점이기도 하다.
 -> 같은 이름의 method로 override하면 완전히 대체하는 것이 된다...

- 같은 클래스에 대한 다른 카테고리에 있는 것을 override하는 것은 안된다.
 ->당연하겠지. 수평적 확장이니까.

- 기존의 클래스에 변수를 추가해야 할 경우엔?
 -> 상속을 써야함... Category는 method만 추가 가능.

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

[Objective C] Protocol  (0) 2009.11.20
[Objective C] Root Class  (0) 2009.11.20
[Objective C] 15 NSDictionary  (0) 2009.11.13
[Objective C] 14 NSArray  (0) 2009.11.13
[Objective C] 13 Autorelease Pool  (1) 2009.11.13

[Objective C] 15 NSDictionary

프로그래밍/iPhone Dev 2009. 11. 13. 15:44 Posted by galad
NSDictionary
java의 map.
NSMutableDictionary 도 소트는 안되는 듯.

main.m
#import <Foundation/NSString.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/Foundation.h>
#import <stdio.h>

void print( NSDictionary *map ) {
    NSEnumerator *enumerator = [map keyEnumerator];
    id key;

    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 = [[NSDictionary alloc] 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: @"tom@jones.com"];
    [mutable setObject: @"Bob" forKey: @"bob@dole.com" ];

    // print mutable dictionary
    printf( "----mutable dictionary\n" );
    print( mutable );

    // free memory
    [dictionary release];
    [mutable release];
    [pool release];

    system("PAUSE");
    return 0;
}


결과
----static dictionary
1 => one
3 => three
2 => two
----mutable dictionary
bob@dole.com => Bob
tom@jones.com => Tom
계속하려면 아무 키나 누르십시오 . . .

- Foundation Framework classes의 references만 찾아봐도 양이 상당할 듯...ㅎㄷㄷ

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

[Objective C] Root Class  (0) 2009.11.20
[Objective C] Category  (0) 2009.11.18
[Objective C] 14 NSArray  (0) 2009.11.13
[Objective C] 13 Autorelease Pool  (1) 2009.11.13
[Objective C] 12 Dealloc  (1) 2009.11.12

[Objective C] 14 NSArray

프로그래밍/iPhone Dev 2009. 11. 13. 15:36 Posted by galad
Foundation framework classes
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.

NSArray

main.m
#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSEnumerator.h>
#import <stdio.h>

void print( NSArray *array ) {
    NSEnumerator *enumerator = [array objectEnumerator];
    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 = [[NSMutableArray alloc] 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];

    system("PAUSE");
    return 0;
}


결과
----static array
Me
Myself
I
----mutable array
One
Two
Me
Myself
I
Three
----sorted mutable array
I
Me
Myself
One
Three
Two
계속하려면 아무 키나 누르십시오 . . .

- There are two kinds of arrays (and of usually most data oriented 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.
  NSArray는 길이 변경 불가.
- You initialize an array via the constructor using Obj, Obj, Obj, ..., nil. The nil is an ending delimiter.
  nil이 끝을 의미. 반드시 필요하겠군..
- In the print method, I used the method description. This is similar to Java's toString. It returns an NSString representation of an object.
  description 메소드가 NSString을 반환하고, cString이 그 내용을 반환.
- 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.

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

[Objective C] Category  (0) 2009.11.18
[Objective C] 15 NSDictionary  (0) 2009.11.13
[Objective C] 13 Autorelease Pool  (1) 2009.11.13
[Objective C] 12 Dealloc  (1) 2009.11.12
[Objective C] 11 Retain and Release  (0) 2009.11.12
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.

main.m
#import <Foundation/NSString.h>
#import <Foundation/NSAutoreleasePool.h>
#import <stdio.h>

int main( int argc, const char *argv[] ) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *str1 = @"constant string";
    NSString *str2 = [NSString stringWithString: @"string managed by the pool"];
    NSString *str3 = [[NSString alloc] initWithString: @"self managed string"];

    // print the strings
    printf( "%s retain count: %x\n", [str1 cString], [str1 retainCount] );
    printf( "%s retain count: %x\n", [str2 cString], [str2 retainCount] );
    printf( "%s retain count: %x\n", [str3 cString], [str3 retainCount] );

    // free memory
    [str3 release]; // alloc으로 생성한 것만 release. 나머지는 AutoreleasePool에서 처리

    // free pool
    [pool release];
   
    system("PAUSE");
    return 0;
}


결과
constant string retain count: 40387657
string managed by the pool retain count: 1
self 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.
  str3 하나만 release 했지만 이 프로그램의 메모리 관리는 완벽하다는 군. str1, str2 생성 시의 방법이 string을 알아서 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.
  stringWithString 같이 auto release pool을 사용하는 메소드를 쓰는 것이 편하다.
- 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.


Auto Release Pool 사용 예제

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;
+(Fraction*) fractionWithNumerator: (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;
}

// Auto Release Pool
+(Fraction*) fractionWithNumerator: (int) n denominator: (int) d {
    printf( "Create object using auto release pool.\n");
   
    Fraction *ret = [[Fraction alloc] initWithNumerator: n denominator: d];
    [ret autorelease]; // retain count -1: 이후 auto release pool을 release 할 경우 자동 처리됨.

    return ret;
}

-(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 : %i\n", numerator );
}
@end


main.m
#import <Foundation/NSAutoreleasePool.h>
#import "Fraction.h"
#import <stdio.h>

int main( int argc, const char *argv[] ) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    Fraction *frac1 = [Fraction fractionWithNumerator: 2 denominator: 5];
    Fraction *frac2 = [Fraction fractionWithNumerator: 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
    printf( "Auto Release Pool release.\n" );
    [pool release]; // 이 안에 담긴 object들이 모두 release 되면서 dealloc 됨.
   
    system("PAUSE");
    return 0;
}


결과
Create object using auto release pool.
Create object using auto release pool.
Fraction 1: 2/5
Fraction 2: 1/3
Auto Release Pool release.
Deallocing fraction : 2
Deallocing fraction : 1
계속하려면 아무 키나 누르십시오 . . .

- 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 [obj release] 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.
  autorelease 하면 -1 되므로 생성 후 다시 release 하면 segmentation fault.
- 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.
 Auto release pool도 동적으로 생성할 수 있다 -> 여러 개의 풀을 생성할 수 있다.

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

[Objective C] 15 NSDictionary  (0) 2009.11.13
[Objective C] 14 NSArray  (0) 2009.11.13
[Objective C] 12 Dealloc  (1) 2009.11.12
[Objective C] 11 Retain and Release  (0) 2009.11.12
[Objective C] 10 Protocols  (0) 2009.11.11

[Objective C] 12 Dealloc

프로그래밍/iPhone Dev 2009. 11. 12. 17:37 Posted by galad
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.
객체가 다른 객체를 갖고 있으면, 객체가 dealloc될 때 포함하고 있던 다른 것도 free 시켜야함. Objective-C의 좋은 장점은 메시지를 nil에게 보낼 수 있기에 객체 release 시에 많은 에러 체킹이 없다는 점이라는 군.

아래 소스는 원 소스를 살짝 변경해서 retain/release를 이용해 인스턴스 변수의 dealloc이 자동으로 일어나는 것을 잘 보여줌.
원 소스는 파일 첨부

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 : %i\n", numerator );
}
@end


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

@interface AddressCard: NSObject {
    Fraction *first;
    Fraction *last;
    Fraction *email;
}

-(AddressCard*) initWithFirst: (Fraction*) f
                last: (Fraction*) l
                email: (Fraction*) e;
-(Fraction*) first;
-(Fraction*) last;
-(Fraction*) email;
-(void) setFirst: (Fraction*) f;
-(void) setLast: (Fraction*) l;
-(void) setEmail: (Fraction*) e;
-(void) setFirst: (Fraction*) f
        last: (Fraction*) l
        email: (Fraction*) e;
-(void) setFirst: (Fraction*) f last: (Fraction*) l;
-(void) print;
@end


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

@implementation AddressCard
-(AddressCard*) initWithFirst: (Fraction*) f
                last: (Fraction*) l
                email: (Fraction*) e {
    self = [super init];

    if ( self ) {
        [self setFirst: f last: l email: e];
    }

    return self;
}

-(Fraction*) first {
    return first;
}

-(Fraction*) last {
    return last;
}

-(Fraction*) email {
    return email;
}

-(void) setFirst: (Fraction*) f {
    [f retain]; // 새로 받는 것을 +1
    [first release]; // 기존 것을 -1. 이때 dealloc 됨
    first = f;
}

-(void) setLast: (Fraction*) l {
    [l retain];
    [last release];
    last = l;
}

-(void) setEmail: (Fraction*) e {
    [e retain];
    [email release];
    email = e;
}

-(void) setFirst: (Fraction*) f
        last: (Fraction*) l
        email: (Fraction*) e {
    [self setFirst: f];
    [self setLast: l];
    [self setEmail: e];
}

-(void) setFirst: (Fraction*) f last: (Fraction*) l {
    [self setFirst: f];
    [self setLast: l];
}

-(void) print {
    printf( "%i (%i) <%i>", [first numerator],
                                [last numerator],
                                [email numerator] );
}

// AddressCard가 dealloc될 때, 기존에 남아있던 클래스 변수들의 retain값을 모두 -1해서 dealloc 시킴
-(void) dealloc {
    [first release];
    [last release];
    [email release];

    [super dealloc];
}
@end


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

int main( int argc, const char *argv[] ) {
    Fraction *first =[[Fraction alloc] initWithNumerator: 1 andDenominator: 10];
    Fraction *last = [[Fraction alloc] initWithNumerator: 2 andDenominator: 20];
    Fraction *email = [[Fraction alloc] initWithNumerator: 3 andDenominator: 30];
    AddressCard *tom = [[AddressCard alloc] initWithFirst: first
                                            last: last
                                            email: email];

    // we're done with the strings, so we must dealloc them
    // 사실 여기서 dealloc되지는 않고 retainCount가 -1됨.
    printf( "Retain count. Before release - first: %i\n", [first retainCount] ); // AddressCard 생성 시에 +1됨
    [first release];
    [last release];
    [email release];
    printf( "Retain count. After release  - first: %i\n", [first retainCount] );
    system("PAUSE");

    // print to show the retain count
    printf( "Retain count: %i\n", [[tom first] retainCount] );
    [tom print];
    printf( "\n" );
    system("PAUSE");
   
    Fraction *first2 =[[Fraction alloc] initWithNumerator: 5 andDenominator: 50];
    printf( "Set first again\n" );
    [tom setFirst: first2]; // setFirst할 때 first2를 retain. first2 = 2. 그리고 tom에 있는 기존 first를 -1해서 dealloc시킴.
   
    [first2 release]; // 위와 마찬가지로 사용하지 않으므로 must delloc. first2 = 1.
    // setFirst 시에 retain했으므로 release해도 아직 1. delloac되지는 않았음
   
    printf( "Retain count: %i\n", [[tom first] retainCount] );
    [tom print];
    printf( "\n" );
   
    // free memory
    [tom release];

    system("PAUSE");
    return 0;
}


결과
Retain count. Before release - first: 2
Retain count. After release  - first: 1
계속하려면 아무 키나 누르십시오 . . .
Retain count: 1
1 (2) <3>
계속하려면 아무 키나 누르십시오 . . .
Set first again
Deallocing fraction : 1
Retain count: 1
5 (2) <3>
Deallocing fraction : 5
Deallocing fraction : 2
Deallocing fraction : 3
계속하려면 아무 키나 누르십시오 . . .

- 위의 Deallocing fraction : X 메시지에서 보다시피 setXXX 하면서 retain/release 하는 것과 dealloc될 때 release 하는 것으로
포함하고 있는 객체를 자동으로 dealloc 시킬 수 있음.
- This example shows not only how to make a dealloc method, as shown in AddressCard.m, but one way to do member variables.
 dealloc 메소드 사용법 뿐 아니라, 멤버 변수 취급 방식에 대한 예제임.
- 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.
 set 시에는 반드시 매개변수 retain 후에, 멤버변수 release 할 것.
 만약 넘겨 받은 매개변수를 return하는 경우에 release를 먼저하면 그 때 매개변수가 dealloc되어버린다.
 위의 예제에선 상관없으나 습관의 문제일 듯. 로직상으로도 먼저 retain하는 것이 옳고...
- 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 strings and 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.
  이건 멤버변수 메모리 관리의 한 방법. 다른 방법은 set 메소드에서 카피를 생성하는 방법.

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

[Objective C] 14 NSArray  (0) 2009.11.13
[Objective C] 13 Autorelease Pool  (1) 2009.11.13
[Objective C] 11 Retain and Release  (0) 2009.11.12
[Objective C] 10 Protocols  (0) 2009.11.11
[Objective C] 09 Posing  (0) 2009.11.10
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

Developer Career Path

사는 얘기 2009. 11. 11. 17:49 Posted by galad
출처: http://init.egloos.com/1541498

어디로 가야 하나....