Restart Timer again - iphone

Time is invalidated to pause the views from updating because pause button was hit to pause the audio file.
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[timer invalidate];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11 target:self selector:#selector(displayviewsAction:) userInfo:nil repeats:NO];
}
}
- (void)displayviewsAction:(id)sender
{
FirstViewController *viewController = [[FirstViewController alloc] init];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
self.timer = [NSTimer scheduledTimerWithTimeInterval:23 target:self selector:#selector(secondViewController) userInfo:nil repeats:NO];
[viewController release];
}
-(void)secondViewController {
SecondViewController *secondController = [[SecondViewController alloc] init];
secondController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:secondController.view];
[self.view addSubview:toolbar];
self.timer = [NSTimer scheduledTimerWithTimeInterval:27 target:self selector:#selector(ThirdviewController) userInfo:nil repeats:NO];
[secondController release];
}
It goes like this for multiple views. As per the application logic user can hit pause on any view to pause the audio file and timer invalidate statement will also pause views from updating. When user will hit pause again to resume audio file it should start updating views from that point onwards. So problem i m having is how to restart the timer again so that it keep on updating views onwards no matter at which view user pauses.
Anyideas how i can do that.

The timers are not supposed to be reused, simply create another one.

-(void)countDown{
counter--;
if (counter == 0){
[self.timer invalidate];
[self secondViewController];
}
}
Launch your timer:
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(countDown) userInfo:nil repeats:YES];
And relaunch your timer:
counter = 23;
[self.timer fire];
you should adjust this answer for your purposes, because as you can see, the timer is scheduled only for launching -(void)secondViewController method

Related

Connection between two UIButtons programmatically

Connected rewindButton with playButton programmatically. rewindButton is simply rewinding and playing from the beginning and playButton toggles from play to pause.In the rewindButton method used statement to change the UIImage of UIButton2 when UIButton1 is pressed. That is working fine.
PlayButton method is working fine when play button is pressed and paused. Even after resuming is working fine.
Issue briefing:
When rewindButton is pressed it will change the UIImage of playButton to PauseImage so that user can pause. Problem arises when pause is resumed. When pause is resumed it is reloading view controllers.It should load viewcontrollers only for the first time as per code.
-(void)rewind:(id)sender{
audioPlayer.currentTime = 0;
[timer invalidate];
ContainerViewController *viewController = [[[ContainerViewController alloc] init]autorelease];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
[audioPlayer play];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
[_playButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
}
-(void)playpauseAction:(id)sender {
if([audioPlayer isPlaying])
{
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[self pauseTimer];
[self pauseLayer:self.view.layer];
}else{
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
[self resumeTimer];
[self resumeLayer:self.view.layer];
if(isFirstTime == YES)
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
isFirstTime = NO;
}
}
}
- (void)displayviewsAction:(id)sender
{
First *first = [[First alloc] init];
first.view.frame = CGRectMake(0, 0, 320, 425);
CATransition *transitionAnimation = [CATransition animation];
[transitionAnimation setDuration:1];
[transitionAnimation setType:kCATransitionFade];
[transitionAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
[self.view.layer addAnimation:transitionAnimation forKey:kCATransitionFade];
[self.view addSubview:first.view];
[first release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:23 target:self selector:#selector(Second) userInfo:nil repeats:NO];
}
-(void)Second
{
Second *second = [[Second alloc] init];
second.view.frame = CGRectMake(0, 0, 320, 425);
CATransition *transitionAnimation = [CATransition animation];
[transitionAnimation setDuration:1];
[transitionAnimation setType:kCATransitionReveal];
[transitionAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
[self.view.layer addAnimation:transitionAnimation forKey:kCATransitionReveal];
[self.view addSubview:second.view];
[second release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:27 target:self selector:#selector(Third) userInfo:nil repeats:NO];
}
Reason it was reloading view controllers after resuming cause in the rewind method i forgot to add isFirstTime == YES for loading view controllers. Viewcontrollers are not required to reload. Viewcontrollers are required to start loading from the beginning only for the first time only.
So after setting the value of isFirstTime == YES in rewind method now it is not reloading view controllers from the beginning after it is resumed from the pause.
-(void)rewind:(id)sender{
audioPlayer.currentTime = 0;
[timer invalidate];
ContainerViewController *viewController = [[[ContainerViewController alloc] init]autorelease];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
[audioPlayer play];
if(isFirstTime == YES){
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
isFirstTime = NO;
}
[_playButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
}
Now it is working fine.

pause button when pressed again to resume reloading view controllers

I am using AVAudioplayer to play audio files, play/pause button to toggle between play and pause and NSTimer with audio player to synchronize view controllers one after another. I have a total of 10 or 11 view controllers to load one after the other.
When play button is pressed the very first time it starts NSTimer, starts playing an audio file and based on NSTimer, view controllers will load one after the other. When pause button is pressed again to resume it resumes everything from that point audio file, NSTimer and view controllers from the same point where it was paused which is good. However, at the same time it starts loading the view controllers again one after the other from the beginning based on NSTimer which is not good.
It is reloading view controllers with this statement
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
So my issue is that I need to stop the loading of view controllers again from the beginning when pause button is pressed again to resume playback.
-(void)playpauseAction:(id)sender
{
if ([audioPlayer isPlaying]) {
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[self pauseTimer];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
[self resumeTimer];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
}
}
-(void)pauseTimer{
pauseStart = [[NSDate dateWithTimeIntervalSinceNow:0] retain];
previousFireDate = [[timer fireDate] retain];
[timer setFireDate:[NSDate distantFuture]];
}
-(void)resumeTimer{
float pauseTime = -1*[pauseStart timeIntervalSinceNow];
[timer setFireDate:[previousFireDate initWithTimeInterval:pauseTime sinceDate:previousFireDate]];
[pauseStart release];
[previousFireDate release];
}
- (void)displayviewsAction:(id)sender
{
First *firstController = [[First alloc] init];
firstController.view.frame = CGRectMake(0, 0, 320, 480);
CATransition *transitionAnimation = [CATransition animation];
[transitionAnimation setDuration:1];
[transitionAnimation setType:kCATransitionFade];
[transitionAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
[self.view.layer addAnimation:transitionAnimation forKey:kCATransitionFade];
[self.view addSubview:firstController.view];
[self.view addSubview:toolbar];
[firstController release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:23 target:self selector:#selector(Second) userInfo:nil repeats:NO];
}
Can anyone give an idea on how to stop the loading of view controllers again from the beginning when pause button is pressed again to resume playback.
I gather you're trying to display FirstViewController after 11 seconds have elapsed in the audio track.
You can set you timer up to poll (every .5 - 1.0 seconds) and if the audioPlayer's elapsed time is greater than 11.0, perform your action.
-(void)playpauseAction:(id)sender
{
if ([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[self.timer invalidate]; // stop the polling timer
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
// start/resume the timer
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 /* polling interval */
target:self
selector:#selector(tryToDisplayViews:)
userInfo:nil
repeats:YES]; /* REPEAT = YES */
}
}
// the new polled method
-(void)tryToDisplayViews:(id)sender {
// need last current time as a new variable to ensure that we only add the view once
// and not every time the method fires with currentTime > 11.0
if( audioPlayer.currentTime > 11.0 && lastCurrentTime < 11.0) {
[self displayviewsAction:nil];
}
// you can add the second view here in a similar fashion
// if(audioPlayer.currentTime > (23.0+11.0) && lastCurrentTime < (23.0+11.0) ) {}
lastCurrentTime = audioPlayer.currentTime;
}
This also get's rid of your resumeTimer/pauseTimer actions, you don't need to count the time paused.

Run Timer for first time and resume timer for second time

Declared variable in m file.
BOOL isFirstTime;
I want that if play button is pressed the very first time then it should toggle to pause button and check the function isFirstTime then it should start the timer and execute the displayviewsAction method and if the pause button is resumed to play back then it should check again the function isFirstTime or second time and if the hit is for the second time then it should resume timer.
-(void)playpauseAction:(id)sender {
if ([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[self pauseTimer];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(AfterOneSecondsFuction) userInfo:nil repeats:YES];
}
}
-(void)pauseTimer{
pauseStart = [[NSDate dateWithTimeIntervalSinceNow:0] retain];
previousFireDate = [[timer fireDate] retain];
[timer setFireDate:[NSDate distantFuture]];
}
-(void)resumeTimer{
float pauseTime = -1*[pauseStart timeIntervalSinceNow];
[timer setFireDate:[previousFireDate initWithTimeInterval:pauseTime sinceDate:previousFireDate]];
[pauseStart release];
[previousFireDate release];
}
-(void)AfterOneSecondsFuction
{
if(!isFirstTime)
{
isFirstTime=YES;
return;
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
} else if (!isFirstTime){
isFirstTime=NO;
return;
[self resumeTimer];
}
}
- (void)displayviewsAction:(id)sender
{
First *firstController = [[First alloc] init];
firstController.view.frame = CGRectMake(0, 0, 320, 480);
CATransition *transitionAnimation = [CATransition animation];
[transitionAnimation setDuration:1];
[transitionAnimation setType:kCATransitionFade];
[transitionAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
[self.view.layer addAnimation:transitionAnimation forKey:kCATransitionFade];
[self.view addSubview:firstController.view];
[self.view addSubview:toolbar];
[firstController release];
}
-(void)Second
{
Second *secondController = [[Second alloc] init];
secondController.view.frame = CGRectMake(0, 0, 320, 480);
CATransition *transitionAnimation = [CATransition animation];
[transitionAnimation setDuration:1];
[transitionAnimation setType:kCATransitionReveal];
[transitionAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
[self.view.layer addAnimation:transitionAnimation forKey:kCATransitionReveal];
[self.view addSubview:secondController.view];
[self.view addSubview:toolbar];
[secondController release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:27 target:self selector:#selector(Third) userInfo:nil repeats:NO];
}
Looks like when play is pressed first it is only toggling to pause button not checking the function isFirstTime or not and not starting the timer and executing displayviewsaction.
If anyone can tell why it is not happening and what i m doing wrong.
Thanks for help.
BOOL isFirstTime
//Somewhere where the object is set up, isFirstTime should be set to YES
- (void)playpauseAction:(id)sender {
//When the button is pressed
if(isFirstTime) {
//Load the sound file
//Start playing the sound
//Start view controller timers
//Change the button image to paused
isFirstTime = FALSE;
}
else {
//The button has already been pressed
if ([audioPlayer isPlaying]) {
//If the sound is playing
//Stop playing the sound
//Stop view controller timers
//Change the button image to playing
}
else {
//Resume playing the sound
//Start view controller timers
//Change the button image to paused
}
}
}

How to check if audioplayer is paused while loading multiple viewcontrollers

In playpauseAction Method execution it will play audio file as well as load multiple viewcontrollers
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected];
[audioPlayer pause];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11 target:self selector:#selector(displayviewsAction:) userInfo:nil repeats:NO];
}
}
While loading these view controllers just want to check in every viewcontroller that if audioplayer is paused then invalidate timer if not then continue loading of viewcontroller with NSTimer
- (void)displayviewsAction:(id)sender
{
FirstViewController *viewController = [[FirstViewController alloc] init];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
if
([audioPlayer pause]){
[timer invalidate];
} else {
self.timer = [NSTimer scheduledTimerWithTimeInterval:23 target:self selector:#selector(secondViewController) userInfo:nil repeats:NO];
}
[viewController release];
}
My problem is when i add if statement in displayviewAction method it gives me red warning message that statement requires expression of scalar type (void invalid).
But if statement in the playpauseAction works fine.
Why the if statement of displayviewAction is giving red warning message.
AVAudioPlayer's pause is defined as:
-(void)pause
so writing:
if([audioPlayer pause]) {...}
corresponds to write:
if(void) {...}
and void is not a scalar type, exactly what the error message tells you.
Probably your intention was to check if the audio player was paused, that is it is not playing :
if([audioPlayer isPlaying]==NO) {...}

How to resume updating views when resumed AVAudioplayer

I m struggling with this issue for so long but not able to find any solution for this
The issue i have is when i pause the audioplayer i want views to be paused from updating so i used timer invalidate to pause the views from loading but when i resume play only Audioplayer is resumed not the views cause i invalidated the timer.
Now i how i can resume updating views from that point where view was paused. By starting the timer again i can start updating views again but how program will know that at what view it was paused and it should resume updating views from that point. There are multiple views involved displayed code for only two.
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[timer invalidate];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11 target:self selector:#selector(displayviewsAction:) userInfo:nil repeats:NO];
}
}
- (void)displayviewsAction:(id)sender
FirstViewController *viewController = [[FirstViewController alloc] init];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
[viewController release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:23 target:self selector:#selector(secondViewController) userInfo:nil repeats:NO];
-(void)secondViewController {
SecondViewController *secondController = [[SecondViewController alloc] init];
secondController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:secondController.view];
[self.view addSubview:toolbar];
[secondController release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:27 target:self selector:#selector(ThirdviewController) userInfo:nil repeats:NO];
}
Thanks and appreciate for your answers and helping me out with this issue.
Use a background thread to basically bind the view to the player, something like this:
UIImageView* imageView; //the view that gets updated
int current_selected_image_index = 0;
float time_for_next_image = 0.0;
AVAudioPlayer* audioPlayer;
NSArray* image_times; //an array of float values representing each
//time when the view should update
NSArray* image_names; //an array of the image file names
-(void)update_view
{
UIImage* next_image_to_play = [image_names objectAtIndex:current_selected_image_index];
imageView.image = next_image_to_play;
}
-(void)bind_view_to_audioplayer
{
while(audioPlayer.isPlaying)
{
float currentPlayingTime = (float)audioPlayer.currentTime;
if(currentPlayingTime >= time_for_next_image)
{
current_selected_image_index++;
[self performSelectorOnMainThread:#selector(update_view) withObject:nil waitUntilDone:NO];
time_for_next_image = [image_times objectAtIndex:[current_selected_image_index+1)];
}
[NSThread sleep:0.2];
}
}
-(void)init_audio
{
current_selected_image_index = 0;
time_for_next_image = [image_times objectAtIndex:1];
}
-(void)play_audio
{
[audioPlayer play];
[self performSelectorInBackground:#selector(bind_view_to_audioplayer) withObject:nil];
}
-(void)pause_audio
{
[audioPlayer pause];
//that's all, the background thread exits because audioPlayer.isPlaying == NO
//the value of current_selected_image_index stays where it is, so [self play_audio] picks up
//where it left off.
}
also, add self as observer for the audioPlayerDidFinishPlaying:successfully: notification to reset when the audioplayer finishes playing.