アプリ開発をしていてメモリリークが頻発していてアプリが落ちる要因となっており開発が終わってからObjective-Cについて改めて見なおしてみた。
Objective-Cは参照カウンタによるメモリ管理をしていてretainで+1、releaseで-1され参照が無くなった後、deallocが呼ばれるという認識はあった。
しかしinitしても参照カウンタが+1ではなく違う値になったりとしていたのでNSStringで様々な生成方法をやりまとめてみた。


// TestObject.h
@interface TestObject : NSObject {
    NSString *m_strText;
}
@property (nonatomic, readwrite, retain) NSString *strText;
@end

// TestObject.m
@implementation TestObject
@synthesize strText = m_strText;

- (id)init {
    self = [super init];
    if (self) {
        /*
         * m_strTextの生成処理.
         */
        NSLog(@"init [m_strText retainCount] = %d", [m_strText retainCount]);
    }
}
- (void)dealloc {
    NSLog(@"dealloc1 [m_strText retainCount] = %d", [m_strText retainCount]);
    [m_strText release];
     NSLog(@"dealloc2 [m_strText retainCount] = %d", [m_strText retainCount]);
    [super dealloc];
}
@end

// 【パターン1:[[alloc] initWithString]】
m_strText = [[NSString alloc] initWithString:@"sample"];
NSLog(init)     -> 2147483647
NSLog(dealloc1) -> 2147483647
NSLog(dealloc2) -> 2147483647

// 【パターン2:[[alloc] initWithFormat]】
m_strText = [[NSString alloc] initWithFormat:@"%@", @"sample"];
NSLog(init)     -> 1
NSLog(dealloc1) -> 1
NSLog(dealloc2) -> エラー

// 【パターン3:[[alloc] initWithUTF8String]】
m_strText = [[NSString alloc] initWithUTF8String:"sample"];
NSLog(init)     -> 1
NSLog(dealloc1) -> 1
NSLog(dealloc2) -> エラー

// 【パターン4:プロパティに対して[[alloc] initWithFormat]】
self.strText = [[NSString alloc] initWithFormat:@"%@", @"sample"];
NSLog(init)     -> 2
NSLog(dealloc1) -> 2
NSLog(dealloc2) -> 1

// 【パターン5:[stringWithFormat]】
m_strText = [NSString stringWithFormat:@"%@", @"sample"];
NSLog(init)     -> 1
NSLog(dealloc1) -> エラー
NSLog(dealloc2) -> エラー

// 【パターン6: [stringWithString]】
m_strText = [NSString stringWithString:@"sample"];
NSLog(init)     -> 2147483647
NSLog(dealloc1) -> 2147483647
NSLog(dealloc2) -> 2147483647

// 【パターン7:代入】
m_strText = @"sample";
NSLog(init)     -> 2147483647
NSLog(dealloc1) -> 2147483647
NSLog(dealloc2) -> 2147483647

エラーとなっている箇所は共通して、すでにリリースされているオブジェクトに対してreleaseを行ったというものだったので、
エラーが出ている箇所は正常に解放されていると思う。
[[NSString alloc] initWithXXXXX];で生成したものはdeallocでreleaseする必要があることは分かった。
しかし、stringWithXXXXなどのようにallocせずに生成したものに対しては参照カウンタは2147483647(intの最大値)になってreleaseしてもカウンタが減らず定数扱いになってる。
これはちゃんと解放されるのだろうか。

初心に帰ってObjective-Cをじっくり勉強し直さないとだめですね。