Magic Bullet Dave
Magic Bullet Dave

Reputation: 9076

UIView drawRect leak with CoreText

I have a leak that I can't track down. I am new to CoreText (and C in general) so please be gentle! The static analyser doesn't show any problems but Instruments does in this method:

- (void)drawAttributedStringInBubbleInContext:(CGContextRef)context {
    static CGFloat const kTextInset = 10;

    // Add the text to the bubble using an ellipse path inside the main speech bubble if the text property is set
    if (text) {

        // Create an attributed string from the text property
        NSMutableAttributedString *bubbleText = [[NSMutableAttributedString alloc] initWithString:text];        

        // Justify the text by adding a paragraph style
        CFIndex stringLength = CFAttributedStringGetLength((CFAttributedStringRef)bubbleText);
        CTTextAlignment alignment = kCTJustifiedTextAlignment;
        CTParagraphStyleSetting _settings[] = {
            {kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment}
        };      
        CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(_settings, sizeof(_settings) / sizeof(_settings[0]));
        CFRange stringRange = CFRangeMake(0, stringLength);
        CFAttributedStringSetAttribute((CFMutableAttributedStringRef)bubbleText, stringRange, kCTParagraphStyleAttributeName, paragraphStyle);
        CFRelease(paragraphStyle);      

        // Layout the text within an elliptical frame
        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)bubbleText);

        // Create elliptical path that is inset from the frame of the view
        CGMutablePathRef path = CGPathCreateMutable();
        CGRect drawingRect = self.bounds;
        drawingRect.origin.x = kTextInset;
        drawingRect.origin.y = kTextInset;
        drawingRect.size.width -= 2 * kTextInset;
        drawingRect.size.height -= 2 * kTextInset;
        CGPathAddEllipseInRect(path, NULL, drawingRect);

        // Create a text frame from the framesetter and the path 
        CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);

        // Draw the text frame in the view's graphics context
        CTFrameDraw(textFrame, context);

        // Clean up
        CGPathRelease(path);
        CFRelease(framesetter);
        [bubbleText release];
    }
}

The main culprit according to Instruments is the CTFrameRef textFrame = line, although I thought I have released everything properly.

Upvotes: 1

Views: 1603

Answers (1)

Joe
Joe

Reputation: 57179

That is the culprit, the Core Foundation rule for Create methods are you have to release them. Apple releases it properly in an example in the Core Text Programming Guide.

    // Clean up
    CGPathRelease(path);
    CFRelease(framesetter);
    CFRelease(textFrame);

Upvotes: 1

Related Questions