1

我观察到以下行为。

取了两个属性变量。

@property (nonatomic, retain) NSString *stringOne;
@property (nonatomic, assign) NSString *stringTwo;

在 .m 文件中写在下面的代码中..

 NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];
 self.stringOne = localstring;
 NSLog(@"localstring = %d", [string retainCount]);
 NSLog(@"string one retain count = %d", [self.stringOne retainCount]);
 self.stringTwo = localstring;
 NSLog(@"localstring = %d", [localstring retainCount]);
 NSLog(@"string two  retain count = %d", [self.stringTwo retainCount]);

由于 alloc,这里 localstring 保留计数为 1。现在我给了 self.stringOne = localString。

由于 stringOne 的保留属性,localstring 的保留计数将变为 2。现在我给了 self.stringTwo = localString。

即使在这里,localstring 保留计数也会增加 1。请注意,我已将属性分配给 stringTwo。实际上,localstring 或 stringTwo 的保留计数不应增加 1,因为它是分配属性。如果我错了,请纠正我。

谢谢吉腾

4

5 回答 5

5

转储retainCount; 这是没用的。 http://www.whentouseretaincount.com/

您困惑的根源在于不了解指针的工作原理。像这样修改你的代码:

@interface BBQ:NSObject
@property (nonatomic, retain) NSString *stringOne;
@property (nonatomic, assign) NSString *stringTwo;
@end

@implementation BBQ
- (void) burn
{
    NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];
    self.stringOne = localstring;
    NSLog(@"localstring = %p", localstring);
    NSLog(@"string one = %p", self.stringOne);
    self.stringTwo = localstring;
    NSLog(@"localstring = %p", localstring);
    NSLog(@"string two  = %p", self.stringTwo);
}
@end

它会喷出这样的东西:

2013-04-11 08:48:13.770 asdffadsfasddfsa[18096:303] localstring = 0x10010aaf0
2013-04-11 08:48:13.772 asdffadsfasddfsa[18096:303] string one = 0x10010aaf0
2013-04-11 08:48:13.772 asdffadsfasddfsa[18096:303] localstring = 0x10010aaf0
2013-04-11 08:48:13.772 asdffadsfasddfsa[18096:303] string two  = 0x10010aaf0

播放中只有一个字符串实例; localstring, stringOne, 并且stringTwo都持有对一个 NSMUtableString 实例的引用

因此,您会看到的那个字符串实例的+1 RC alloc,分配给stringOne属性的 +1 和没有变化stringTwo

(RC 应该仅根据增量进行推理;如果您保留一个对象,则需要在不再需要该对象时将其与释放进行平衡。该对象可能被其他东西保留是无关紧要的。)

于 2013-04-11T15:51:47.667 回答
3

当我运行这段代码时:

@interface ViewController ()

@property (nonatomic, retain) NSString *stringOne;
@property (nonatomic, assign) NSString *stringTwo;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self test];
}

- (void)test
{
    NSMutableString *localstring = [[NSMutableString alloc] initWithString:@"test"];
    NSLog(@"localstring (before setting `stringOne` or `stringTwo`) = %d", [localstring retainCount]);
    self.stringOne = localstring;
    NSLog(@"localstring (after setting `stringOne`) = %d", [localstring retainCount]);
    NSLog(@"string one retain count = %d", [self.stringOne retainCount]);
    self.stringTwo = localstring;
    NSLog(@"localstring (after setting `stringTwo`) = %d", [localstring retainCount]);
    NSLog(@"string two retain count = %d", [self.stringTwo retainCount]);
}

@end

我收到了这个控制台日志:

localstring(在设置 `stringOne` 或 `stringTwo` 之前)= 1
localstring(设置 `stringOne` 后)= 2
字符串一保留计数 = 2
localstring(设置 `stringTwo` 后)= 2
字符串二保留计数 = 2

所有这些值都与人们期望的一样。

  • 当您第一次创建由局部变量引用的对象时,该对象具有+1保留计数。

  • 当您设置retain属性时stringOne,对象的保留计数将增加到+2,并且由于两者都localstring引用stringOne同一个对象,它们都将报告相同的retainCount

  • 但是,当您使用该assign属性时,stringTwo不会retainCount改变。

于 2013-04-11T07:21:25.313 回答
2

当您使用 声明属性时retain,它会自动“保留”该对象,从而增加其保留计数。

所以NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];使保留计数= 1;

然后self.stringOne = localstring;使保留计数= 2。

我的想法是如果属性被赋予retain,那么在这一行self.stringOne = localstring之后,self.stringone的retain count应该变成1

当您创建一个对象时,它的保留计数将从 1 开始。

于 2013-04-11T06:36:38.927 回答
1

首先,永远不要retainCount用于任何事情。它根本不可靠,因为它是一个全局保留计数,并且可能受到代码之外的其他因素的影响。令人惊讶的是,在这种情况下,它是正确的。让我们检查一下:

//Immediately localstring is +1 because you allocated it
NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];

//self.stringOne is a retain property, so localstring is incremented again (+2)
self.stringOne = localstring;

//self.stringTwo is a retain property, so localstring is incremented again (+3)
self.stringTwo = localstring;


注意 nowlocalstring和all 指向内存中的同一个位置self.stringOneself.stringTwo不是每次使用该=符号时都在复制内存内容(您的思维方式似乎表明您认为它是这样工作的)。您只是将另一个变量指向内存中的某个位置并说“在我这么说之前不要释放这块内存”。(至少在保留属性的情况下)。

结论:localstring的retain count、self.stringOne的retain count、self.stringTwo的retain count都是一样的。

旁注:对象的保留计数不可能为零。唯一可能发生的时间retainCount是发送到nil(我假设self.stringOne是在您测试它时)

于 2013-04-11T06:38:26.597 回答
0

虽然在编写代码时查看它从来都不是一个好主意retainCount,但在这种情况下它的行为应该如此。我认为您对内存管理的理解似乎有点偏离。

要回答你的问题,

NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];

这将创建一个可变字符串Object,增加其保留计数并返回指向它的指针。请注意,retainCount它与Object而不是指针相关联。

当您将其分配给您的保留财产时,

self.stringOne = localstring;

它传递retain给您的对象并再次将其保留计数增加 1。现在您的对象的保留计数为 2,并且两个指针都指向同一个对象。所以,当你登录时retainCount,你会得到你所得到的。希望这能回答你的问题。

于 2013-04-11T06:40:05.163 回答