views:

88

answers:

2

I am at my wits end trying to come up with a design pattern for this paradigm. I haven't had much luck on this site but at this stage I'll try anything.

I am trying to implement a radar type animation and hence I am rotating a view 360 degrees to represent the radius rotating around the circle. I have placed points around this circle and am able to calculate the angle from the center of the circle using standard trig.

As the radius sweeps around the circle, if it intersects with a point (eg angle of the point equals the angle of the sweeping radius + a tolerance) the point flashes on.

Now, I have approached this paradigm in a number of ways but have not achieved an ideal solution. Here is what I have tried.

FIRST: iOS4 animation blocks. I would rotated the radius 10 degrees at a time with a duration of .1sec and in the completion method, check for intersections with points. The problem here is that if you set the option to repeat, then the completion method doesn't get called. The only time the completion method gets called is when the entire animation terminates, not after every repeat cycle, so this solution doesn't work.

SECOND: Tried explicit animation using CABasicAnimation. Same approach as above, rotating 10 degrees at every .1 seconds and setting the delegate to self and implementing the animationDidFinish method. In the animationDidFinish method, I checked for intersections with point. I set the animation to cumulative and repeatCound to Huge Value. The raduis rotates but once again, the animationDidFinish doesn't get called unless I set the repeatCount to a small number and then it only gets called at the end of the repeatCount, not after every repeat cycle.

THIRD: Using NSTimer and this approach actually works but the animation can be jerky depending on what is going on around the screen. I use a timer tick of .1 sec and initiate a single animation of 10 degrees as well as a intersection check at every tick. The problem with this approach is that it is susceptible to being stalled when starting each animation due to the processor doing other animations in the background. Note that i didn't have this problem with the other two approaches!

FOURTH: I tried using a combination of the two. CABasicAnimation on the radius and NSTimer on the Points. This issue here is that they can get out of sync and happens quite easily if the iDevice goes to sleep and then resumes.

FIFTH: Using the iOS3.0 style animation block and rotating 10 degrees with a duration of .1sec. Setting the delegate and the animationDidStopSelector with the animationDidStop method calling the animation method again as well as checking of intersection with points. This works too but much like the third solution, it is jerky when scrolling and other animations are happening. This is most likely caused by the stop start nature of the animation.

Basically, is there a way to animation a view infinitely but make it call a method after every repeat cycle? Or is there a way to make the third solution work more smoothly?

PLEASE HELP, I HAVE RUN OUT OF DESIGN PATTERNS.

A: 

I wonder if this would work:

UIView* yourView = ...;
// preparing the callbacks:
void(^)(void) animations = ...; // the animation would rotate 10 degrees
void(^)(BOOL) completion = ^(BOOL finished) {
  // do your radar stuff
  [UIView animateWithDuration:0.1 animations:animations completion:completion];
}

// the first call to start it all
[UIView animateWithDuration:0.1 animations:animations completion:completion];

The idea is to call the animation sequence again each time after finishing your radar activity, assuming the radar check is not a heavy one it should be smooth.

Aviad Ben Dov
I think the issue of keeping the animation smooth is to catch it before it completes so that you do not remove the animation layer and have to recreate it. However, I'll give it ago just in it calls this method prior to removing the animation layer and has the smarts to reuse the object and not create a new one.
Nader
Actually the more I think about it, the more I think this is like my fifth solution, but you never know.
Nader
Am not sure. It sounds similar, but this is more iOS 4.0 style. :-) Anyway, you should check your other animation properties if its too jerky - maybe the animation curve is wrong, or you should set "start animation from current position" or something.
Aviad Ben Dov
Resolved :-) if you agree with my answer, can you please vote it up.
Nader
+1  A: 

Got it working perfectly.

Here is what I did:

1/ Applied a CABasicAnimation rotation object to the layer to rotate 360 degrees every 2 sec. (don't need to make it cumulative that way)

2/ Set up a timer to call the presentation layer from the layer every .1 sec.

3/ Calculate the angle from the 3D transform stored in the presentation layer. Click here for my answer on how to do this.

4/ Check for intersecting angles.

Done :-)

Things to watch out for: The 3D transform is based on angles between 180 and -180 degrees and not 0 to 360 degrees Use atan2 and not atan as the later will only give angles in the first quadrant.

Nader