Memory management 如何使用核心文本发布核心基础对象

Memory management 如何使用核心文本发布核心基础对象,memory-management,ios5,memory-leaks,core-text,Memory Management,Ios5,Memory Leaks,Core Text,我有一个计算文本行高度的方法。但问题是它用两个项目泄漏内存:CTFrame和Malloc(48字节) 以下是该方法的核心: (void)calculatePageHeight { __weak UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.view.bounds]; NSString *sampleText = @"The CTFont opaque type represents a Core Text

我有一个计算文本行高度的方法。但问题是它用两个项目泄漏内存: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);
}
那么泄漏将只有一个用于Malloc。 仪器工具让我知道这行代码导致泄漏

CTFrameRef contentFrame = CTFramesetterCreateFrame(framesetter, myRange , myPath, nil);
任何人都可以帮我解释这一点,但我无法解释Malloc泄漏的原因。如何解决这个问题,如何释放CTFrame对象


我做了很多研究,但没有找到解决方案。

使用
CFRelease
而不是
free
,文档中没有提到使用
CFRelease
解除分配
CT*
对象,但它只是起作用。

使用
CFRelease
而不是
free
,文档中没有提到使用
CFRelease
解除分配
CT*
对象,但它确实有效。

问题在于以下几行:

CTFrameRef contentFrame = CTFramesetterCreateFrame(framesetter, myRange , myPath, nil);
CFArrayRef lines = CTFrameGetLines(CFRetain(contentFrame));
在第一行中,contentFrame的retain计数器是1,在第二行中它增加到2

您不应该调用CFRetain(),当您使用完它后,请编写:

CFRelease(contentFrame), contentFrame = NULL;
另外,请确保is 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;
}
(void)calculatePageHeight{
//__弱UIBezierPath*路径=[UIBezierPath bezierPathWithRect:self.view.bounds];
NSString*样本文本=@"CTFont不透明类型表示核心文本字体对象。字体对象表示应用程序的字体,提供对字体特征的访问,如点大小、变换矩阵和其他属性。字体有助于布置字形,并用于在gr中绘制时建立当前字体aphics上下文。”;
NSRange contentRange=NSRangeFromString(sampleText);
NSAttributedString*attributedString=[[NSAttributedString alloc]initWithString:sampleText属性:self.textAttributes];
CFAttributedStringRef attributeRef=(u桥CFAttributedStringRef)attributedString;
CTFramesetterRef framesetter=CTFramesetterCreateWithAttributedString(attributeRef);
if(framesetter==NULL)
{
[attributedString release],attributedString=nil;
返回;
}
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;
返回;
}
CFArrayRef lines=CTFrameGetLines(contentFrame);
NSInteger lineCount=CFArrayGetCount(行);
CGPoint*origins=(CGPoint*)malloc(lineCount*sizeof(CGPoint));
CTFrameGetLineOriginates(contentFrame、CFRangeMake(0,0)、Originates);
CGFloat线间距=0.0f;
对于(NSInteger index=0;index
问题出在以下几行:

CTFrameRef contentFrame = CTFramesetterCreateFrame(framesetter, myRange , myPath, nil);
CFArrayRef lines = CTFrameGetLines(CFRetain(contentFrame));
在第一行中,contentFrame的retain计数器是1,在第二行中它增加到2

您不应该调用CFRetain(),当您使用完它后,请编写:

CFRelease(contentFrame), contentFrame = NULL;
另外,请确保is 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;
}
(void)calculatePageHeight{
//__弱UIBezierPath*路径=[UIBezierPath bezierPathWithRect:self.view.bounds];
NSString*sampleText=@”CTFont不透明类型表示核心文本字体对象。字体对象表示应用程序的字体,提供对字体特征的访问,如点大小、变换矩阵和其他属性。字体有助于布置字形,并用于在gr中绘制时建立当前字体aphics上下文。”;
NSRange contentRange=NSRangeFromString(sampleText);
NSAttributedString*attributedString=[[NSAttributedString alloc]initWithString:sampleText属性:self.textAttributes];
CFAttributedStringRef attributeRef=(u桥CFAttributedStringRef)attributedString;
CTFramesetterRef framesetter=CTFramesetterCreateWithAttributedString(attributeRef);
if(framesetter==NULL)
{
[attributedString release],attributedString=nil;
返回;
}
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;
返回;
}
CFArrayRef lines=CTFrameGetLines(contentFrame);
NSInteger lineCount=CFArrayGetCount(行);
CGPoint*origins=(CGPoint*)malloc(lineCount*sizeof(CGPoint));
CTFrameGet