Xcode NSTimer get position object every millisecond - iphone

I need to get the position of the _propArrow (UIImageView) every .1sec at all time and use a NSLog to verify in the method (void)runScheduledTask
but does not operate every .1 sec.
only indicates the start and end of the movement of the animation
This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
_propArrow.frame = CGRectMake(144, 291, 33, 71);
aTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(runScheduledTask) userInfo:nil repeats:YES];
}
- (void)runScheduledTask {
NSLog(#"Position: %#", NSStringFromCGRect(_propArrow.frame));
}
- (IBAction)fire:(id)sender {
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationCurveEaseInOut
animations:^{
_propArrow.frame = CGRectMake(144, 0, 33, 71);
}
completion:^(BOOL finished){
}];
}

First, according to the NSTimer docs, that class has an effective resolution of about 50-100 ms. So using it to do anything at 1 ms intervals is bound to fail.
Second, even if NSTimer could handle 1 ms intervals, you're not even asking it to do that:
aTimer = [NSTimer scheduledTimerWithTimeInterval:.05...
Your code schedules the timer to run ever 0.05 s, which is to say every 50 ms.
Third, the screen doesn't update at anything close to 1 ms intervals, so the actual position of your image on the screen will change much less often than that.
So, what exactly are you trying to accomplish here? If you want to know where the object would be in the real world with continuous motion, you can calculate that for any point in time.

Because in most UIKit animated properties, the new value gets set immediately from the perspective of your code; it's the displayed value that actually animates. Reading animatable properties like UIView.frame should never give you an intermediate value (the main exception is UIScrollView which does its own thing for animated scrolling).
If you want "approximately what's being displayed on screen", you need to access the CoreAnimation "presentation layer":
#import <QuartzCore/CALayer.h>
- (void)runScheduledTask {
NSLog(#"Position: %#", NSStringFromCGRect(_propArrow.layer.presentationLayer.frame));
}
Also consider using CADisplayLink if you want a callback that runs every frame.

Related

Scroll UISlider Automatically

So currently I have a UISlider in a UIViewcontroller that is meant to start animations within subviews when the user slides.. Basically when the user slides I have this battery with a filling in it that fills the empty battery image with a bar to indicate power within a cell, and the user can slide to see the energy the battery has at certain times of the day.
At the moment, when the View loads I would like the UISlider to AUTOMATICALLY start sliding from the beginning of the slider and scroll to the end within, lets say 5 seconds.
I implemented a loop that cycles through all the values of the uislider using this loop
for (int i = 0; i < [anObject count] - 2; i++)
{
sleep(.25);
NSUInteger index = (NSUInteger)(slider.value + 0.5); // Round the number.
[slider setValue:index animated:YES];
}
[anObject count] - 2 is equal to 62 at this time of day but will change and increment every 15 seconds because I'm fetching data from a server.
But that aside, why doesn't this work? The loop?
EDIT:
So heres what I did with NSTIMER
[NSTimer timerWithTimeInterval:0.25 target:self selector:#selector(animateSlider) userInfo:nil repeats:NO];
and animateSlider looks like this:
- (void)animateSlider:(NSTimer *)timer
{
NSLog(#"Animating");
NSUInteger index = (NSUInteger)(slider.value + 0.5); // Round the number.
[slider setValue:index animated:YES];
}
But no luck... Why isn't NSTimer "firing"..... I remmeber vaguely there was a method that FIRES an nstimer method but not sure if that's needed...
EDIT:
Ahh it does need "Fire"....
NSTimer *timer = [NSTimer timerWithTimeInterval:0.25 target:self selector:#selector(animateSlider) userInfo:nil repeats:NO];
[timer fire];
But for some reason it only fires once.... Any ideas ?
"for some reason it only fires once..."
If you changed the NSTimer set up to this:
NSTimer *timer =
[NSTimer scheduledTimerWithTimeInterval:0.25
target:self
selector:#selector(animateSlider:)
userInfo:nil
repeats:YES];
This would schedule the timer on the current run loop immediately.
And since the "repeats" parameter is "YES", you'd then repeat the timer every quarter second, until you invalidate the timer (which you should do when the ending condition is reached, like when the slider reaches its destination).
P.S. You'd need to change the selector method declaration of your timer's target slightly. According to Apple's documentation, "The selector must correspond to a method that returns void and takes a single argument. The timer passes itself as the argument to this method."
So declare "animateSlider" like this instead:
- (void)animateSlider: (NSTimer *) theTimer;

Capture frames with time delay - iPhone camera

I'm trying to write some objective-c code that allows capture of frames through the iPhone camera, after a specific time delay. Any examples I have found online have captured the 'present' frame input by the camera (i.e. a realtime frame capture). I am looking for a less real time frame capture - a way to capture frames with a specific time delay. Any ideas?
I would use NSTimer.
It would allow you to use the code that captures the current frame, and it would get called after a delay.
You can create a non-repeating timer like this: timer = [NSTimer scheduledTimerWithTimerInterval:delay target:self selector:#selector(capture) userInfo:nil repeats:NO]; where delay is the specific time delay and capture is a method that contains the code from an example that captures the present frame.
Use following code.....
//call method according to your delay that you need.....
float yourdelay;
yourdelay = 0.7;
[self performSelector:#selector(captureView) withObject:nil afterDelay:yourdelay];
// or set time for calling method....
[NSTimer scheduledTimerWithTimeInterval:0.02 target: self selector:#selector(captureView) userInfo:nil repeats:NO];
///or you can call method directly when you need..
[self captureView];
////Here the code for capture real time image.
- (void)captureView {
UIGraphicsBeginImageContext(mapView.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
flickerImaveView.image=viewImage;
}
Hope this will help you....

NSTimer firing instantly

I'm trying to develop a game and running into a small issue with NSTimer, once a sprite appear it has a certain amount on time in my scene before fading out.
double CALC_TIME = 5;
[NSTimer scheduledTimerWithTimeInterval:CALC_TIME target:self selector:#selector(hideSprite) userInfo:nil repeats:NO];
I want hideSprite to be called after 5 seconds, but instead it's called instantly(Or near instant).
A possible solution:
I know I could do this by setting the timer to repeat, and having a bool firstCall that is set first time and then the next interval the fading is done, the timer is invalidated but I don't think this is good practice
Like this:
bool firstCall = false;
-(void)hideSprite{
if(!firstCall){
firstCall = true
}else{
//fade out sprite
//Invalidate NSTimer
//firstCall = false;
}
}
Thanks for your help!
I suspect something else is calling hideSprite. The code you have written will cause the timer to wait for five seconds before calling the selector hideSprite.
Provide a different selector (write a new test method which just does an NSLog) to the timer and see what happens. This will tell you a) whether the timer is indeed immediately firing and b) if something else is calling hideSprite.
[NSTimer scheduledTimerWithTimeInterval:CALC_TIME target:self selector:#selector(testTimer) userInfo:nil repeats:NO];
-(void) testTimer { NSLog(#"Timer - and only the timer - called me."); }
-(void) hideSprite {
NSLog(#"I definitely wasn't called by the timer.");
}
Quite often it's easier to just use something like
[UIView animateWithDuration: 0 delay: 5 options:0 animations: nil completion:
^{
// fade sprite
}];
(not sure if animations can be nil, but you get the idea).
Consider initializing your timer using the initWithFireDate:interval:target:selector:userInfo:repeats method. Here is a more detailed look at NSTimer.

animations ios objective-c

I have a global variable p.
I have a function that draws (or redraws) my complex UIView objects depending on the value of this global variable.
When I increase p my uiview objects needs to be redrawed. I need this be done using animation.
double pInitialValue=0.5;
double pNewValue=1.0;
//somewhere before animation we must call [self redraw] to draw our view with p=pInitialValue;
//then, when we call animate function.
//we change p to pNewValue
//and every step must be redrawed using [self redraw]
p=pNewValue; //using animation p must slowly grow from pInitialValue to pNewValue
[self redraw]; //and ofcourse user must see every step of animation so we need to call redraw function
for example I need an animation with duration 4.
That means that during this 4 seconds my p must grow from pInitialValue to pNewValue and in every step my redraw function must be called
Help me, please. How can it be done?
You can use a timer to increase your p value. Do that like this: have an instance variable in your class defined like
NSTimer *timer;
After that just before you want your animation to happen do:
CGFloat timerInterval = 1 / 30; // This means 30 frames per second. Change this as you want.
timer = [NSTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:#selector(increaseP) userInfo:nil repeats:YES];
Than have a method called increasePlike this:
- (void)increaseP
{
if (p < maxPValue) {
// Increase p here and redraw your things
}
else {
[timer invalidate];
}
}
Let me know if you have any question and if this works for you.

How to use isAnimating in an iPhone app

I want to have a custom loading menu made from a series of stills, that loops 3 times and then reveals a picture. Currently the picture is visible from the start. I want to use isAnimating to find out when the loading animation has stopped, and either change myImage.hidden off, or have the UIImageView initially containing a white image, then being replaced with the picture when isAnimating returns NO.
Apple's website just says
- (BOOL)isAnimating
and that it returns a Boolean YES or NO.
but how do you use this?
I need things to happen depending on whether something is animating or not, so i do i put the result it returns in a variable and check that in the conditional of an if statement?
put it in an if statement itself?
or is it a while statement?
or is it like:
- (BOOL)isAnimating{
//stuff to do if it is
}
or am i just getting the whole concept entirely wrong?
I guess isAnimating method just tells you if an UIViewImage is actually performing an animation.
Since you just want to create a short loading before displaying your image, why don't you simply use a timer?
You can do something like this
- (void)startAnimation {
yourImageView.hidden = YES; // Keep you image hidden while loading
[yourLoadingAnimation startAnimating]; // Start you loading animation
NSInteger timeout = 2; // Duration in seconds of your loading animation
[NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:#selector(stopAnimation) userInfo:nil repeats:NO]; // Set the timer
}
- (void)stopAnimation {
[yourLoadingAnimation stopAnimating]; // Stop your loading animation
yourLoadingAnimation.hidden = YES; // Hide your laading animation
yourImageView.hidden = NO; // Display your image
}