1

这是我的代码,

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

4 回答 4

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。这是意料之中的,因为strNameisnil和发送到的消息nil都被忽略了,所以调用 to[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。这是因为NSStrings 的处理方式与大多数对象不同。retainCount这是不是很有用的原因之一。


如果我们将 更改NSStringNSURL如下:

@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。

我们期望的第三个值增加了 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对象。自动释放将对象添加到自动释放池。基本上,NSURL将所有权传递给自动释放池,并了解自动释放池将在不久的将来某个时间点释放对象(在应用程序中,池作为运行循环周期的一部分被刷新)。

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

于 2013-01-31T07:10:24.067 回答
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
于 2013-01-31T09:04:24.073 回答
1

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

于 2013-01-31T07:32:28.467 回答
0

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

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

这种方法被认为是“过时的”,并且永远不应该用于运输,生产代码顺便说一句

于 2013-01-31T06:50:21.990 回答