0

I have created a core text view and visually it's working great but i run it for 30 minutes with a lot of data coming in and it crashes. The debugger starts saying 'received memory warning'. I think the views i'm drawing that refresh on every new line that comes in from telnet, are not leaving memory on a redraw completely. code below. The first part of this code might be an issue. I found on a redraw i had to clear the old views or it over layed or drew on top and text got garbled. But it could be any of my variables that i create that are becoming persistent.

- (void)buildFrames
{

    for (UIView __strong *view in self.subviews) {
        [view removeFromSuperview];
        view = nil;
    }



    frameXOffset = 20; //1
    frameYOffset = 0;
    double height=0;
    double oldHeight = 0;
    int columnIndex = 0;
    self.frames=nil;
    self.frames = [NSMutableArray array];
    // self.pagingEnabled = YES;
    self.delegate = self;
    CGRect textFrame = CGRectInset(self.bounds, frameXOffset, frameYOffset);
    // set string
    int spot =0;
    if(self.chatLog != nil && self.chatLog != NULL)
      if(self.chatLog.total > 300)
          spot = self.chatLog.total - 300;
    if(spot < 0)
        spot=0; // double check for thread saftey;
    int _total = self.chatLog.total;
    if(_total < 0 || _total > self.chatLog.max)
        return;

    if(self.chatLog != nil && self.chatLog != NULL)
        for(int index = spot; index < _total; index ++)
        {

            NSString *theTell = [self.chatLog getChatAt:index];
             NSString *chatType = [self.chatLog getTypeAt:index];

            if(theTell == nil || theTell == NULL)
            {    theTell=@"nil";

                 chatType = @"line";
            }
        attString=nil;
        attString = [[NSMutableAttributedString alloc] initWithString:theTell];



            //else
    //    attString = [[NSAttributedString alloc] initWithString:@"Hello core text world"];

    CTFontRef font = CTFontCreateWithName(CFSTR("Courier"), self.fontSize, NULL);
    CFAttributedStringSetAttribute((__bridge CFMutableAttributedStringRef)(attString), CFRangeMake(0, CFAttributedStringGetLength((__bridge CFAttributedStringRef)(attString))), kCTFontAttributeName, font);
if([chatType isEqual: @"line"])
{
CFAttributedStringSetAttribute((__bridge CFMutableAttributedStringRef)(attString), CFRangeMake(0, CFAttributedStringGetLength((__bridge CFAttributedStringRef)(attString))), kCTForegroundColorAttributeName, _lineColor);    

}
else if([chatType isEqual: @"notify"])
{
CFAttributedStringSetAttribute((__bridge CFMutableAttributedStringRef)(attString), CFRangeMake(0, CFAttributedStringGetLength((__bridge CFAttributedStringRef)(attString))), kCTForegroundColorAttributeName, _notifyColor);
}
else if([chatType isEqual: @"tell"])
{
    CFAttributedStringSetAttribute((__bridge CFMutableAttributedStringRef)(attString), CFRangeMake(0, CFAttributedStringGetLength((__bridge CFAttributedStringRef)(attString))), kCTForegroundColorAttributeName, _tellColor);
}
else
{
CFAttributedStringSetAttribute((__bridge CFMutableAttributedStringRef)(attString), CFRangeMake(0, CFAttributedStringGetLength((__bridge CFAttributedStringRef)(attString))), kCTForegroundColorAttributeName, _defaultColor);        
}

    textFrame =  CGRectMake(0, 0, self.bounds.size.width, self.fontSize+4);
    CGMutablePathRef path = CGPathCreateMutable(); //2
       CGPathAddRect(path, NULL, textFrame );

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attString);
    int textPos = 0; //3

    while (textPos < [attString length]) { //4


    //  CGPoint colOffset = CGPointMake( (columnIndex+1)*frameXOffset + columnIndex*(textFrame.size.width), 20 );
        CGPoint colOffset = CGPointMake(  20, (columnIndex+1)*frameYOffset + columnIndex*(textFrame.size.height) );
        CGRect colRect = CGRectMake(0, 0 , textFrame.size.width-10, textFrame.size.height);// was -40

        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddRect(path, NULL, colRect);

        //use the column path
        CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(textPos, 0), path, NULL);
        CFRange frameRange = CTFrameGetVisibleStringRange(frame); //get visiblestringrange
        //create an empty column view
        CTColumnView *content = [[CTColumnView alloc] initWithFrame: CGRectMake(0, 0, self.contentSize.width, self.contentSize.height)];
        content.backgroundColor = [UIColor clearColor];
        content.frame = CGRectMake(colOffset.x, colOffset.y, colRect.size.width, colRect.size.height) ;

        //set the column view contents and add it as subview
        [content setCTFrame:(__bridge id)frame];  //6
        [self.frames addObject: (__bridge id)frame];
        [self addSubview: content];

        //prepare for next frame
        textPos += frameRange.length;

        //CFRelease(frame);
        CFRelease(path);

        columnIndex++;
        oldHeight = height;
        height= [self measureFrameHeight:frame];

    }
        }// end while
    //set the total width of the scroll view
    int totalPages = (columnIndex) ; //7
   // self.contentSize = CGSizeMake(totalPages*self.bounds.size.width, textFrame.size.height);


    self.contentSize = CGSizeMake(textFrame.size.width, (textFrame.size.height ) * (totalPages -1) + height + 40 );

   [self scrollRectToVisible:CGRectMake(0, 0 , textFrame.size.width-10,  (textFrame.size.height) * (totalPages -1) + height +40 ) animated: FALSE];



}

the class definition is:

@interface ConsoleView :UIScrollView<UIScrollViewDelegate>
{
    float frameXOffset;
    float frameYOffset;

    NSMutableArray *frames;

}
@property  (strong, nonatomic) NSAttributedString *attString;
-(void) addNewText:(NSString *) text;
@property (weak, nonatomic) NSMutableArray *frames;// was reatin not strong
- (void)buildFrames;
@property (strong, nonatomic) ChatTextQueue *chatLog;
@property (nonatomic) int fontSize;
@property  (strong, nonatomic) UIColor *userColor;
@property (nonatomic) CGColorRef notifyColor;
@property (nonatomic) CGColorRef lineColor;
@property (nonatomic) CGColorRef defaultColor;
@property (nonatomic) CGColorRef tellColor;

@end
LanternMike
  • 664
  • 1
  • 5
  • 16

1 Answers1

1

you are not releasing some objects, for example font, framesetter and frame. Use the Analyze command in xCode to find all memory leaks in your buildFrames method.

Jonathan Cichon
  • 4,396
  • 16
  • 19
  • did analyze. have one memory issue it says. pottential leak into object stored into path – LanternMike Feb 17 '13 at 13:34
  • now releasing font framesetter and frame as well and will see if it fixes it – LanternMike Feb 17 '13 at 14:24
  • from the apple developer documentation on core text, they release framesetter and frame but not font so not relasing font now and i guess i will see. was over releasing releasing font and color and had crashes. now i'm trying to match apple page on what to release. – LanternMike Feb 17 '13 at 17:44
  • In addition to Xcode's Analyze command (which you really should turn on to run on every build in the build settings), it's worth running the app under Instruments's Leaks template, which will show you the graph of your memory usage and tell you just what's taking up all that space in memory. – Peter Hosey Feb 18 '13 at 05:20