在Obj-c中iVar和self.iVar的保留计数是多少?

时间:2013-01-31 06:40:40

标签: ios objective-c retaincount

这是我的代码,

import <Foundation/Foundation.h>

@interface SyncObjectInfo : NSObject
{
     NSString *strName;

}
@property(nonatomic,retain) NSString *strName;
-(void)returnRetainCount;

@end

#import "SyncObjectInfo.h"

@implementation SyncObjectInfo
@synthesize strName;
-(void)returnRetainCount
{

 self.strName=@"name";
 strName=@"name";
 NSLog(@"Que-1. what is the retainCount of self.strName = ___");
 NSLog(@"Que-2. what is the retainCount of      strName = ___");

 [self.strName retain];
 NSLog(@"Que-3. what is the retainCount of  self.strName= ___");

}

@end

我对保留计数感到困惑,所以......

请给我-(void)returnRetainCount方法问题(1,2,3)的答案?请解释原因?

由于

4 个答案:

答案 0 :(得分:2)

我刚刚修改了您的示例,以便在retainCount语句中添加对NSLog的调用。应该注意的是retainCount不是一种特别有用的方法,一般应该避免。

有关详细信息,请参阅http://whentouseretaincount.com(不要忘记向下滚动以获取更多详细信息)。

无论如何,这是我跑的。请注意,我将[self.str retain]更改为[self.strName retain]

#import <Foundation/Foundation.h>


@interface SyncObjectInfo : NSObject
{
     NSString *strName;
}

@property(nonatomic,retain) NSString *strName;

-(void)returnRetainCount;

@end

@implementation SyncObjectInfo
@synthesize strName;
-(void)returnRetainCount
{
 NSLog(@"Que-1. what is the retainCount of self.strName = %lu", [self.strName retainCount]);
 NSLog(@"Que-2. what is the retainCount of      strName = %lu", [strName retainCount]);

 [self.strName retain];
 NSLog(@"Que-3. what is the retainCount of  self.strName= %lu", [self.strName retainCount]);

}

@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        SyncObjectInfo *obj = [SyncObjectInfo new];

        [obj returnRetainCount];
    }
}

在所有情况下,答案都是0.这是预期的,因为strNamenil而发送给nil的邮件会被忽略,因此对[self.strName retain]的调用是忽略。


但是,如果我将strName设置为某些内容,请使用以下代码:

int main(int argc, char *argv[]) {
    @autoreleasepool {
        SyncObjectInfo *obj = [SyncObjectInfo new];

        obj.strName = @"Something";

        [obj returnRetainCount];
    }
}

然后当我重新运行时,我得到以下内容:

Que-1. what is the retainCount of self.strName = 18446744073709551615
Que-2. what is the retainCount of      strName = 18446744073709551615
Que-3. what is the retainCount of  self.strName= 18446744073709551615

保留计数为18446744073709551615.这是因为NSString的处理方式与大多数对象不同。这是retainCount不太有用的原因之一。


如果我们将NSString更改为NSURL,如下所示:

@interface SyncObjectInfo : NSObject
{
     NSURL *strName;
}

@property(nonatomic,retain) NSURL *strName;

// snip

int main(int argc, char *argv[]) {
    @autoreleasepool {
        SyncObjectInfo *obj = [SyncObjectInfo new];

        obj.strName = [NSURL URLWithString:@"http://stackoverflow.com"];

        [obj returnRetainCount];
    }
}

然后重新运行:

Que-1. what is the retainCount of self.strName = 2
Que-2. what is the retainCount of      strName = 2
Que-3. what is the retainCount of  self.strName= 3

前两种情况是相同的。 +URLWithString返回的对象保留但自动释放,然后分配给属性并再次保留。在将来的某个时刻,自动释放池将被刷新,保留计数将降至1。

由于显式调用retain,我们预期的第三个值上升了一个。


您从Apple文档中了解保留计数应为1(而不是问题1和2中的2)在技术上是不正确的,但在概念上是正确的。该对象已被自动释放(实际上是在不久的将来将释放该对象的承诺)。

我们可以通过冲洗池来调查自动释放池的影响。我在调用main之前修改了returnRetainCount函数来刷新自动释放池。

int main(int argc, char *argv[]) {
    @autoreleasepool {
        SyncObjectInfo *obj;

        @autoreleasepool {
            obj = [SyncObjectInfo new];

            obj.strName = [NSURL URLWithString:@"http://stackoverflow.com"];
        }

        [obj returnRetainCount];
    }
}

这次输出是:

Que-1. what is the retainCount of self.strName = 1 
Que-2. what is the retainCount of      strName = 1
Que-3. what is the retainCount of  self.strName= 2

这更符合您的期望。那么发生了什么?

NSURL方法创建URLWithString对象时,它的保留计数为1.但是,NSURL类需要放弃该对象的所有权。如果它在返回之前在此对象上调用release,则保留计数将达到0,并且该对象将在返回之前被释放。

相反,URLWithString方法会在对象上调用autorelease。 Autorelease将对象添加到自动释放池。基本上,NSURL将所有权传递给自动释放池,同时理解自动释放池将在不久的将来某个时刻释放对象(在应用程序中,池作为runloop循环的一部分被刷新)。

在上面的示例中,URLWithString返回的对象的保留计数为1.将其分配给属性会使保留计数增加1(因此它现在为2)。然后我们刷新自动释放池(通过保留@autoreleasepool { }块的范围,保留计数回落到1。

答案 1 :(得分:1)

@"Something"这样的常量字符串将保留计为max unsigned int 因为无法释放它们,因为它们是在常量字符串池中分配的。

答案 2 :(得分:1)

NSLog(@"Que-1. what is the retainCount of self.strName = %lu", [self.strName retainCount]);
retain count normal=2

NSLog(@"Que-2. what is the retainCount of      strName = %lu", [strName retainCount]);
retain count self=2

NSLog(@"Que-3. what is the retainCount of  self.strName= %lu", [self.strName retainCount]);
retain count self=3

答案 3 :(得分:0)

您总是可以通过"retainCount" method询问任何Objective C对象来自己找到答案。

E.G。:“NSLog( @"retain count for strName is %d", [self.strName retainCount]);

此方法被视为“过时”,永远不会用于运输,生产代码b.t.w。