1

I have translated some code of a library to ARC and i suspect I have failed to do so properly. Basically i have added som __bridge commands to the code. Xcode complains during analyze, saying that there is a potential leak of an object stored in path. The code is attached below. Can you help me fix the potential leak issue of the next to last line:

-(void)drawRect:(CGRect)rect {
    if(self.text.length<=0) {
        self.text = EMPTY;
        return;
    }

    //Prepare View for drawing
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context,CGAffineTransformIdentity);
    CGContextTranslateCTM(context,0,([self bounds]).size.height);
    CGContextScaleCTM(context,1.0,-1.0);

    //Get the view frame size
    CGSize size = self.frame.size;

    //Determine default text color
    UIColor* textColor = nil;
    if(!self.highlightColor||!(textColor=[self.highlightColor objectForKey:kRegexHighlightViewTypeText])) {
        if([self.textColor isEqual:[UIColor clearColor]]) {
            if(!(textColor=[[RegexHighlightView highlightTheme:kRegexHighlightViewThemeDefault] objectForKey:kRegexHighlightViewTypeText]))
               textColor = [UIColor blackColor];
        } else textColor = self.textColor;
    }

    //Set line height, font, color and break mode
    CGFloat minimumLineHeight = [self.text sizeWithFont:self.font].height,maximumLineHeight = minimumLineHeight;
    CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)self.font.fontName,self.font.pointSize,NULL);
    CTLineBreakMode lineBreakMode = kCTLineBreakByWordWrapping;

    //Apply paragraph settings
    CTParagraphStyleRef style = CTParagraphStyleCreate((CTParagraphStyleSetting[3]){
        {kCTParagraphStyleSpecifierMinimumLineHeight,sizeof(minimumLineHeight),&minimumLineHeight},
        {kCTParagraphStyleSpecifierMaximumLineHeight,sizeof(maximumLineHeight),&maximumLineHeight},
        {kCTParagraphStyleSpecifierLineBreakMode,sizeof(CTLineBreakMode),&lineBreakMode}
    },3);
    NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)font,(NSString*)kCTFontAttributeName,(__bridge id)textColor.CGColor,(NSString*)kCTForegroundColorAttributeName,(__bridge id)style,(NSString*)kCTParagraphStyleAttributeName,nil];

    //Create path to work with a frame with applied margins
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path,NULL,CGRectMake(MARGIN+0.0,(-self.contentOffset.y+0),(size.width-2*MARGIN),(size.height+self.contentOffset.y-MARGIN)));


    //Create attributed string, with applied syntax highlighting
    CFAttributedStringRef attributedString = (__bridge CFAttributedStringRef)[self highlightText:[[NSAttributedString alloc] initWithString:self.text attributes:attributes]];

    //Draw the frame
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0,CFAttributedStringGetLength(attributedString)),path,NULL);
    CTFrameDraw(frame,context);
}

Here is a preview from the profiling after releasing path

David Karlsson
  • 9,396
  • 9
  • 58
  • 103

2 Answers2

3

HaIR's definition is a little incomplete: The compiler only manages Objective-C types. Anything that follows the create rule, or is malloc'd, calloc'd or new'd onto the heap is your responsibility. The memory leaks you've got stem from 4 distinct instances of not balancing a function with create in it's name with the properly prefixed ...release() call.

You can fix number 1 with a call to CGPathRelease(), number 2 with a call to -autorelease for that attributed string (assuming ARC is off, which given the circumstances, it is if Instruments is complaining), numbers 3 and 4 can be fixed with two calls to CFRelease().

CodaFi
  • 43,043
  • 8
  • 107
  • 153
  • what do you mean arc is of? this is an ARC activated project – David Karlsson Jun 08 '13 at 08:41
  • 1
    Yes, but if the setter is complaining, then either you're indirectly retaining the returned object (resulting in a +2 reference count), or that call to create a frame setter is retaining the string (unlikely). It should go away when you release the frame setter properly if ARC is enabled. – CodaFi Jun 08 '13 at 08:47
  • also i cant find the function CTRelease, do i need some extra import for this? Thank you – David Karlsson Jun 08 '13 at 08:51
  • My bad, typo. It should say CFRelease() – CodaFi Jun 08 '13 at 08:53
0

In the manual, it mentions that the compiler doesn't automatically manage CF objects. You must call CFRetain and CFRelease, according to CF memory management rules.

so you need a CGPathRelease(path); at some point.

HalR
  • 11,411
  • 5
  • 48
  • 80
  • do i also need to handle: __bridge CFAttributedStringRef) differently? – David Karlsson Jun 08 '13 at 07:42
  • I'm 98% sure that its ok ;) So I looked for a few specific Questions about it, like this one: http://stackoverflow.com/q/10285149/793607 – HalR Jun 08 '13 at 07:47
  • I think you need to cast the CFAttributedString stuff on the other two lines with __block. But I'm feeling blasted... – HalR Jun 08 '13 at 07:51