CTLineRef可能出现内存泄漏?

时间:2014-07-23 18:02:28

标签: ios cocoa-touch

我的代码中有内存泄漏,我无法解决问题。具体来说,我在这一行得到一个EXC_BAD_ACCESS(代码= 1):

CGFloat xStart = origin.x + CTLineGetOffsetForStringIndex(line, index, NULL);

在以下代码中:

- (CGRect)firstRectForNSRange:(NSRange)range;
{
    NSInteger index = range.location;

    NSArray *lines = (__bridge NSArray *) CTFrameGetLines(self.textFrame);
    NSInteger linesCount = [lines count];
    CFIndex paragraphSpacingOffset = (self.paragraphSpacing > 0) ? 1 : 0;

    for (NSInteger i = 0 + paragraphSpacingOffset; i < (linesCount - paragraphSpacingOffset); i++)
    {
        CTLineRef line = (CTLineRef) CFBridgingRetain([lines objectAtIndex:i]);
        CFRange lineRange = CTLineGetStringRange(line);
        NSInteger localIndex = index - lineRange.location;

        if (localIndex >= 0 && localIndex < lineRange.length)
        {
            NSInteger finalIndex = MIN(lineRange.location + lineRange.length, range.location + range.length);

            CGPoint origin;
            CTFrameGetLineOrigins(self.textFrame, CFRangeMake(i, 0), &origin);
            CGFloat xStart = origin.x + CTLineGetOffsetForStringIndex(line, index, NULL);
            CGFloat xEnd = origin.x + CTLineGetOffsetForStringIndex(line, finalIndex, NULL);
            CGFloat ascent, descent;
            CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
            CFRelease(line);
            return CGRectMake(xStart, origin.y - descent, xEnd - xStart, ascent + descent);
        }
        else
        {
            CFRelease(line);
        }
    }

    return CGRectNull;
}

我几乎可以肯定这是内存泄漏,因为我已经彻底检查了代码。任何人都可以看到我如何管理上面的Core Foundation对象line?当line被发送到CTLineGetOffsetForStringIndex我需要再次发布时,会发生什么事吗?

1 个答案:

答案 0 :(得分:1)

你的问题几乎肯定在这里:

CTFrameGetLineOrigins(self.textFrame, CFRangeMake(i, 0), &origin);

这表示&#34;将来自索引i的行原点通过帧结尾写入origin指向的内存。&#34;不幸的是,origin仅指向一个元素,因此您将遍布堆栈的其余部分。我怀疑你的意思是CFRangeMake(i, 1)

其他说明:

你在CFArray和NSArray之间移动创造了很多复杂性。如果你只使用CFArray,代码会简单得多:

CFArrayRef lines = CTFrameGetLines(self.textFrame);
CFIndex linesCount = CFArrayGetCount(lines);
...

  CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, i);

这样做,您不需要拨打CFRelease()。您现在拨打CFRelease的唯一原因是因为您正在调用CFBridgingRetain(),这使得一切都变得比它需要的更复杂。有时候接触NSArray是一件非常棒的事情,但在这种情况下它并非如此。