我们都知道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。