invalidate nstimer in objective-c iphone - iphone

I am having issue with invalidating a NSTimer.
I initialize a NSTimer with below function.
-(void) initLTTimer{
[self shutLTTimer];
[self setQuestion:questionCounter];
isQuestionAttempt=NO;
tmLeftTime=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateLeftTime:) userInfo:nil repeats:YES];
NSLog(#"Timer Initialized");
}
further I called a function updateLeftTime in its selector.
- (void)updateLeftTime:(NSTimer *)theTimer {
NSLog(#"%d",timeCounter);
timeCounter+=1;
tfLeftTime.text=[NSString stringWithFormat:#"%d", (QUESTION_TIME_LIMIT-timeCounter)];
if (timeCounter>=QUESTION_TIME_LIMIT) {
if (isQuestionAttempt==NO) {
[self increaseDropShots];
}
[self setQuestionBg];
timeCounter=0;
[self shutLTTimer];
[self updateQuestion:nil];
}
}
This function [self increaseDropShots]; called in above function.
here is the code of this function
-(void)increaseDropShots
{
NSString *imgName = #"DactiveRetake";
if (IS_IPAD) {
imgName = [imgName stringByAppendingString:#"_ipad"];
}
wrongAttemp+=1;
for (int i =1; i<=wrongAttemp; i++ )
{
UIImageView *img=(UIImageView *)[self.view viewWithTag:i+50];
[img setImage:[UIImage imageNamed:imgName]];
}
NSLog(#"Question dropped counter: %d",wrongAttemp);
if (wrongAttemp == 3)
{
[self shutLTTimer];
[CommonFunctions initGlobalVars];
[Bgplayer stop];
[Bgplayer release];
OverPageViewController *opvc=[[OverPageViewController alloc] initWithNibName:[CommonFunctions getXIBFile:#"OverPageViewController"] bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:opvc animated:YES];
[opvc release];
}
}
In this function I am killing this timer but I am unable.
-(void) shutLTTimer{
if ([tmLeftTime isValid]) {
[tmLeftTime invalidate];
tmLeftTime=nil;
}
}
This is the whole scenario of my application
Please help me what is the issue.

Answered after conversation in comments
Does the code definitely get to the line, [tmLeftTime invalidate];? You can check this by using a breakpoint or an NSLog.

Related

Timer doesn't start in viewWillAppear Methods

I want to start a timer when a viewWillAppear method gets called.
It's working perfectly, but I'm having a problem when I push a new view on this Current View, which already has a timer. When I pop that new View and recall viewWillAppear I want to start the timer again as before. I have most of the techniques but can't find a solution.
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[NSThread detachNewThreadSelector:#selector(createTimer) toTarget:self withObject:self];
}
- (void)createTimer
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
gameTimer = [[NSTimer timerWithTimeInterval:1.00 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES] retain];
[[NSRunLoop currentRunLoop] addTimer:gameTimer forMode:NSDefaultRunLoopMode];
timeCount = 360;
[runLoop run];
[pool release];
}
- (void)timerFired:(NSTimer *)timer
{
if(timeCount == 0)
{
[self timerExpired];
} else {
timeCount--;
if(timeCount == 0) {
[timer invalidate];
[self timerExpired];
}
}
timeLabel.text = [NSString stringWithFormat:#"%02d:%02d",timeCount/60, timeCount % 60];
}
- (void) timerExpired
{
//NSLog(#"Final == %#",arrayAnswers);
//NSLog(#"Attempt == %d",[arrayAnswers count]);
[gameTimer invalidate];
gameTimer = nil;
}
Well, based on experience, your problem is the timer's thread. Basically, the problem is here:
[NSThread detachNewThreadSelector:#selector(createTimer) toTarget:self withObject:self];
I'm not absolutely sure but I believe that your code is not really wrong. I haven't figured it out yet but I guess the NSTimer object is not being activated when detachNewThreadSelector: is used. Try executing the timer on the main thread.
[self performSelectorOnMainThread:#selector(createTimer) withObject:nil waitUntilDone:NO]
I've done this and got the results that I wanted.

increase a value while uibutton is kept pressing in iphone

I am trying to increase a variable's value while uibutton is kept pressing. But when user leaves button, increasing of variable's value will be stopped.
i have tried using threads with touch down and touchupinside but couldn't make it work.
-(void) changeValueOfDepthFields:(UIButton *)sender {
if (pressing)
pressing = NO;
else
pressing = YES;
pressingTag = 0;
while (pressing) {
[NSThread detachNewThreadSelector:#selector(increaseValue) toTarget:self withObject:nil];
}
}
- (void) stopValueChange:(UIButton *)sender {
pressing = NO;
}
[fStopUp addTarget:self action:#selector(changeValueOfDepthFields:) forControlEvents:UIControlEventTouchDown];
[fStopUp addTarget:self action:#selector(stopValueChange:) forControlEvents:UIControlEventTouchUpInside];
- (void) increaseValue {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
fstopVal = fstopVal + 0.1;
[self performSelectorOnMainThread:#selector(changeTextOfValues) withObject:nil waitUntilDone:YES];
[pool release];
}
- (void) changeTextOfValues {
fStopField.text = [NSString stringWithFormat:#"%.02f", fstopVal];
}
I wonder if there is an alternative way to do this or not. It seems very simple but couldn't think of any other solution than this one.
It is much easier to use an NSTimer.
- (void)changeValueOfDepthFields:(UIButton *)sender
{
if (!self.timer) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(increaseValue) userInfo:nil repeats:YES];
}
}
- (void)stopValueChange:(UIButton *)sender
{
if (self.timer) {
[self.timer invalidate];
self.timer = nil;
}
}
- (void)increaseValue
{
fstopVal = fstopVal + 0.1;
fStopField.text = [NSString stringWithFormat:#"%.02f", fstopVal];
}
Note: The previous code is just for reference, I didn't do any memory management for example.

Pause the Views from Updating

Want to pause the multiple views from updating when Pause button is pressed
In h file
#property BOOL appIsPaused;
In m file
#synthesize appIsPaused;
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected];
[audioPlayer pause];
appIsPaused = YES;
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
appIsPaused = NO;
[self performSelector:#selector(displayviewsAction:) withObject:nil afterDelay:11.0];
}
}
- (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 performSelector:#selector(secondViewController) withObject:nil afterDelay:23];
[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 performSelector:#selector(ThirdviewController) withObject:nil afterDelay:27];
[secondController release];
}
and it goes on like this for multiple views.
Any ideas how to pause views from updating whenever pause button is pressed.
Instead of using performSelector after delay, you should consider using a NSTimer.
Like this:
Declare a NSTimer *timer ivar.
Declare a NSUInteger viewControl;
Set viewControl to 0;
On the play part of the method add this line:
timer = [NSTimer scheduledTimerWithTimeInterval:11 target:self selector:#selector(tick) userInfo:nil repeats:YES];
-(void)tick
{
switch(viewControl)
{
case 0:
[self performSelector:#selector(firstViewController) withObject:nil];
break;
case 1:
[self performSelector:#selector(secondViewController) withObject:nil];
break;
case 2:
[self performSelector:#selector(thirdViewController) withObject:nil];
break;
.
.
.
default:
break;
}
viewControl++;
if(viewControl > MAX_VIEWS)
{
viewControl = 0;
}
}
And add this line on pause action:
[timer invalidate]
It is also cleaner and let you have more control over your code.
Hope it helps.

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.

Iphone facebook connect example does't call login screen. Why?

i added [self fbButtonClick:nil]; , but it does't call login screen. Why?
- (void)viewDidLoad {
_facebook = [[Facebook alloc] initWithAppId:kAppId];
[self.label setText:#"Please log in"];
_getUserInfoButton.hidden = YES;
_getPublicInfoButton.hidden = YES;
_publishButton.hidden = YES;
_uploadPhotoButton.hidden = YES;
_fbButton.isLoggedIn = NO;
[_fbButton updateImage];
[self fbButtonClick:nil];
}
You're suppose to call the authorize method on the _facebook object to login. That will call the login screen
i solved this problem with timer
NSTimer *timer = [[NSTimer timerWithTimeInterval:0.001
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:NO] retain];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
- (void)timerFired:(NSTimer *)timer
{
[timer invalidate];
[timer release];
timer = nil;
[self fbButtonClick:nil];
}