如何增加 NSString 类型变量的保留计数? [复制]
Posted
技术标签:
【中文标题】如何增加 NSString 类型变量的保留计数? [复制]【英文标题】:how retain count of NSString type variable is increased? [duplicate] 【发布时间】:2013-07-27 07:09:07 【问题描述】:下面是关于增加 NSString 类型变量的 d 保留计数值的程序 在接口部分我已经声明了
@property (strong,nonatomic)NSString *str1;
@property (strong, nonatomic)NSString *str2;
-(IBAction)goBtn:(id)sender;
我在下面定义的 ind 实现部分
- (IBAction)goBtn:(id)sender
self.str1=[[NSString alloc]init];
self.str1=self.str2;
self.str2=[self.str1 retain];
self.str2=[[NSString alloc]init];
self.str2=self.str1;
self.str1=[self.str2 retain];
self.str2=[self.str1 retain];
NSLog(@"retain count is %i", self.str1.retainCount);
NSLog(@"retain count of str2 is %i", self.str2.retainCount);
但输出是
保留计数为 0
str2
的保留计数为 0
为什么会这样??代码有什么问题吗???
【问题讨论】:
查看此站点何时使用保留计数:whentouseretaincount.com 【参考方案1】:您正在向 nil 发送大量消息,这就是为什么您的保留计数为 0。
在这里,我再次用变量更改时的新值写下您的代码:
str1 和 str2 为零
self.str1=[[NSString alloc]init];
str1 为空字符串
self.str1=self.str2;
str1 为零
self.str2=[self.str1 retain];
self.str2=[[NSString alloc]init];
str2 为空字符串
self.str2=self.str1;
str2 为零
self.str1=[self.str2 retain];
self.str2=[self.str1 retain];
最后 str1 和 str2 都为零,保留计数为零。
但即使你没有每次都用 nil 覆盖你的新字符串,你也不会得到预期的结果。让我们考虑一下:
self.str1 = [[NSString alloc] init]
self.str2 = [[NSString alloc] init]
如果您查看他们的保留计数,您会得到 18446744073709551615(在 Mac OS X 上,64 位)。如果你再看一下指针的值,你会发现它们都是相等的,所以你两次调用 [[NSString alloc] init]
时都会得到相同的空 NSString 对象。
这实际上是有道理的。 NSString 对象是不可变的,这意味着它们一旦被创建就永远无法改变。因此,在空字符串的多个相同副本上浪费内存是没有意义的。
其中一些共享实例从它们的 retainCount 方法返回最大可能的值,以表明它们是单例的。但不是全部。
所以对象的保留计数不是很有用。有些对象是关于它的。在真实的应用程序中,它仍然经常不是你所期望的。有时系统会保留对象一段时间,即使您自己没有保留它。
但我猜您正在尝试了解保留/释放内存模型的工作原理(即使您使用的是 ARC,这也是必要的)。为此,您可以不用查询保留计数。但是你应该直接使用基类NSObject
,因为它对保留计数器没有任何特殊的作用。而且您需要记住,一旦您将测试对象传递给某些系统方法,您的保留计数可能会在以后出现意外。永远不要在真正的应用程序中查询保留计数——这是没用的。
【讨论】:
很好地抓住了零。我以为他把它放在别处。当我看到那个代码块时,我只看到绝望。 对不起,先生,但是当我没有用 nil 覆盖我的新字符串时,意味着 self.str1=self.str2;反之亦然不使用,它的输出总是-1。为什么会这样??保留计数可以是负数吗??? 不,保留计数不能为负数,它是一个无符号整数。如果您得到一个负数,则将其打印为有符号整数。解释为无符号整数的有符号整数 -1 的位模式将给出最大可能值(对于给定的位大小)。尝试使用%u
而不是%i
打印它。
okkkkkkk...现在我明白了..【参考方案2】:
保留计数毫无意义。别担心。它涉及到很多复杂的因素,比如 NSString 是一个类集群,实现细节真的不是你的问题。
更重要的是,您的属性声明不正确。
自动保留计数 (ARC)
@property (strong, nonatomic) NSString *ARCString;
保留/释放
@property (retain, nonatomic) NSString *retainString;
进一步讨论
正如 Sven(下)指出的那样,从技术上讲,保留和强是同义词。但是,我认为区分代码何时处于 ARC 或 Retain/Release 下很重要。一些通用的最佳做法:
仅使用 _ivar 引用 init 和 dealloc 中的 ivar,如果不使用 ARC,则在此处使用调用来保留/释放。 ARC下不需要dealloc。
- (id)initWithString:(NSString *)string
self = [super init];
if (self != nil)
_retainString = [string retain]; // Adds 1 to retain count
return self;
- (void)dealloc
[_retainString release]; // Decrement retain count by 1
[super dealloc];
其余时间使用 self.ivar 调用 getter/setter。这会自动处理正确的行为。
- (void)doSomethingWithString:(NSString *)string
self.retainString = string; // Adds 1 to retain count
如果您决定在声明的属性中覆盖 getter/setter,那么您将引用 _ivar 并手动调用保留或释放。如果使用 ARC,则无需调用保留/释放。
- (void)setRetainString:(NSString *)string
if (_retainString != string)
[_retainString release];
_retainString = [string retain];
您应该始终分析您的代码,以确认您没有以明显的方式搞砸了。它通常会揭示你的逻辑错误。
【讨论】:
strong 和 retain 是同义词,这不是问题。 @Sven 这在风格上是灾难性的。他很可能混淆了基本概念,而区别非常重要。 初学者可能会感到困惑,但是一旦您知道系统是如何工作的,这应该不是问题。毕竟引用计数机制并没有随着 ARC 消失。当然,您总是应该为新的 ARC 代码编写strong
,但如果您使用的是为手动内存管理而编写并稍后转换为 ARC 的旧代码,您几乎总是会同时看到两者。
字符串属性应该被复制。如果传递一个可变字符串,该 init 方法会做非常糟糕的事情.....
是的,如果你有传递可变字符串的习惯。然而,这里的重点只是为了演示保留和释放。复制和对象中复制的实现完全是“另一锅鱼”。以上是关于如何增加 NSString 类型变量的保留计数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章