ステートメントに呼び出しを追加するように例を変更し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です。isと送信されたメッセージが無視されるため、これは予想されることstrName
です。したがって、toの呼び出しは無視されます。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
sがほとんどのオブジェクトとは異なる方法で処理されるためです。retainCount
これが、あまり役に立たない理由の1つです。
次のようにをに変更する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
The first two cases are the same. The object returned by +URLWithString
is retained but autoreleased and then assigned to the property and retained again. At some point in the future the autorelease pool will be flushed and the retain count will drop to 1.
The third value as we expect has gone up by one because of the explicit call to retain
.
Your understanding from the Apple documentation that the retain count should be 1 (rather than 2 in questions 1 & 2) is technically incorrect but conceptually correct. The object has been autoreleased (effectively a promise that the object will be released in the near future).
We can investigate the effects of the autorelease pool by flushing the pool. I have modified the main
function to flush the autorelease pool before calling returnRetainCount
.
int main(int argc, char *argv[]) {
@autoreleasepool {
SyncObjectInfo *obj;
@autoreleasepool {
obj = [SyncObjectInfo new];
obj.strName = [NSURL URLWithString:@"http://stackoverflow.com"];
}
[obj returnRetainCount];
}
}
This time the output is:
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
This is more what you'd expect. So what is happening?
When the NSURL
object is created by the URLWithString
method it has a retain count of 1. However, the NSURL
class needs to give up ownership of the object. If it called release
on this object before returning it the retain count would reach 0 and the object would be deallocated before it is ever returned.
Instead the URLWithString
method calls autorelease
on the object. Autorelease adds the object to the autorelease pool. Basically, NSURL
passes ownership to the autorelease pool with the understanding that the autorelease pool will release the object at some point in the near future (in an application the pool is flushed as part of the runloop cycle).
In the example above the object returned by URLWithString
has a retain count of 1. Assigning it to the property increments the retain count by 1 (so it is now 2). We then flush the autorelease pool (by leaving the scope of the @autoreleasepool { }
block and the retain count drops back to 1.