我一直在使用来自Raphael Cruzeiro的代码PDF Annotator,并且发现了一些内存泄漏(ARC关闭,并且将停留以支持较旧的设备)。大部分补丁修补完毕后,我倒到了最后一对,他们让我难倒了。因此,在名为PDFDocument
的课程中,他具有CGPDFPageRef
,CGPDFDocument
和自定义注释类别@synthesize
'd的属性。我不得不用释放他的dealloc方法,并删除一些悬挂指针,这除了一个小问题之外运行良好:经过大约3个完整的retain-release循环,它的注释对象在@synthesize行崩溃......我已经由于在@synthesize期间发送了释放的对象,所以从未见过SIGABRT,所以自然不知道如何解决它。如果我在dealloc中删除发布代码,它会泄漏,但是如果我将它放入,它会崩溃。下面是该PDFDocument类的代码:发送到释放实例的消息...在@synthesize期间发送的消息?
//.h
#import <Foundation/Foundation.h>
@class Annotation;
@interface PDFDocument : NSObject {
Annotation *_annotation;
}
- (id)initWithDocument:(NSString *)documentPath;
- (NSInteger) pageCount;
- (void) loadPage:(NSInteger)number;
- (BOOL)save;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *hash;
@property (readwrite, nonatomic, assign) CGPDFDocumentRef document;
@property (readwrite, nonatomic, assign) CGPDFPageRef page;
@property (nonatomic, retain) NSString *version;
@property (nonatomic, assign) BOOL dirty;
@property (nonatomic, retain) Annotation *annotation;
@end
//.m
#import "PDFDocument.h"
#import "Annotation.h"
#import "HashExtensions.h"
#import "DocumentDeserializer.h"
#import "DocumentSerializer.h"
@implementation PDFDocument
@synthesize document;
@synthesize page;
@synthesize annotation = _annotation; //after 3rd cycle, it crashes here.
@synthesize name;
@synthesize hash;
@synthesize dirty;
@synthesize version;
- (id)initWithDocument:(NSString *)documentPath
{
if((self = [super init]) != NULL) {
self.name = [documentPath lastPathComponent];
if ([self.name isEqualToString:@"Musette.pdf"] || [self.name isEqualToString:@"Minore.pdf"] || [self.name isEqualToString:@"Cantata.pdf"] || [self.name isEqualToString:@"Finalé.pdf"])
{
CFURLRef ref = CFBundleCopyResourceURL(CFBundleGetMainBundle(), (CFStringRef)self.name, NULL, NULL);
self.document = CGPDFDocumentCreateWithURL(ref);
self.page = CGPDFDocumentGetPage(document, 1);
self.version = @"1.0";
DocumentDeserializer *deserializer = [[[DocumentDeserializer alloc] init] autorelease];
self.annotation = [deserializer readAnnotation:[[(NSURL*)ref absoluteString] stringByDeletingPathExtension]];
CFRelease(ref);
}
else {
CFURLRef pdfURL = (CFURLRef)[[NSURL alloc] initFileURLWithPath:documentPath];
self.document = CGPDFDocumentCreateWithURL(pdfURL);
self.page = CGPDFDocumentGetPage(document, 1);
self.version = @"1.0";
DocumentDeserializer *deserializer = [[[DocumentDeserializer alloc] init] autorelease];
self.annotation = [deserializer readAnnotation:[[(NSURL*)pdfURL absoluteString] stringByDeletingPathExtension]];
CFRelease(pdfURL);
CGPDFPageRelease(self.page);
}
}
return self;
}
- (NSInteger)pageCount
{
return CGPDFDocumentGetNumberOfPages(self.document);
}
- (void)loadPage:(NSInteger)number
{
self.page = CGPDFDocumentGetPage(document, number);
}
- (BOOL)save
{
DocumentSerializer *serializer = [[[DocumentSerializer alloc] init] autorelease];
[serializer serialize:self];
self.dirty = NO;
return !self.dirty;
}
- (void)dealloc
{
CGPDFDocumentRelease(self.document);
if (self.annotation != nil && _annotation != nil) {
[_annotation release];
self.annotation = nil;
} //my attempt to prevent the object from being over-released
self.document = nil;
self.name = nil;
[super dealloc];
}
@end
然后我跑了通过仪器发现僵尸对象,果然,仪器发现正在发送的信息在完全相同的@synthesize行解除分配的对象!
有没有人有任何想法是怎么回事,以及如何解决它?
只有第一代iPhone与ARC不兼容,为什么不使用它? – 2012-02-25 21:08:18
仅仅是我自己的偏好......结合ARC重构工具现在令我烦恼的事实。叹息......我现在就转换。 – CodaFi 2012-02-25 21:27:56
你说它在“合成”期间坠毁了。实际上,它是在' - (Annotation *)注释'或' - (void)setAnnotation:(Annotation *)'合成方法中崩溃。可能是伊娃已经被释放的二传手。 – mattjgalloway 2012-02-25 21:30:03