这是关于增加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
为什么会这样?代码中有什么问题???
答案 0 :(得分:2)
您正在向nil发送大量消息,这就是为什么您的保留计数为0的原因。
在这里,我再次使用变量的新值写下代码:
str1和str2是nil
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,给你零保留计数。
但即使你没有用nil覆盖你的新字符串,每次你都不会得到预期的结果。让我们考虑一下:
self.str1 = [[NSString alloc] init]
self.str2 = [[NSString alloc] init]
如果您查看他们的保留计数,您将获得18446744073709551615(在Mac OS X上,64位)。如果你看一下指针的值,你会看到它们都是相等的,所以你在调用[[NSString alloc] init]
时都得到了相同的空NSString对象。
这实际上是有道理的。 NSString对象是不可变的,这意味着一旦创建它们就无法改变。因此,在空字符串的多个相同副本上浪费内存是毫无意义的。
其中一些共享实例从retainCount方法返回最大可能值,以显示它们是单例的事实。但不是全部。
因此对象的保留计数不是很有用。一些对象就是谎言。在真正的应用程序中,它通常不是你所期望的。有时系统会保留对象一段时间,即使您没有自己保留它。
但我想您正在尝试了解保留/释放内存模型的工作原理(即使您使用ARC,这也是必要的)。为此,您可以通过查询保留计数来逃避。但是你应该直接使用基类NSObject
,因为它不会对保留计数器做任何特殊的技巧。并且您需要记住,只要您将测试对象传递给某些系统方法,您的保留计数可能会在以后出现意外情况。始终牢记永远不要在真实应用中查询保留计数 - 这是无用的。
答案 1 :(得分:0)
保留计数毫无意义。别担心。它涉及很多复杂的因素,比如NSString是一个类集群,而实现细节确实不是你的问题。
更重要的是,您的财产声明不正确。
@property (strong, nonatomic) NSString *ARCString;
@property (retain, nonatomic) NSString *retainString;
正如斯文(下文)所指出的,保留和强大是技术上的同义词。但是,我认为区分代码何时处于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并手动调用retain或release。如果使用ARC,则不需要保留/释放调用。
- (void)setRetainString:(NSString *)string
{
if (_retainString != string) {
[_retainString release];
_retainString = [string retain];
}
}
您应该始终分析您的代码,以验证您没有以明显的方式搞砸了。它经常会揭示你的逻辑中的失败。