我一直在使用來自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