【问题标题】:What is the retain count of iVar and self.iVar in Obj-c?Obj-c 中 iVar 和 self.iVar 的保留计数是多少?
【发布时间】:2023-03-09 04:22:01
【问题描述】:

这是我的代码,

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)的答案?请解释原因?

谢谢

【问题讨论】:

  • 如果你没有在某处为strName 赋值,所有保留计数都将为零。
  • 应该是[self.strName retain]; 还是你的意思是[self.str retain]

标签: ios objective-c retaincount


【解决方案1】:

我刚刚修改了您的示例,在您的 NSLog 语句中添加了对 retainCount 的调用。需要注意的是,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。这是因为 NSStrings 的处理方式与大多数对象不同。这也是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,我们预期的第三个值增加了1。


您从 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 将所有权传递给自动释放池,并了解自动释放池将在不久的将来某个时间点释放对象(在应用程序中,池作为 runloop 循环的一部分被刷新)。

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

【讨论】:

  • 嗨 mttrb,按照你的方法我得到了答案,但我仍然很困惑为什么 que-1 和 que-2 的保留计数是 2 而不是 1,因为我从苹果读到它应该是 1。你能解释一下我的详细信息?
  • @Nikh1414 我已经更新了我的答案,提供了更多关于自动释放池的信息。
【解决方案2】:

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

【讨论】:

    【解决方案3】:
    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
    

    【讨论】:

      【解决方案4】:

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

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

      这种方法被认为是“过时的”并且应该永远用于运输,生产代码b.t.w.

      【讨论】:

        猜你喜欢
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        • 1970-01-01
        • 2011-05-08
        • 1970-01-01
        • 1970-01-01
        • 2016-11-16
        相关资源
        最近更新 更多