uiscrollview personalizado no se desplaza (usando coretext)

I am using CoreText to draw text in multiple columns (depending on the orientation of the iPad).

To test, I've created an NSMutableString composed of the numbers 100 - 999. This text spans 5 columns, 1 or 2 of which are onscreen (depending on the orientation).

To my main ViewController I've added a custom UIScrollView to hold this text, and I want it to be scrollable.

I've noticed that the scrollview doesn't scroll until I set:

[myScrollView setContentMode:UIViewContentModeRedraw];

I do want the scrollView to call drawRect when the iPad is rotated (to adjust the number of columns)!

My issue with this though is that it seems to call drawRect over and over and over ... while scrolling (and thus allocates more and more memory, also causing some lag).

I add the UIScrollView to my main viewController like so:

myScrollView = [[CoreTextTestUIView alloc] init];
myScrollView.parentView = self;
if(FACING == @"PU" || FACING == @"PD")
{
    myScrollView.frame = CGRectMake(0,50,768,974);
}
else
{
    myScrollView.frame = CGRectMake(0,50,1024,718);
}
[myScrollView setContentMode:UIViewContentModeRedraw];
[container addSubview:myScrollView];

Again, I want drawRect to be called when the iPad is rotated, so the number of columns can change ... BUT I do not want it to call drawRect when I simply try to scroll the UIScrollView.

¿Puede alguien ayudarme por favor?

...

below is the .m for my UIScrollView:

#import "CoreTextTestUIView.h"
#import <CoreText/CoreText.h>

@implementation CoreTextTestUIView

@synthesize parentView;


NSMutableString *testText;



-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        // Initialization code

        //set BG color
        self.backgroundColor = [[UIColor alloc] initWithRed:134 green:166 blue:228 alpha:1.0];

        //UIScrollView Stuff
        //self.delegate = self;
        self.scrollEnabled = YES;
        self.pagingEnabled = YES;
        self.userInteractionEnabled = YES;
        [self becomeFirstResponder];
        self.showsVerticalScrollIndicator = NO;
        self.showsHorizontalScrollIndicator = NO;
        self.bounces = NO;
        self.alwaysBounceHorizontal = YES;
        self.alwaysBounceVertical = NO;

        //generate long text
        testText = [[NSMutableString alloc] initWithString:@""];
        for(int i = 100; i < 1000; i++)
        {
            [testText appendString:[NSString stringWithFormat:@"%i ",i]];
        }

        self.alpha = 0.0;
        [self fadeIn];
    }
    return self;
}



-(void)fadeIn
{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];  
    [UIView setAnimationDelegate:self]; 
    //[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];  
    self.alpha = 1.0;
    [UIView commitAnimations];
}



// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
-(void)drawRect:(CGRect)rect
{

    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@",testText]];

    //set font
    CTFontRef helvetica = CTFontCreateWithName(CFSTR("Helvetica"), 40.0, NULL);
    [string addAttribute:(id)kCTFontAttributeName
                   value:(id)helvetica
                   range:NSMakeRange(0, [string length])];


    //layout master
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);

    //flip the coordinate system
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    int textPos = 0;
    int columnIndex = 0;

    //how many columns? (orientation dependent)
    float howManyColumns;
    if(parentView.FACING == @"PU" || parentView.FACING == @"PD")
    {
        howManyColumns = 1.0;
    }
    else
    {
        howManyColumns = 2.0;
    }

    //create columns in loop
    while(textPos < [string length])
    {
        NSLog(@"column started");

        //column form
        CGMutablePathRef columnPath = CGPathCreateMutable();
        CGPathAddRect(columnPath, NULL, 
                      CGRectMake((self.bounds.size.width/howManyColumns*columnIndex), 0, 
                                 (self.bounds.size.width/howManyColumns),
                                 self.bounds.size.height));

        //column frame
        CTFrameRef columnFrame = CTFramesetterCreateFrame(framesetter, 
                                                             CFRangeMake(textPos, 0),
                                                             columnPath,
                                                             NULL);

        //use the column path
        CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(textPos, 0), columnPath, NULL);
        CFRange frameRange = CTFrameGetVisibleStringRange(frame);

        //draw
        CTFrameDraw(columnFrame, context);

        //cleanup
        CFRelease(columnFrame);
        CGPathRelease(columnPath);

        textPos += frameRange.length;
        columnIndex++;
    }

    //set scrollView content size
    int totalPages = (columnIndex+1)/howManyColumns;
    self.contentSize = CGSizeMake(totalPages*self.bounds.size.width, self.frame.size.height);

    //release
    CFRelease(framesetter);
    [string release];
}



-(void)dealloc
{
    [super dealloc];

    [parentView release];
    [testText release];
}


@end

preguntado el 22 de mayo de 12 a las 16:05

2 Respuestas

Looking at this, I can't see where you are setting the contentSize of your scrollView. If you do not set the contentSize of your scrollView, scrolling will not be enabled, and you will only see what fits within the current area of the scrollView. Also, if your text is static in a configuration, consider optimizing out some of the redrawing that is occurring and add it to a subview of the scrollView.

contestado el 22 de mayo de 12 a las 17:05

I had included a setContentSize call deep within the drawRect method ... but the solution was to draw all the text into a UIView, then include the whole view inside a UIScrollView (as @heckman suggested)!!! Thanks a bundle!!! - chris allinson

@Chris Allinson If your setContentSize was embedded in this drawRect method, it is likely that this is why you were able to scroll after you performed <code>[myScrollView setContentMode:UIViewContentModeRedraw];</code> - Diablos

@ChrisAllinson Is this resolved then? Can you accept someone's answer so that I can stop looking back at this. - Diablos

SUCCESS!!! The solution was to draw the text in a UIView, and then add that UIView to a UIScrollView ... this way the drawRect doesn't get called over and over (as it did when I drew into the UIScrollView itself) ... THANKS!!! - chris allinson

@ChrisAllinson Glad to hear it! - Diablos

That is how drawRect works. It is called every single time that the view moves or changes or has something overlapping it. If you are managing memory correctly this shouldn't be a problem.

contestado el 22 de mayo de 12 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.