2012-12-31 44 views
0

這裏是我的情況:我想提出一個倒計時應用程序,它工作正常,但似乎沒有停止的時候我打電話[stopWatchTimer invalidate];,我不知道爲什麼。這裏是我的代碼:Objective-C的計時器不會失效

- (IBAction)btnStartPressed:(id)sender { 
//Start countdown with the time on the Date Picker. 

    timeLeft = [pkrTime countDownDuration]; 

    [self currentCount]; 

    lblTimer.text = time; //sets the label to the time set above 

    pkrTime.hidden = YES; 
    btnStart.hidden = YES; 
    btnStop.hidden = NO; 

    //Fire this timer every second. 
    stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/1.0 
                target:self 
               selector:@selector(reduceTimeLeft:) 
               userInfo:nil 
               repeats:YES]; 
} 
- (void)reduceTimeLeft:(NSTimer *)timer { 
    //Countown timeleft by a second each time this function is called 
    timeLeft--; 
    // Get the system calendar 
    NSCalendar *sysCalendar = [NSCalendar currentCalendar]; 

    // Create the NSDates 
    NSDate *date1 = [[NSDate alloc] init]; 
    NSDate *date2 = [[NSDate alloc] initWithTimeInterval:timeLeft sinceDate:date1]; 

    // Get conversion to months, days, hours, minutes 
    unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; 

    NSDateComponents *conversionInfo = [sysCalendar components:unitFlags fromDate:date1 toDate:date2 options:0]; 

    int sec = [conversionInfo second]; 
    int min = [conversionInfo minute]; 
    int hour = [conversionInfo hour]; 

    NSString *seconds = [NSString stringWithFormat:@"%d",sec]; 
    NSString *minutes = [NSString stringWithFormat:@"%d",min]; 

    if (sec <= 9) 
     seconds = [NSString stringWithFormat:@"0%d", sec]; 
    if (min <= 9) 
     minutes = [NSString stringWithFormat:@"0%d", min]; 

    if ([conversionInfo hour] == 0) 
     time = [NSString stringWithFormat:@"%@:%@", minutes, seconds]; 
    else 
     time = [NSString stringWithFormat:@"%d:%@:%@", hour, minutes, seconds]; 

    lblTimer.text = time; //sets the label to the time set above 

    NSLog(@"%d", timeLeft); 

    if (timeLeft == 0) { 
     [self timerDone]; 
     [stopWatchTimer invalidate]; 
     stopWatchTimer = nil; 
    } 
} 

-(void)timerDone { 

    pkrTime.hidden = NO; 
    btnStart.hidden = NO; 
    btnStop.hidden = YES; 

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Timer Done" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok", nil]; 
    [alert show]; 

    [self playAlert]; 
} 

請讓我知道是什麼問題...我不能用我的代碼找到問題的任何地方!

+0

我可以有一些修改正確運行的代碼。 (1)[pkrTime countDownDuration];被假定爲5(2)註釋掉[self currentCount]和[self playAlert](3)註釋掉所有隱藏的引用者 – HKTonyLee

回答

1

在您的btnStartPressed:方法中,您沒有任何功能可以阻止第二個NSTimer被分配並指定給stopWatchTimer。如果按下按鈕兩次,你會擁有兩個定時器,但只有一個將永遠不會失效。

添加類似:

if (stopWatchTimer) return; 

btnStartPressed:開始。如果不解決這個問題,那麼就沒有足夠的上下文肯定知道是怎麼回事超出揣測即timeLeft爲零?


奈特說了什麼,但這裏是另一種解釋。

,如果你做到這一點想象(其中stopWatchTimer是一個全球性或實例變量,無所謂):

現在,這樣做:

stopWatchTimer = nil; 
[stopWatchTimer invalidate]; 

定時器不會因此而失效,但它仍然會開火。 stopWatchTimer參考到對象。這不是對象本身。因此,當您將定時器指定爲stopWatchTimer時,您將覆蓋對第一個定時器的引用,但該定時器仍將觸發!

+0

哇,這個工作很完美,但你能向我解釋這是幹什麼的 - 我沒有之前沒有見過這個。 –

+2

@coryginsberg一旦你在運行循環中調度了一個定時器,運行循環「保持定時器有效」直到定時器失效。想象一下,'stopWatchTimer'指的是一個已經在運行循環中被調度的定時器。想象一下,你將'stopWatchTimer'設置爲'nil'。你現在已經喪失了使預定計時器無效的能力。這裏就是這種情況,除了一點小小的錯誤,不是將'stopWatchTimer'設置爲'nil',而是將它設置爲運行循環中調度的_another_ timer。 –