NSStringのretainCount考察

2011/02/07

NSStringのretainCount

#import 

@interface RetainTestViewController : UIViewController {
    NSString *nameRetain;
    NSString *nameAssign;
    NSString *nameCopy;
}

@property (nonatomic, retain) NSString *nameRetain;
@property (nonatomic, assign) NSString *nameAssign;
@property (nonatomic, copy) NSString *nameCopy;

@end
#import "RetainTestViewController.h"

@implementation RetainTestViewController
@synthesize name;

- (void)viewDidLoad {
    [super viewDidLoad];
    //Retain
    NSLog(@"retain0: %x %@ retain = %d",nameRetain, nameRetain, [nameRetain retainCount]);
    
    nameRetain = @"Yoo"; //(1)
    NSLog(@"retain1: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
    
    nameRetain = [NSString stringWithFormat:@"Yoo"]; //(2)
    NSLog(@"retain2: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
    
    nameRetain = [NSString stringWithFormat:@"Hello %@", nameRetain]; //(3)
    NSLog(@"retain3: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
    
    nameRetain = [[NSString stringWithFormat:@"Yoo"] retain]; //(4)
    NSLog(@"retain4: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
    
    [nameRetain release];  //(5)
    NSLog(@"retain5: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
    
    nameRetain = nil; //(6)
    NSLog(@"retain6: %x %@ retainCount = %d",nameRetain, nameRetain, [nameRetain retainCount]);
}

- (void)dealloc {
    [super dealloc];
}

@end

2011-02-07 17:58:13.387 RetainTest[37717:207] retain0: 0 (null) retain = 0 2011-02-07 17:58:13.388 RetainTest[37717:207] retain1: 4044 Yoo retainCount = 2147483647 2011-02-07 17:58:13.388 RetainTest[37717:207] retain2: 4b025a0 Yoo retainCount = 1 2011-02-07 17:58:13.389 RetainTest[37717:207] retain3: 4b0dde0 Hello Yoo retainCount = 1 2011-02-07 17:58:13.389 RetainTest[37717:207] retain4: 4b039f0 Yoo retainCount = 2 2011-02-07 17:58:13.389 RetainTest[37717:207] retain5: 4b039f0 Yoo retainCount = 1 2011-02-07 17:58:13.390 RetainTest[37717:207] retain6: 0 (null) retainCount = 0

(1) retainCountが「2147483647」になっています。 これは、文字列を定数として保持しているからみたいです。 (2) stringWithFormatを介すとretainCountが1増加します。 (3) 文字を連結してもretainCountは変化しません。 (4) retainを記述すると、alloc/initと計2つretainCountが増加します。 (5) releaseにすると、retainCountが1減少します。 ただし、retainCountが0になってしまうと解放できないのでアプリが落ちます。 (6) nilにすると、retainCountが0となります。

で、このサンプルでは、NSStringに関してはretain,assign,copyのどれを使っても 結果が同じ(?)になりました。

Copyの例

    //Copy
    NSLog(@"copy0: %x %@ retain = %d",nameCopy, nameCopy, [nameCopy retainCount]);
    
    nameCopy = @"Yoo"; //(1)
    NSLog(@"copy1: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
    
    nameCopy = [NSString stringWithFormat:@"Yoo"]; //(2)
    NSLog(@"copy2: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
    
    nameCopy = [NSString stringWithFormat:@"Hello %@", nameCopy]; //(3)
    NSLog(@"copy3: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
    
    nameCopy = [[NSString stringWithFormat:@"Yoo"] copy]; //(4)
    NSLog(@"copy4: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
    
    [nameCopy release];  //(5)
    NSLog(@"copy5: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);
    
    nameCopy = nil; //(6)
    NSLog(@"copy6: %x %@ retainCount = %d",nameCopy, nameCopy, [nameCopy retainCount]);

2011-02-07 17:58:13.390 RetainTest[37717:207] copy0: 0 (null) retain = 0 2011-02-07 17:58:13.390 RetainTest[37717:207] copy1: 4044 Yoo retainCount = 2147483647 2011-02-07 17:58:13.391 RetainTest[37717:207] copy2: 4b03180 Yoo retainCount = 1 2011-02-07 17:58:13.391 RetainTest[37717:207] copy3: 4e194e0 Hello Yoo retainCount = 1 2011-02-07 17:58:13.392 RetainTest[37717:207] copy4: 4b0c0d0 Yoo retainCount = 2 2011-02-07 17:58:13.392 RetainTest[37717:207] copy5: 4b0c0d0 Yoo retainCount = 1 2011-02-07 17:58:13.392 RetainTest[37717:207] copy6: 0 (null) retainCount = 0

ちなみに、NSStringはそのままcopyを利用できますが、その他のオブジェクトは基本的にcopyWithZoneで複製します。