iOS中的retainCount

      我们都知道iOS中采用引用计数的技术来管理内存,当一个对象没有任何一个地方引用的时候会自动释放,此时的retainCount为0,而且提供了一个-(NSInteger)retainCount的方法来获得对象当前的持有数。

     这个概念清楚而明确,不过,让我们看两段代码:

    NSNumber *number = [NSNumber numberWithInt:1];
    NSLog(@"retainCount = %lu",[number retainCount]);

      这段代码的运行结果是什么?

    NSString *string = [NSString stringWithFormat:@"foo"];
    NSLog(@"retainCount = %lu", [string retainCount]);

      这一段呢?

      在Xcode5.0, ARC关闭的情况下运行,结果是:

2014-01-13 22:08:13.217 blockTest[2732:303] retainCount = 9223372036854775807

2014-01-13 22:08:13.218 blockTest[2732:303] retainCount = 1

      这个很出人意料啊,第二段看上去很符合我们的预期,但第一段就有点让人掉眼镜了。

      查阅了一下官方的文档,第一句就是“Do not use this method.”,后面给出了说明,因为Autorelease pool的存在,对于内存的管理会相当复杂,retainCount就不能用作调试内存时的依据了。这样对于第一段的结果就可以理解了,可能系统对于这一个特殊的对象有特殊的处理(没准framework里面有早就创建了这个对象了),于是我们拿到了一个非常出人意料的结果。

      想想见过的如下的代码就很有点吓人了:

    while ([a retainCount] > 0) {
        [a release];
    }
      如果运行结果正确,那么这是多么幸运的一个人啊!

      但对于内存的思考我们可以更进一步,看一段代码:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property(nonatomic, retain) NSString *name;
@property(nonatomic, assign) NSInteger age;

@end

@implementation Person
- (id)init
{
    self = [super init];
    if (self) {
        self.name = @"name";
        self.age = 20;
    }
    return self;
}

- (void)dealloc
{
    NSLog(@"dealloc");
    [super dealloc];
}

@end

int main(int argc, const char * argv[])
{
    Person *per1 = [[Person alloc] init];
    //NSLog(@"retainCount = %lu -- 0",[per1 retainCount]);
    [per1 release];
    per1.age = 22;
    NSLog(@"retainCount = %lu -- 1, age = %ld",[per1 retainCount], per1.age);
    //[per1 retain];
    //per1.age = 23;
    //NSLog(@"retainCount = %lu -- 2, age = %ld",[per1 retainCount], per1.age);
    
    return 0;
}
      这段代码的运行结果居然是:

2014-01-13 22:17:11.619 blockTest[2758:303] dealloc

2014-01-13 22:17:11.621 blockTest[2758:303] retainCount = 1 -- 1, age = 22

      这个问题位于http://www.cocoachina.com/ask/questions/show/106777#36483,个人猜测是对象确实销毁了,毕竟dealloc都调用了,但内存里面数据仍然存在,立刻打印是存在内容的,至于retainCount不是0,只能说明对象即使已经销毁了,这个值仍然可能大于0。

posted @ 2014-01-13 22:21  huluo666  阅读(222)  评论(0编辑  收藏  举报