2012-05-06 7 views
0

テキスト行の高さを計算する方法があります。しかし問題は、2つのアイテム、CTFrameとMalloc(48バイト)でメモリをリークすることです。ここでコアテキストを扱うときにコア基礎オブジェクトを解放する方法

は、その方法の核心です:

(void)calculatePageHeight { 
    __weak UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.view.bounds]; 

    NSString *sampleText = @"The CTFont opaque type represents a Core Text font object. Font objects represent fonts to an application, providing access to characteristics of the font, such as point size, transform matrix, and other attributes. Fonts provide assistance in laying out glyphs relative to one another and are used to establish the current font when drawing in a graphics context."; 
    NSRange contentRange = NSRangeFromString(sampleText); 
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:sampleText attributes:self.textAttributes]; 

    CFAttributedStringRef attributeRef = (__bridge CFAttributedStringRef)attributedString; 

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attributeRef); 

    CGPathRef myPath = [path CGPath]; 
    CFRange myRange = CFRangeMake(contentRange.location, contentRange.length); 

    CTFrameRef contentFrame = CTFramesetterCreateFrame(framesetter, myRange , myPath, nil); 
    CFArrayRef lines = CTFrameGetLines(CFRetain(contentFrame)); 
    NSInteger lineCount = CFArrayGetCount(lines); 
    CGPoint *origins = calloc(lineCount, sizeof(CGPoint)); 

    CTFrameGetLineOrigins(contentFrame, CFRangeMake(0, 0), origins); 
    CGFloat lineSpacing = 0; 

    for (NSInteger index = 0; index < lineCount; index ++) { 
     CTLineRef line = CFArrayGetValueAtIndex(lines, index); 
     CGFloat ascent; 
     CGFloat descent; 

     CTLineGetTypographicBounds(line, &ascent, &descent, nil); 
     NSLog(@"line height: %f", ascent + (descent * 2)); 

     lineSpacing = ascent + (descent * 2); 
    } 
    free(origins); 
    CFRelease(lines); 
    //free(contentFrame); 

    NSLog(@"line spacing: %f", lineSpacing); 

    NSInteger numberOfLine = TEXT_PAGE_HEIGHT/(lineSpacing); 

    CGFloat pageHeight = numberOfLine * (lineSpacing); 
    self.pageHeight = pageHeight; 

    CGPathRelease(myPath); 
    CFRelease(framesetter); 
} 

私は行のコメントを解除した場合、CTFrameが出されますが、警告が表示されます。その後、漏れがあります

Passing CTFrameRef (aka const struct_CTFrame *) to parameter of type "void *' discards qualifiers) 

free(contentFrame); 

Mallocのための1つだけ。 計器ツールは、このコード行が漏れを引き起こしていることを知らせます。

CTFrameRef contentFrame = CTFramesetterCreateFrame(framesetter, myRange , myPath, nil); 

私はこれを説明するのに役立ちますが、私はなぜMallocが漏れているのか説明できません。どのように修正するには、どのようにCTFrameオブジェクトをリリースするには?

私はあまり研究していますが、解決策を見つけることができませんでした。

答えて

2

利用CFRelease代わりのfree、ドキュメントはCT*オブジェクトを解放するCFReleaseを使用して言及していないが、それだけで動作します。

0

問題は、これらの行である:最初の行で

CTFrameRef contentFrame = CTFramesetterCreateFrame(framesetter, myRange , myPath, nil); 
CFArrayRef lines = CTFrameGetLines(CFRetain(contentFrame)); 

contentFrameのカウンタが1で保持し、第二それは2

に増加では、CFRetain(呼び出してはならない)とするとき

CFRelease(contentFrame), contentFrame = NULL; 

また、CTFrameがNULLでないことを確認してください。それは作成されていない可能性があります。 ...行を解放しないでください!あなたはそれらのためのメモリを割り当てていない、あなたはちょうど参照を取得します。

あなたのコードは、そのような何か探している必要があり

(void)calculatePageHeight { 
    //__weak UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.view.bounds]; 

    NSString *sampleText = @"The CTFont opaque type represents a Core Text font object. Font objects represent fonts to an application, providing access to characteristics of the font, such as point size, transform matrix, and other attributes. Fonts provide assistance in laying out glyphs relative to one another and are used to establish the current font when drawing in a graphics context."; 
    NSRange contentRange = NSRangeFromString(sampleText); 
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:sampleText attributes:self.textAttributes]; 

    CFAttributedStringRef attributeRef = (__bridge CFAttributedStringRef)attributedString; 

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attributeRef); 
    if(framesetter == NULL) 
    { 
     [attributedString release], attributedString = nil; 
     return; 
    } 

    CGMutablePathRef myPath = CGPathCreateMutable(); 
    CGPathAddRect(myPath, self.view.bounds); 

    CFRange myRange = CFRangeMake(contentRange.location, contentRange.length); 

    CTFrameRef contentFrame = CTFramesetterCreateFrame(framesetter, myRange , myPath, nil); 
    if(contentFrame == NULL) 
    { 
     CFRelease(framesetter), framesetter = NULL; 
     [attributedString release], attributedString = nil; 
     return; 
    } 
    CFArrayRef lines = CTFrameGetLines(contentFrame); 
    NSInteger lineCount = CFArrayGetCount(lines); 
    CGPoint *origins = (CGPoint *)malloc(lineCount * sizeof(CGPoint)); 

    CTFrameGetLineOrigins(contentFrame, CFRangeMake(0, 0), origins); 
    CGFloat lineSpacing = 0.0f; 

    for (NSInteger index = 0; index < lineCount; index ++) { 
     CTLineRef line = CFArrayGetValueAtIndex(lines, index); 
     CGFloat ascent; 
     CGFloat descent; 

     CTLineGetTypographicBounds(line, &ascent, &descent, nil); 
     NSLog(@"line height: %f", ascent + (fabs(descent) * 2)); 

     lineSpacing = ascent + (fabs(descent) * 2); 
    } 
    free(origins); 
    //CFRelease(lines); 
    //free(contentFrame); 

    NSLog(@"line spacing: %f", lineSpacing); 

    NSInteger numberOfLine = TEXT_PAGE_HEIGHT/(lineSpacing); 

    CGFloat pageHeight = numberOfLine * (lineSpacing); 
    self.pageHeight = pageHeight; 

    CGPathRelease(myPath), myPath = NULL; 
    CFRelease(framesetter), framesetter = NULL; 
    CFRelease(contentFrame), contentFrame = NULL; 
    [attributedString release], attributedString = nil; 
} 
関連する問題