Or Ron
Or Ron

Reputation: 2343

How to use DrawRect correctly

Im currently building Custom UIActivityIndicator. In order to do that I created the following draw rect function:

-(void) drawRect:(CGRect)rect  
{
CGPoint point;
NSLog(@"here %d",stage);`

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx, 2.0);

for (int i = 1 ; i<=10; ++i) {


    CGContextSetStrokeColorWithColor(ctx, [[self getColorForStage:stage+i WithAlpha:0.1 *i] CGColor]);
    point = [self pointOnOuterCirecleWithAngel:stage+i];
    CGContextMoveToPoint(ctx, point.x, point.y);
    point = [self pointOnInnerCirecleWithAngel:stage+i];
    CGContextAddLineToPoint( ctx, point.x, point.y);
    CGContextStrokePath(ctx);
}



stage++;
}

And i added an NSTimer to call [self setNeedsDisplay];

The animation works fine BUT when I import it to my application every time i will scroll a table or do anything the animation will stop until the table stops moving.

I assume that only after the UI finish to update it update my DrawRect but how can I work around it OR do it the right way

Upvotes: 2

Views: 1374

Answers (3)

user3126875
user3126875

Reputation: 21

you shouldn't call [self setNeedsDisplay]; Do it in the view didload

Upvotes: 1

omz
omz

Reputation: 53561

You have to schedule your timer manually with a different runloop mode, if you want it to fire while a table view (or any other scroll view) is scrolling. By default, timers don't fire while scrolling to improve performance.

NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

(you'd get the default behavior with NSDefaultRunLoopMode instead of NSRunLoopCommonModes.)

Upvotes: 3

morningstar
morningstar

Reputation: 9162

It would have helped if you described what your desired result would look like. From looking at the code it looks like you are trying to achieve a multi-colored ring. You refer to animation, but there is no true animation here. It might look animated, based on making it redraw at an interval, but I'm not sure even how that is happening. If it redraws the exact same thing every time, you won't see anything that looks like motion. Do the methods you call (getColorForStage and pointOnOuterCirecleWithAngel) return different results for the same arguments each time you process drawRect?

You should not use drawRect to achieve animation. drawRect should make your view look like it's supposed to look, and then do nothing until it's needed again. Often it doesn't need to be called again at all unless the view is hidden and the OS recycled the memory that was holding its pixels. The purpose of setNeedsDisplay is to trigger drawRect being called again because the information the view represents has changed, not to update an ongoing animation of the same data. You can change the appearance of a view in a lot of ways that don't involve drawRect running again, such as changing its size, position, alpha, or rotating it.

I wouldn't be surprised if drawRect does not get called during pan and zoom, and calls to setNeedsDisplay are queued until after the adjustment of the view.

You should be using Core Animation. Hopefully Core Animation will keep running during pan and zoom. You should be able to achieve the kind of effect you want by drawing your icon with one call to drawRect and then using Core Animation to rotate it or something.

Upvotes: 1

Related Questions