How can I make an animated timer - objective-c

Hi I need to make an animated timer like this:
for an iPhone Application using Objective C.
I really don't know what to do. Any Helps?
Thanks.

Have a look at DACircularProgress, it implements a circular progress view. As others said, you would increment the progress value with a NSTimer.

Just calculate the angle from the top using the ratio between elapsed time and the total time. Seems really simple. The timer can fire regularly and redo this calculation.
The image above looks like there are two circles with the same midpoint but slightly different radius superimposed on each other. The timer firing could also update this display.
It could also update the labels inside the circles, but I really do not understand "2 days 24 hours"....

That timer looks like it can be made using a pie chart with a mask on top of it.
Actually, you can use a png with the black circle transparent and draw the pie chart behind.
[edit] my answer assumes you know how to handle the timer part. If you want, I could also give you some info on that
This code starts a timer that would fire a function every two seconds
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(timePassed) userInfo:nil repeats:YES];
You can then make a function like this
-(void)timePassed {
//draw a bigger pie chart than the previous
//you can store the previous size inside a class property or global var
}
Don't forget to stop the timer when you're done with it
[self.timer invalidate];

This is a relative question I answered before (if u are only focusing on using the NSTimer to do animation )
Objective c - NSTimer, CADisplayLink, Thread
Hope it helps you

Related

Call method repeatedly after time delay until end condition reached

I have a crosshair on the iphone screen and when a pavilion (dot on map) moves under it i want to start zooming on the map.
I all ready got the detection to work when a pavilion comes under the crosshair and the moment it is not under it anymore.
For now i post it in here in psuedo code:
- (void) checkForPavilionUnderCrosshair {
if(new pavilion under crosshair) {
// start zooming
}
else if(just left pavilion under crosshair){
// stop zooming
}
}
So what i need to do now is keep triggering:
mapView setZoom:(mapView.zoom+0.1) animated:NO];
And being able to stop that progress when the crosshair moves off the pavilion.
I did some searches on stackoverflow but the posts i found did not include stopping it for example. I have no experience with timing things in programs so could someone help me a litle by telling what i'm looking for?
I tried
[self performSelector:#selector(zoomTest) withObject:self afterDelay:0.0];
If i keep touching the map and move my finger then it keeps checkForPavilionUnderCrosshair just like i want.
But the perform selector get's fired after i stop touching the screen, so if i touch the screen for 20 seconds it fires 20 seconds to late.
Any workaround for that?
You can call [self performSelector:#selector(checkForPavilionUnderCrosshair) withObject:nil afterDelay:1.0] at the end of your method to have it called again after the specified time period. Note that the delay is in seconds.
If you want something more advanced, you can look at NSTimer over at the Apple docs, or see this SO question for an example and explanation.
If you decide to use the simple performSelector method, you can simply not call the method when you don't want to repeat anymore. If you choose to use NSTimer, call invalidate on the timer to stop it.

Time Intervals in Objective C

I am very very new to Objective C and x-code. I just started learning it last week. so sorry if the question is too simple.
I am doing a game more like a visual novel so its very simple and story board based app, but I have a question regarding displaying my choices. I want the choices to appear after my cut scene ends. is there any way I can add something like time-interval breaks so they only appear after certain time. can some one please guide me on how to go about it.
You can use NSTimer:
[NSTimer scheduledTimerWithTimeInterval:2.0f
target:self
selector:#selector(displayChoiceTimerFired:)
userInfo:nil
repeats:NO];
This will schedule a timer that will execute the displayChoiceTimerFired: method after 2 seconds. (The argument of that method is the timer itself.)
Or you can also use NSObject's perform methods:
[self performSelector:#selector(displayChoice:) withObject:nil afterDelay:2.0f];
Depending on how you are displaying your cut scenes, the safer way to display these UI elements would be to somehow trigger an action when your cut scene ends. The problem with the NSTimer Implementation I can foresee is if, for whatever reason, your cut scene takes longer to play than your NSTimer interval is set to, then your UI Elements are displayed prematurely. Just my two cents on a different, but what I believe to be a more elegant approach.
[self performSelector:#selector(displayChoice:) withObject:nil afterDelay:1.0];
You can use this method...where after delay is number of seconds

Is there a way to programmatically "tap" UIControls such as segment buttons?

I hope that the answer to my question may be useful to a lot of developers and fear that it is a really stupid question: I have a routine that graphically and programmatically shuffle cards in 5 different ways (including cut and deal.) This is implemented from a UISegmentControl, replacing a 5-button Modal Alert. This all works very well but here is the problem: When it is the computer's turn to deal I built a for-loop inside a for-loop to trigger random number generated calls to the shuffling graphic routines a random number of times < 10. All of the calls seem to be executed for the entire for-loops sets before any graphics show up on the screen. Then I see face-down and face up cards moving all over the screen. Psychedelic, right? It seems that my control loop logic is executing without blocking or waiting or serializing the graphics. Remember that the graphics work fine when the user is tapping one segment at a time. I have been considering implementing a UITouchEvent to programmatically simulate tapping the buttons but I haven't found a single example. Is it possible to programmatically "tap" the segment "buttons"?
you can do something like:
- (void)simulateButtonPressed {
[button sendActionsForControlEvents:UIControlEventTouchDown];
button.highlighted = YES;
[NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:#selector(simulateButtonTimeElapsed:) userInfo:nil repeats:NO];
}
- (void)simulateButtonTimeElapsed:(NSTimer *)timer {
button.highlighted = NO;
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
}

Swapping UIImageView Images in a loop

I have a NSArray of UIImageViews that I want to loop over and quickly swap out an "on" and "off" state. I wrote the code to do so in a for loop instead a method that was called when the user tapped a UIButton ( the button's action ).
Here's that loop:
for(int i = 0; i < [Images count]; i++) {
if( i > 0 ){
[self toggleImageViewOff:[Images objectAtIndex:i - 1]];
}
[self toggleImageViewOn:[Images objectAtIndex:i]];
[NSThread sleepForTimeInterval:0.5f];
}
The UI did not update as I expected as I only ever saw the last UIImageView in the "on" state. I figured that the drawing update of the views must occur in the main thread this code was also executing in. So I learned about performSelectorInBackground:withObject: . Performing the toggleImageViewOn/Off methods using this made the loop work. The problem is if I make the sleep interval too short I can have an "on" update after an "off" with Threads operating out of order.
So I had the bright idea of moving the whole loop with the sleep into its own method and calling that from the action method using performSelectorInBackground:withObject: . I tried that and I'm back to not getting an updated view until the loop is over.
That's a long winded way to get to my question:
What's the best way to animate this to guarantee the on/off code fires in the right order and still get view updates, even at high speeds? ( i.e. looping very quickly )
I tried to think about how I'd do it with CoreAnimation, but I can't seem to get my head around how to do it there.
For bonus, here are the toggle methods:
- (void)toggleImageViewOn:(UIImageView *)theImageView {
[theImageView setImage:[UIImage imageNamed:#"on.png"]];
}
- (void)toggleImageViewOff:(UIImageView *)theImageView {
[theImageView setImage:[UIImage imageNamed:#"off.png"]];
}
Did you set up an animation context (UIView class method does that) around this for loop? Without it changes are immediate instead of animated.
The problem is that you are not giving any of the UIImages time to draw. The drawing code is optimised to only draw what's needed - rendering all those intermediate stages is optimised out.
Sleeping the main thread doesn't actually give it chance to run.
Bill is right in that you need to set up an animation context around your loop. This will capture all of the UIView changes you make and then play them out. The easiest way to do this is using Core Animation. Core animation 'records' changes in UIElemenets and plays them back. Your code (without the sleep) will work just fine in a Core Animation block.
Apple have a reasonable cookbook for Core Animation on their site
You're on the right track with moving the loop to a background thread, but you also need to make sure that you give the main run loop a chance to update the UI. You should be able to replace the direct calls to toggleImageViewOn: and toggleImageViewOff: with something like
[self performSelectorOnMainThread:#selector(toggleImageViewOn:) withObject:[Images objectAtIndex:i] waitUntilDone:NO];
This will do the UI update on the main thread, and by not waiting until the update is done you give the main run loop a chance to reach its end. You run into the same issue with things like progress bars, where they won't change until the loop ends unless you do your updates from a background thread with a UI update call like the one above.
Hey Patrick. Have a look at UIImageView's animationImages property, as well as the animationRepeatCount and animationDuration properties. If you put your on/off images into an array and assign that as the animationImages property, you should be able to control the repeat and duration to get the desired effect.
Hope that helps!
Thanks for that. I've already looked into UIIMageView's animationImages property. That's not exactly what I'm attempting to do. I'm cycling between several UIImageView's that are placed near each other to give the impression that a light is moving between them and cycling over them. So an individual UIImageView's animation is separate from each other as I need to swap the image as necessary in code.
Calling peformSelectorOnMainThread:withObject:waitUntilDone: from the loop on the background thread does indeed update the view as quickly as I can think I will ever need. I'm curious why I need to do the UIImageView swap on the Main thread? Why wouldn't changing it on the background thread and then using NSThread's sleepForTimeInterval allow the main thread to update the drawing anyway?
I guess I need to go read up on the run loop and where drawing updates occur.
Thanks so much for the help. ( I'm also going to try some additional suggestions from Bill Dudney, that I think will work based on CoreAnimation )

"scheduledTimerWithTimeInterval:" problem in cocos2d?

I am trying to developed a iPhone app by using cocos2d. I using "scheduledTimerWithTimeInterval" for calling a method that called a fixed time interval. But now time interval increases in gradually. for this reason the time is slow in gradually.
here is my code:
- (void) methodTime: (id) sender{
NSTimer *rat =[NSTimer scheduledTimerWithTimeInterval:(.5) target:self selector:#selector(rotation:) userInfo:nil repeats:YES];
}
- (void) rotation:(NSTimer *)theTimer{
NSLog(#"I m # %i", i);
i=i+10; // Here , i is a global int variable.
i=i % 1440;
if(i==0){
[theTimer invalidate];
}
else {
int rotationNum=i;
Sprite *sp = [Sprite spriteWithFile: #"1.png"];
sp.position=cpv(220,180.5);
sp.rotation=rotationNum;
[self add:sp];
}
}
It looks like every 0.5 seconds you are adding a sprite to some list of sprites. Eventually the list is getting very large and all that data causes your method to take longer than 0.5 seconds to execute. This causes the timer to fire fast as it can, which is not all that fast since its always waiting for your method to be finished with.
Without know more about your code, that's my best guess.
Don't use NSTimer. Check out cocos2d best practices.
I had trouble understanding your question. You haven't even used one quotation mark in your 'question'.
Is it possible that your code needs more than 0.5 seconds to execute? Especially because the amount of work done in the background increases each iteration. (More sprites.)
Try to make this function faster, for example load that PNG into memory and don't load it each time from the file. (That's better for memory anyway.)
Btw: That loop looks dangerously like an infinite loop. (Though could be that it works…)
If all you're doing is continually rotating the object, CATransforms and Core Animation might be a better bet.
I would use Cocos2d-iphone's built in intervals.
Go through the demo cocos project and you will see how things like this "should" be done in the cocos framework.