I have a custom button which is my own subclass of UIButton. It looks like a circled arrow, starting at some angle startAngle end finishing at some endAngle=startAngle+1.5*M_PI.
startAngle is a button’s property which is then used in its drawRect: method.
I want to make this arrow to continuously rotate by 2Pi around its center when this button is pressed. So I thought that I can easily use [UIView beginAnimations: context:] but apparently it can’t be used as it doesn’t allow to animate custom properties. CoreAnimation also doesn’t suite as it only animates the CALayer properties.
So what is the easiest way to implement an animation of a custom property of UIView subclass in iOS?
Or maybe I missed something and it is possible with already mentioned techniques?
Thank you.
Thanks to Jenox I have updated animation code using CADisplayLink which seems to be really more correct solution than NSTimer. So I show the correct implementation with CADisplayLink now. It is very close to the previous one, but even a bit simpler.
We add the QuartzCore framework to our project.
Then we put the following lines in the header file of our class:
Now in implementation file we set the values for duration of the animation and the other initial values:
To start the animation we need to create the CADisplayLink instance which will call method
animateand add it to main RunLoop of our application:This timer will call
animatemethod every runLoop of the application.So now comes the implementation of our method for updating the property after each loop:
So unlike case with NSTimer we now don’t need to calculate the time interval at which to update the angle property and redraw the button. We now only need to count how much time has passed from the start of animation and set the property to value which corresponds to this progress.
And I must admit that animation works a bit more smoothly than in case of NSTimer.
By default, CADisplayLink calls the
animatemethod each run loop. When I calculated the frame rate, it was 120 fps. I think that it is not very efficient so I have decreased the frame rate to just 22 fps by changing the frameInterval property of CADisplayLink before adding it to mainRunLoop:It means that it will call the
animatemethod at first run loop, then do nothing next 3 loops, and call on the 4-th, and so on. That’s why frameInterval can be only integer.