2012-12-31 3 views
0

여기 내 상황이 있습니다 : [stopWatchTimer invalidate];을 호출하면 멈추지 않는 카운트 다운 응용 프로그램을 만들고 있는데, 이유가 없습니다. 여기 내 코드는 다음과 같습니다.목표 -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]; [self currentCount] & [self playAlert] (3) 모든 주석 처리 된 설정자를 주석 처리했습니다. – HKTonyLee

답변

1

btnStartPressed: 방법에서는 두 번째 NSTimer이 할당되지 않고 stopWatchTimer에 할당되는 것을 막을 수있는 방법이 없습니다. 버튼을 두 번 누르면 두 개의 타이머가 생기지 만 하나만 무효화됩니다. btnStartPressed:의 시작 부분에

if (stopWatchTimer) return; 

:

뭔가를 추가합니다. 그래도 문제가 해결되지 않으면 timeLeft이 0이라고 추측하는 것 이상의 상황을 확실히 알 수있는 문맥이 충분하지 않은 것입니까?


네이트가 말한 바가 있지만 다른 설명이 있습니다.

이렇게 상상해 (stopWatchTimer 글로벌 또는 인스턴스 변수이고, 중요하지 않습니다) :

을 지금, 이렇게 :

stopWatchTimer = nil; 
[stopWatchTimer invalidate]; 

타이머가 무효화되지 않습니다를 ,하지만 여전히 발사 될거야. stopWatchTimer은 개체에 참조입니다. 그것은 대상 자체가 아닙니다. 따라서 에 타이머를 stopWatchTimer에 할당하면 첫 번째 타이머에 대한 참조를 덮어 쓰지 만 해당 타이머는 계속 실행됩니다!

+0

와우, 완벽하게 작동했지만, 이것이 간단히 말해서 무엇을 설명 할 수 있습니까? 전에 이것을 보지 못했습니다. –

+2

@coryginsberg 실행 루프에서 타이머를 예약하면 타이머가 무효화 될 때까지 실행 루프가 "타이머를 활성 상태로 유지"합니다. 'stopWatchTimer'가 이미 실행 루프에서 스케쥴 된 타이머를 참조한다고 상상해보십시오. 'stopWatchTimer'를'nil'으로 설정했다고 상상해보십시오. 이제 예약 된 타이머를 무효화하는 기능을 잃어 버렸습니다. 이것은 'stopWatchTimer'를'nil'으로 설정하는 대신에 실행 루프에서 스케줄 된 _another_ timer로 설정하는 작은 주름을 제외하고는 상황입니다. –

관련 문제