NSArray是强引用容器

经常比较疑惑NSArray、NSDictionary、NSSet这几个对象容器管理对象所采用的方式是“强引用”还是“弱引用”。

通过简单的命令行程序得到的结论是“NSArray、NSDictionary、NSSet这几个容器都是强引用容器”。

打开Xcode,新建project,选择“OS X”-“Application”-“Command Line Tool”,完成project的创建,默认情况下,project会使用ARC,这里不需要使用ARC,所以还需要在project配置文件中将ARC取消。容易在“PROJECT”-“Build Settings”-“Apple LLVM 6.0 - Language - Objective C”中找到“Objective-C Automatic Reference Counting”这一项,选择为“No”即可。

话不多说,开始。

创建一个类Person,该类定义很简单,只有一个name属性:

@interface Person : NSObject
    
@property (nonatomic, retain) NSString *name;
    
@end

main.m文件代码如下:

int main(int argc, const char * argv[]) {
    
    Person *person = [[Person alloc] init];
    person.name = @"Jason";
    
    NSLog(@"(1). Object Reference Count = %lu, name=%@",
          [person retainCount], person.name);
    // output: (1). Object Reference Count = 1, name=Jason
    
    NSArray *array = @[person];
    NSLog(@"(2). Object Reference Count = %lu, name=%@",
          [person retainCount], person.name);
    // output: (2). Object Reference Count = 2, name=Jason
    
    [array release];
    NSLog(@"(3). Object Reference Count = %lu, name=%@",
          [person retainCount], person.name);
    // output: (3). Object Reference Count = 1, name=Jason
    
    [person release];
    NSLog(@"(4). Object Reference Count = %lu, name=%@",
          [person retainCount], person.name);
    // output: (4). Object Reference Count = 1, name=Jason
    
    return 0;
}

刚开始对output(4)的输出非常不理解,有两个疑点: 

  1. [person release]之后person对象应该不存在了,为什么其reference count为1而不是0呢?
  2. person不是被released了吗,为什么还能访问器name属性?

对于第一个问题,读了唐巧的《iOS开发进阶》,得出的答案是:
因为该对象已经被回收,而我们向一个被回收的对象发了一个retainCount消息,所以它的输出结果应该是不确定的。那为什么在这个对象被回收之后,这个不确定的值是1而不是0呢?这是因为当最后一次执行release时,系统知道马上就要回收内存了,就没有必要再将retainCount减1了,因为不管减不减1,该对象肯定会被回收,而对象被回收后,它的所有内存区域,包括retainCount值也变得没有意义了。不将这个值从1变为0,可以减少一次内存的操作,加速对象的回收。

对于第二个问题,还没有找到比较权威的解释,以后再来回到吧。

总之,搞清楚了“NSArray、NSDictionary以及NSSet都是强引用容器”这个事实。

posted @ 2015-05-22 11:11  脸大皮厚歌  阅读(435)  评论(0编辑  收藏  举报