通过'分析',在dealloc中得到: 调用者此时不拥有的对象的引用计数的不正确减少
#import <AVFoundation/AVFoundation.h>
@interface XYZViewController : UIViewController
@property (retain) AVAudioRecorder *recorder;
@end
@implementation XYZViewController
@synthesize recorder;
- (void) dealloc
{
[self.recorder release];
[super dealloc];
}
- (void) viewDidLoad
{
NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
nil];
NSError *error;
self.recorder = [[[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error] autorelease];
}
@end
这是否意味着我不应该发布它?
此外,我试图'配置'代码,无论如何我都会从[[[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error] autorelease]
收到内存泄漏。
答案 0 :(得分:4)
您应该直接释放ivar,而不是通过访问者:
- (void)dealloc
{
[recorder release];
[super dealloc];
}
您不拥有访问者的返回对象,因此您不应该将其释放。
答案 1 :(得分:1)
不是将-release
发送到属性访问器方法返回的对象,而是将属性本身设置为nil
:
- (void)dealloc {
self.recorder = nil;
[super dealloc];
}
编译器将知道做正确的事情,因为您已在属性声明中指定了存储语义。合成用retain
语义声明的属性实际上等同于编写以下访问器方法:
- (AVAudioRecorder *)recorder {
return recorder;
}
- (void)setRecorder:(AVAudioRecorder *)newRecorder {
[newRecorder retain];
[recorder release];
recorder = newRecorder;
}
编写self.recorder = nil
时,编译器会将其转换为[self setRecorder:nil]
。因此,以这种方式将属性设置为nil
可以避免内存泄漏和悬空指针,您可以使用更少的样板,并且更清楚地表达代码的意图。
最后,重新阅读The Objective-C Programming Language永远不会受到伤害,Advanced Memory Management Programming Guide有一个关于声明属性的部分;和{{3}},它详细介绍了所有不同的内存管理方法。