IOS保留,分配

时间:2013-04-11 06:25:00

标签: iphone ios memory-management retain assign

我观察到以下行为。

取两个属性变量。

@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的retain属性,localstring的保留计数将变为2。现在我给了     self.stringTwo = localString。

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

由于 Jithen

5 个答案:

答案 0 :(得分: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

只有一个字符串实例在播放; localstringstringOnestringTwo都只包含对 NSMUtableString 的一个实例的引用。

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

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

答案 1 :(得分: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 (before setting `stringOne` or `stringTwo`) = 1
localstring (after setting `stringOne`) = 2
string one retain count = 2
localstring (after setting `stringTwo`) = 2
string two retain count = 2

所有这些价值观都与人们期望的完全一样。

  • 首次创建局部变量引用的对象时,该对象的保留计数为+1

  • 当您设置retain属性stringOne时,对象的保留计数将增加到+2,同时localstring和{{1}引用同一个对象,它们都会报告相同的stringOne

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

答案 2 :(得分:2)

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

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

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

  

我的想法是,如果属性被保留,那么在此行之后   self.stringOne = localstring,self.stringone的保留计数   应该成为一个

创建对象时,它将以保留计数1开始。

答案 3 :(得分: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;


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

结论:localstring的retain count,self.stringOne的retain count和self.stringTwo的retain count都是相同的。

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

答案 4 :(得分:0)

虽然在编写代码时查看retainCount绝不是一个好主意,但在这种情况下它的行为应该是正常的。我认为你对内存管理的理解似乎有点过时了。

要回答你的问题,

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

这会创建一个可变字符串 Object ,递增其保留计数并返回指向它的指针。请注意,retainCount对象相关联,而非指针。

将其分配给保留属性时,

self.stringOne = localstring;

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