How to Check Playback Time of Audioplayer increases by 2 seconds - objective-c

I m trying to write a loop to check that whenever audio player.currenttime increases by 2 seconds then it should execute update view method
- (void)myTimerMethod{
NSLog(#"myTimerMethod is Called");
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(checkPlaybackTime:)
userInfo:nil
repeats:YES];
}
- (void)checkPlaybackTime:(NSTimer *)theTimer
{
float seconds = audioplayer.currenttime;
NSLog(#"Cur: %f",audioPlayer.currentTime );
if (seconds = seconds + 2){
[self update view];
}
- (void)UpdateView{
if (index < [textArray count])
{
self.textView.text = [self.textArray objectAtIndex:index];
self.imageView.image = [self.imagesArray objectAtIndex:index];
index++;
}else{
index = 0;
}
}
what is the correct way to write if audio player.currenttimer increases by 2 seconds then do this.
NSLog for current time always shows 0.00. Why is that. It should increase as the audioplayer is playing.
Thanks for help.

What i understood from your given explanation that you want to increment the time-interval something like this
Timer calls after 0.55
Timer calls after 0.60
Timer calls after 0.65
Timer calls after 0.70
& so on.
If that is what you are looking to do. Then i think you can do this way that by changing repeats:YES to repeats:NO so that the timer doesn't repeat, and then in onTimer, just start a new timer with a longer interval.
You need a variable to hold your interval so that you can make it a bit longer each time through onTimer.
Also, you probably don't need to retain the timer anymore, as it will only fire once, and when it does, you'll get a new timer.
float gap = 0.50;
[NSTimer scheduledTimerWithTimeInterval:gap target:self selector:#selector(onTimer) userInfo:nil repeats:NO];
-(void) onTimer {
gap = gap + .05;
[NSTimer scheduledTimerWithTimeInterval:gap target:self selector:#selector(onTimer) userInfo:nil repeats:NO];
}
Hope this helps you

First, try using your float "seconds" in your NSLog rather than the current time.
NSLog(#"Cur: %f", seconds);
current time is not a float, it's an NSTimer object so you would have to use %# in your NSLog text so
NSLog(#"Cur: %#",audioPlayer.currentTime );
Should work as well.
Assuming your audioPlayer is set up correctly, if you're looking for when the timer is at 2 seconds, your if statement will be
if(seconds == 2){
[self update view];
}
if you're looking for each time the timer hits an even number, i.e. 2, 4, 6, etc. your if statement will be
if(seconds % 2 == 0){
[self update view];
}
The % in an if statement is the modulo sign: http://www.cprogramming.com/tutorial/modulus.html
Also, your current if statement is assigning rather than checking the seconds variable. To check it, you need == not =. However, your current if statement will never be true since you're checking a variable by itself + 2. To put this another way, if seconds equals 2, your if statement is asking if 2 == (2+2) or if it it is 4, it's asking if 2 == (4+2). This statement cannot validate as true.
Hope this helps!

Related

Timer stops when the screen is locked

I made a timer, but if I lock the screen, the timer stops ... how can I make it work when I block?
-(void)timeRun{
secondsCount = secondsCount - 1;
int minuts = secondsCount / 60;
int seconds = secondsCount - (minuts * 60);
NSString *timerOutput = [NSString stringWithFormat:#"%2d:%.2d", minuts, seconds];
TimerDisplay.text = timerOutput;
if (secondsCount == 0) {
[countdownTimer invalidate];
countdownTimer = nil;
AudioServicesPlaySystemSound(PlaySoundID);
}
}
Start the timer here
-(IBAction)Start:(id)sender{
secondsCount = perVrem;
countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timeRun) userInfo:nil repeats:YES];
}
Here I set the time 5 minutes
-(IBAction)fivemin:(id)sender{perVrem = 300;
TimerDisplay.text = [NSString stringWithFormat:#"05:00"];}
Difficult to answer without more context, but you may need
UIApplication.sharedApplication.idleTimerDisabled = NO;
or maybe you need to use
dispatch_after
or maybe you need to use the wall clock and just use your timer to update some UI.
Yours look like the latter, ie. use the wall clock and your timer just to update. If you count down 5 minutes accurately you'd have a start and end time and use a timer just to update the UI every now and again. So start becomes something like
-(IBAction)Start:(id)sender{
self.start = NSDate.date.timeIntervalSinceReferenceDate;
countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timeRun) userInfo:nil repeats:YES];
}
and timeRun something like
-(void)timeRun{
secondsCount = (x)( NSDate.date.timeIntervalSinceReferenceDate - self.start + 0.5 ); // Add a bit to get rounding right, depends on your types
...
where x will be e.g. int or long depending on secondsCount.

objective c loop blocking user input while video recording with AvFoundation?

Hello every time i try to record the date with CFAbsoluteTimeGetCurrent(); my app ignores the rest of the buttons, it's as if it takes over all memory and blocks all user input. I was wondering what i am doing wrong? I thought of making a function showtime() but i dont know how to pass values between functions from toggleRecording to showtime so that my method would work if this would even solve the problem. Below is my code:
- (IBAction)toggleRecording:(id)sender
{
// Start recording if there isn't a recording running. Stop recording if there is.
[[self recordButton] setEnabled:NO];
if (![[[self captureManager] recorder] isRecording]){
[[self captureManager] startRecording];
/* figure out a day to record for every half a second
while([[[self captureManager]recorder] isRecording]){
CFTimeInterval startTime = CFAbsoluteTimeGetCurrent();
NSLog(#" time is %i", startTime);
}
*/
}
else
[[self captureManager] stopRecording];
}
-(void)showtime:(id)sender{
while([[[self captureManager]recorder] isRecording]){
CFTimeInterval startTime = CFAbsoluteTimeGetCurrent();
NSLog(#" time is %f", startTime);
}
}
An application has to run the event loop to receive the events. While your own code is doing something else (here it's doing a "while" loop), events are queued and not delivered until your code returns.
Schematically, an application is doing something like:
while(1) {
event = _UIReceiveNextQueuedEvent();
_UIProcessEvent(event); // <- this calls -showTime:
}
If you want to record time while not blocking the loop, you will have to schedule an NSTimer every 0.5s and invalidate it as soon as recording is turned off.
Something like:
- (void)showTime:(id)sender
{
if ([[[self captureManager]recorder] isRecording]) {
[NSTimer scheduledTimerWithTimeInterval:0.5f target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
}
}
- (void)timerFired:(NSTimer *)timer
{
if ([[[self captureManager]recorder] isRecording]) {
CFTimeInterval startTime = CFAbsoluteTimeGetCurrent();
NSLog(#" time is %f", startTime);
} else {
[timer invalidate];
}
}

When using a NSTimer in Objective-C, why isn't my code stopping when it gets to 0?

I am using a timer in xcode i have managed to make it count down correctly but when counting down it goes into negatives,
i have tried using an if statement to counter this but it dosnt seem to work here is the code i am using,
IBOutlet UILabel *timelabel;
int MainInt;
NSInteger fred;
NSTimer *timer;
MainInt -= 1;
timelabel.text = [NSString stringWithFormat:#"%i",MainInt ];
MainInt = 20;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countdown) userInfo:nil repeats:YES];
if (timelabel.text <= #"0")
{
[timer invalidate];
timelabel.text = #"20";
}
the H is ov my H
Although I believe it would compile
if (timelabel.text <= #"0")
This line doesn't make much sense. It should probably read:
if(MainInt <= 0)
Instead of trying to compare the text value of the label with zero, compare MainInt. Your problem is that you're trying to compare two strings... Technically, you can get the ASCII value of a character and compare it to another, so basically you tried to do something like #"Dog" >= #"Cat" which the runtime will attempt to do but obviously isn't what you want.
There's also a method on NSString called intValue that you could use to pull out an integer representation of the string. You could do
if ([timelabel.text intValue] <= 0)
If you really want to check the timelabel.text use the intValue
if ([timelabel.text intValue] <= 0)
{
timer invalidate];
timelabel.text = #"20";
}
Note: Change to intValue, but take note you should compare it to int also

Prevent countdown going into negatives

I've created a countdown timer and it works great.. but when it reaches zero it continues counting down.. so it shows -1, -2, -3 etc. How do I prevent it from doing this?
This is my code from the implementation file..
#implementation ViewController
-(IBAction)start {
myTicker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
}
-(IBAction)stop {
[myTicker invalidate];
}
-(IBAction)reset {
time.text = #"0";
}
-(void)showActivity {
int currentTime = [time.text intValue];
int newTime = currentTime -1;
time.text = [NSString stringWithFormat:#"%d", newTime];
}
I'm guessing that I'm missing some code somewhere?
Quick fix is to change:
int newTime = currentTime - 1;
into:
int newTime = (currentTime > 0) ? currentTime - 1 : 0;
That will stop the countdown timer from going below zero. If that's all you need, that should suffice.
It won't turn off the timer or execute an action when it reaches zero. For that, you'll need to add something like the following block after that line above:
if ((currentTime > 0) && (newTime ==0)) {
// optionally turn off timer
fireZeroEvent ();
}
and provide the fireZeroEvent() function to do whatever you need to do.
I say optionally turn off the timer since you may want to leave it running so you can restart the countdown by just be setting time.text without have to recreate the timer.
For that reason, the fireZeroEvent() is only called on the transition from 1 to 0, not every time the timer fires after it reaches zero.

Stop NSTimer when float is 0

I've got a NSTimer and a label which shows the seconds counting down.
-(void)start {
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
}
-(IBAction)stop {
[myTimer invalidate];
}
-(void)showActivity {
currentTime = [timeLabel.text floatValue];
currentTime -= 0.01;
timeLabel.text = [NSString stringWithFormat:#"%.2f", currentTime];
if (currentTime == 0) {
[self stop];
ResultViewController *screen = [[ResultViewController alloc] initWithNibName:nil bundle:nil];
screen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:screen animated:YES];
[screen release];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
timeLabel.text = #"60.0";
[self start];
}
So when the time is 0, the timer should stop and the ResultViewController should load, but when I do it the timer still counts down into negative numbers and nothing happens.
Is there anybody who can help me?
Thank you :)
0.01 doesn't have an exact floating point binary representation, so your float will never get to exactly zero. Use <= instead of == in your comparison.
Try something like this:
if(currentTime <= 0.0)
...
What you're suffering from is floating point drift. It's a well known phenomenon.
Floating point arithmetic isn't "precise" oftentimes (see http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems ) . Change the check to if (currentTime <= 0.0) and you'll be fine.
Not all numbers can be stored accurately with floating point variables. Just as 1/3 can't be represented with finite digits in base 10, 1/10 can't be represented with finite digits in base 2. What you end up with is rounded to 0.10000000000000001 or close. So when you subtract 0.1 from that, you don't quite get 0.
The most robust solution to this is to store your time as milliseconds in an integer and divide it when you want to update the label. Don't bother going back and forth from the label to the number either. The canonical storage of the number should be as a number. The label is just to display it.
Edit:
For everybody recommending that he just change to <= instead - this is just a hack that barely scrapes by. Floating point representation of 0.1 is often 0.10000000000000001. What happens when you subtract 0.1 from that? It's still above 0. The conditional only triggers when it reaches almost -0.1, which isn't expected behaviour from the app. This is a bad solution.
ResultViewController should just alloc init instead of the alloc initWithNibName set to nil.
current time comparison should be put as if (currentTime <= (float)0.0) or similar (Reason for it refer to:this thread)
Better not compare against an int. Try to do this:
if (currentTime == 0.0) {