0

テキスト行の高さを計算するメソッドがあります。ただし、問題は、CTFrameとMalloc(48バイト)の2つの項目でメモリがリークすることです。

その方法の中核は次のとおりです。

(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オブジェクトを解放する方法も?

私はたくさん研究しましたが、解決策を見つけることができませんでした。

4

2 に答える 2

3

CFReleaseの代わりにを使用すると、ドキュメントではオブジェクトの割り当てを解除するためfreeの使用については言及されていませんが、機能するだけです。CFReleaseCT*

于 2012-05-11T03:56:11.660 に答える
0

問題は次の行にあります。

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

最初の行では、contentFrameの保持カウンターは1ですが、2番目の行では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;
}
于 2012-12-19T18:11:36.157 に答える