Question

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
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top