2012-12-27 5 views
0

안녕하세요. 미리 감사드립니다. 하나의보기에서 NSTimer을 시작한 다음 UIPickerView과 함께 다른보기로 전환하면 UIPickerView의 동작이 영향을받습니다. NSTimer을 포함하는보기와보기간에 전환할수록 UIPickerView의 동작이 영향을받습니다. 지연되고 느리게 이동하여 결국 UIPickerViewDidSelectRow 메서드를 호출하지 않는 지점으로 이동합니다. 영향을 받고있는 것은 UIPickerView뿐 아니라 내 앱에있는 UIPickerView입니다.UIPickerView의 동작에 영향을 미치는 NSTimer

처음에 NSTimer을 활성화하지 않기로 결정하면 내 UIPickerViews이 문제없이 작동합니다. 그러나 NSTimer 메서드를 호출하면 NSTimer이 포함 된보기와 다른보기가 여섯 번 반복되는보기 사이에 네 번 전환 한 후 내 앱 UIPickerView이 완전히 작동하지 않습니다. 그들의 적절한 행동을 복원하기 위해 나는 응용 프로그램을 종료하고 다시 시작해야합니다.

저는 ARC을 사용하고 있습니다. 따라서 수동으로 NSTimer을 풀어주지는 않습니다. 그러나 이것은 제 문제와 관련이 있다고 생각합니다. 나는 NSTimer을 포함하는보기로 다시 전환 할 때마다 NSTimer 또는 그 메소드가 중복되거나 (해제되거나 할당 해제되지 않고) 점점 복잡해지고 있다고 생각합니다. 어쨌든,이 두 번째 노력은 무엇이든 코딩하므로이 문제를 해결하는 방법을 모르겠다. 비록 내가 NSTimerUIPickerView을 같은 NSRunLoop이나 스레드를 통해 할당 할 수 있다고 읽었지 만, 그게 뭔지 잘 모르겠다. 방법.

어쨌든, 여기에 제 코드가 있습니다 - 꽤 일반적인 상용구 코드입니다.

-(void)showActivity:(NSTimer *)tim { 

    NSDate *currentDate = [NSDate date]; 
    NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate]; 
    NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval]; 

    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; 
    [dateFormatter setDateFormat:@"HH:mm:ss.S"]; 
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]]; 
    NSString* timeString = [dateFormatter stringFromDate:timerDate]; 
    stopWatchLabel.text = timeString; 

} 


- (IBAction)onStartPressed:(UIButton *)sender; { 

    stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1/10 
                target:self 
               selector:@selector(showActivity:) 
               userInfo:nil 
               repeats:YES]; 
    // Save the new start date every time 
    startDate = [[NSDate alloc] init]; // equivalent to [[NSDate date] retain]; 
    NSDate *savedMentionDate = [[NSUserDefaults standardUserDefaults] objectForKey:@"mostRecentMentionDate"]; 

    if (savedMentionDate == nil) { 
     //There is no existing mention, so save the most recent one 
     [[NSUserDefaults standardUserDefaults]setObject:startDate forKey:@"mostRecentMentionDate"]; 
     [[NSUserDefaults standardUserDefaults] synchronize]; 
    } else { 
     startDate = savedMentionDate; 
    } 

    [stopWatchTimer fire]; 

    timerSetting = 0; 

    NSNumber* timerSettingNS = [[NSNumber alloc] initWithInt:timerSetting]; 
    [[NSUserDefaults standardUserDefaults] setObject:timerSettingNS forKey:@"timerSetting"]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 

} 


- (IBAction)onStopPressed:(UIButton *)sender { 

    [stopWatchTimer invalidate]; 

} 


- (IBAction)resetTimer:(UIButton *)sender; { 

    stopWatchLabel.text = @"00:00:00.0"; 

    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 
    [defaults removeObjectForKey:@"mostRecentMentionDate"]; 

    timerSetting = 1; 

    NSNumber* timerSettingNS = [[NSNumber alloc] initWithInt:timerSetting]; 
    [[NSUserDefaults standardUserDefaults] setObject:timerSettingNS forKey:@"timerSetting"]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 

} 

-(void)ViewDidLoad { 
    ... 
    ... 
    NSNumber* timerSettings = [defaults objectForKey:@"timerSetting"]; 

    if (timerSettings == nil || timerSettings.intValue == 1) { 

     [self resetTimer:resetTime]; 

    } else if (timerSettings.intValue == 0) { 

     [self onStartPressed:start]; 

    } 

} 
+0

'xcode'태그를 남용하지 마십시오. 일반적인 iOS 프로그래밍 관련 질문에 적합합니다. –

+0

좋아요. 나중에 확인하지 않겠습니다. –

답변

0

솔루션을 찾았습니다. 앱에서보기를 전환 할 수있게하는 모든 메소드에 [stopWatchTimer invalidate] 코드를 삽입했습니다.

이는 더 많거나 적은 어떤 사람에 당신을 말한 것 때문에 :

나는 내가있는 viewDidLoad 및 viewDidUnload 법의 stopWatchTimer의 무효]를 포함하는 경우가 없었기 때문에이 작품 놀랐어요 어떤 효과가 ...

그 방법은 매우 특별한 경우에 호출됩니다

viewDidLoad이 때보기 컨트롤러라고 의보기가로드되었습니다.

중요한 부분은 load이 무엇을 의미하는지 이해하는 것입니다 (... 놀랄 정도 있어야하지) : - 코코아 콩을, 또는 코드 -

뷰 컨트롤러가 인스턴스화

그렇지 않습니다 전망이있다. 그것이 무엇을하는지, 대신에, 그것을 요구할 때, 하나를 제공하는 방법에 관한 정보입니다.

그래서 UIViewController에 view 메시지를 보내면 이미 _view 인스턴스 변수가 채워 졌는지를 알 수 있습니다. 그렇지 않으면 인스턴스 변수를 의미있는 것으로 채우기 위해 필요한 모든 작업을 수행하는 자체 loadView 메서드를 호출합니다. 그런 다음 자신이 관리하는 뷰 계층 구조의 설정을 완료하기 위해 viewDidLoad 메시지를 보내고 _view의 값만 반환합니다.

이것은 뷰 컨트롤러보기가 끝나는 동안 만 viewDidLoad이 한 번 호출된다는 것을 의미합니다. 하지만 그게 무슨 뜻 이죠?

iOS 5 및 이전 버전에서는보기의 수명이 가시적 인보기 계층 구조의 일부로 묶여있었습니다.보기에 포함되지 않았고 소유 한보기 컨트롤러가 메모리 경고를 받았을 때 기본 구현은 기본적으로 보기에 수퍼 뷰가 있는지 살펴보고 (그렇지 않은 경우) viewWillUnload, 릴리스 및 없음을 호출하고 _view을 출력하고 결국 viewDidUnload을 호출하여이 프로세스를 완료하십시오. 그렇기 때문에 일부 진절머리 난 레거시 코드 기반에서는 을 무시하고 super ...을 호출하지 않을 수 있습니다.

iOS 6부터 UIViewController는 더 이상이 작업을 수행하지 않습니다!

그 이유는 viewWillUnload 및 viewDidUnload가 더 이상 사용되지 않기 때문입니다. 뷰 컨트롤러가 소유 할 때까지 뷰가 유지되어 더 이상 해당 메서드가 호출되지 않습니다.

그런 상태가되면 타이머를 지우는 데 필요한 관련 상황은 무엇입니까? 1. viewWillDisappear:보기가 "무대에서 나갈"예정이므로, 정면 및 중앙에서만 관련이있는 것이 무엇이든지 찢어 버리십시오. 2. 타이머의 영향을받는 부품을 가릴 때마다. 이는 다른보기 컨트롤러를 표시하거나 UIPickerView와 같은 다른 것들을 표시하여 그 아래에있는 화면의 더 큰 부분을 숨기기 때문일 수 있습니다. 3. 타이머를 재구성하거나 재설정해야 할 때마다.

를 잘 작성 엑스 코드 내에서 사용할 수 이러한 문제에 대한 우수한 문서의 톤 있습니다. (이 작업을 실패하면 앱이 처음부터 숙취 중단에 온 이유입니다), 그리고 온라인 :

  • View Contoller Programming Guide은 iOS의 모든 항목에서 꼭 읽어야 할 필수 항목입니다.
  • NSTimer Class Reference 및 연결된 동반 가이드는 매우 좋습니다. "작업"섹션 전에 개념적 부분을 확실히 읽으십시오. NSTimer 태그 아래 질문을받는 질문의 90 %를 넘어서서 사람들이 실제로 이것을 읽었는지 물어 보지 않을 것입니다 ...
0

해결책을 찾았습니다. 앱에서보기를 전환 할 수있게하는 모든 메소드에 [stopWatchTimer invalidate] 코드를 삽입했습니다. viewWriteTimer invalidate를 viewDidLoad 및 viewDidUnload 메서드에 포함 시켰을 때 아무 효과가 없었기 때문에이 기능이 작동하는 것에 놀랐습니다 ...

관련 문제