2011年4月1日金曜日

NSAutoreleasePoolとNSValue

さっき、ハマっていたのですが、あまりに初心者的なハマりだったので、
テストケースとしてコミットするのをやめ、ブログにメモとして残すことにしました (笑)

[NSValue valueWithCGPoint:CGPointMake(10, 10)]

[NSDate date]
のようなallocしてなくてinit***から始まらないものは、Autoreleaseで解放されちゃうので注意 ということ。

NSAutoreleasePoolなんて、つかってねーよ! という場合でも使用ライブラリによっては実は走っていた!なんて事があるのでちゃんとしとかなくてはイケマセン。

もれちゃうと、EXEC_BAD_ACCESS がでちゃったり、メモリーリークしちゃったり、このタイミングではOKなのに、その後のタイミングではNGだ ... と私のようにハマりますw

以下、簡潔にしたテストコード。
- (void)testNSValue {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSValue *nsValue = [NSValue valueWithCGPoint:CGPointMake(10, 10)];
    [nsValue retain];
    STAssertEquals((int) [nsValue retainCount], 2, @"retain したので2つになっているはず");
    
    NSObject *nsObject = [[NSObject alloc] init];
    [nsObject retain];
    STAssertEquals((int) [nsObject retainCount], 2, @"retain したので2つになっているはず");
    
    NSDate *nsDate = [NSDate date];
    [nsDate retain];
    STAssertEquals((int) [nsDate retainCount], 2, @"retain したので2つになっているはず");

    [pool release]; // autorelease を release
    
    STAssertEquals((int) [nsValue retainCount], 1, @"autorelease により1になる");
    STAssertEquals((int) [nsObject retainCount], 2, @"NSObjectはallocしてるのでautoreleaseしても2のまま");
    STAssertEquals((int) [nsDate retainCount], 1, @"autorelease により1になる");
}
• • •