Performance issue with DrawRect and NSTimer
I'm trying to make a slot machine animation where the reels spin. to do this, I'm using drawRect to draw images in a custom class that inherits from UIView. I'm using an nstimer to update the position of the images and calling [self setNeedsDisplay] to update the drawing. In the simulator, it looks very good, however, on the device, it is very laggy. I was wondering if i'm doing something wrong with my method of drawing or is there any better solutions.
- (void)drawRect:(CGRect)rect
{
[image1 drawInRect:CGRectMake(0, image1Position, 98, 80)];
[image2 drawInRect:CGRectMake(0, image2Position, 98, 80)];
[image3 drawInRect:CGRectMake(0, image3Position, 98, 80)];
}
- (void)spin
{
// move each position down by 10 px
image1Position -= MOVEMENT;
image2Position -= MOVEMENT;
image3Position -= MOVEMENT;
// if any of the position <= -60 reset to 180
if(image1Position < -50)
{
image1Position = 180;
}
if(image2Position < -50)
{
image2Position = 180;
}
if(image3Position < -50)
{
image3Position = 180;
}
[self setNeedsDisplay];
}
-(void)beginSpinAnimation
{
timer = [NSTimer scheduledTimerWithTimeInterval:SCROLL_TIME target:self selector:@selector(spin) userInfo:self repeats:YES];
}
My CoreAnimation Attempt with UIScrollView:
- (void) spinToNextReel
{
int y = self.contentOffset.y + 80;
// if the current >= last element reset to first position (-30)
if(y >= (80 *(elementCount+1) - 30))
{
y = -30;
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:SCROLL_TIME];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
开发者_开发问答self.contentOffset = CGPointMake(0, y);
[UIView commitAnimations];
if (!isSpinning && targetY == y)
{
NSLog(@"target is %d, y is %d", targetY, y);
if(timer)
{
[timer invalidate];
timer = nil;
}
[self playSound];
}
}
I would say research into CoreAnimation. It is made to do what you want to do here. It'll be much faster than what you are doing here.
As for it being slow, calling drawInRect isn't the fastest thing in the world. What is SCROLL_TIME?
You want to use CoreAnimation, it will be a lot easier, and more efficient. Having said that, if you insist on trying to manually animate this way you are doing a couple of thing wrong:
Do not attempt move a constant amount on fixed intervals, timer events can be delayed, and if they are that will result in your animation being uneven, since you are moving a constant amount per event, not per time interval. You should record the actual timestamp every time you animate, compare it to the previous timestamp, and move an appropriate number of pixels. This will result in even amounts of movement even if the events are delayed (effectively you will being dropping frames).
Do not use an NSTimer, use a CADisplayLink. That will tie your drawing to the native refresh rate of the system, and synchronize it with any other drawing that is going on.
I know I said it already, but learn and use CoreAnimation, you will be much happier.
精彩评论