这是我的代码,
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)的答案?请解释原因?
由于
答案 0 :(得分:2)
我刚刚修改了您的示例,以便在retainCount
语句中添加对NSLog
的调用。应该注意的是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.这是预期的,因为strName
为nil
而发送给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.这是因为NSString
的处理方式与大多数对象不同。这是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
,我们预期的第三个值上升了一个。
您从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
。 Autorelease将对象添加到自动释放池。基本上,NSURL
将所有权传递给自动释放池,同时理解自动释放池将在不久的将来某个时刻释放对象(在应用程序中,池作为runloop循环的一部分被刷新)。
在上面的示例中,URLWithString
返回的对象的保留计数为1.将其分配给属性会使保留计数增加1(因此它现在为2)。然后我们刷新自动释放池(通过保留@autoreleasepool { }
块的范围,保留计数回落到1。
答案 1 :(得分:1)
像@"Something"
这样的常量字符串将保留计为max unsigned int
因为无法释放它们,因为它们是在常量字符串池中分配的。
答案 2 :(得分:1)
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
答案 3 :(得分:0)
您总是可以通过"retainCount
" method询问任何Objective C对象来自己找到答案。
E.G。:“NSLog( @"retain count for strName is %d", [self.strName retainCount]);
”
此方法被视为“过时”,永远不会用于运输,生产代码b.t.w。