2010-06-02 7 views
2

저는 이것이 정말 간단하다는 것을 확신합니다. UITableView에 표시하기 위해 웹 서비스에서 데이터를 다운로드해야하는 응용 프로그램이 있으며 작업을 완료하는 데 X 초 이상 걸리는 경우 UIAlertView를 표시하려고합니다. 그래서 내가 (간결 간체)있어 무엇 :NSTimer가 타임 아웃 메커니즘으로 사용됩니다

MyViewController.h

@interface MyViewController : UIViewController 
     <UITableViewDelegate, UITableViewDataSource> { 
    NSTimer *timer; 
} 

@property (nonatomic, retain) NSTimer *timer; 

MyViewController.m

@implementation MyViewController 

@synthesize timer; 

- (void)viewDidLoad { 
    timer = [NSTimer scheduledTimerWithTimeInterval:20 
      target:self 
     selector:@selector(initializationTimedOut:) 
     userInfo:nil 
     repeats:NO]; 

    [self doSomethingThatTakesALongTime]; 
    [timer invalidate]; 
} 

- (void)doSomethingThatTakesALongTime { 
    sleep(30); // for testing only 
    // web service calls etc. go here 
} 

- (void)initializationTimedOut:(NSTimer *)theTimer { 
    // show the alert view 
} 

내 문제는 내가 기대하고있어 것입니다 [self doSomethingThatTakesALongTime] 타이머가 카운팅을 계속하는 동안 블록을 호출하고 타이머가 카운트 다운되기 전에 완료되면 스레드 제어를 viewDidLoad 여기서 [timer invalidate]은 타이머 취소를 진행합니다. 분명히 타이머/스레드가 작동하는 방식에 대한 나의 이해는 코드가 작성된 방식이기 때문에 여기에 결함이 있습니다. 타이머는 결코 꺼지지 않습니다. 그러나 [timer invalidate]을 제거하면됩니다.

답변

3

나는 타이머를 예약하고 같은 스레드에서 블로킹 호출을하는 것이 문제라고 생각한다. 블로킹 호출이 완료 될 때까지 run-loop는 타이머를 작동시킬 수 없습니다.

긴 작업을 수행하기 위해 스레드를 분리하는 것이 좋습니다. 긴 작업이 끝나면 주 스레드에서 다시 호출하여 타이머를 무효화하십시오.

참고 : 예약 된 동일한 스레드에서 타이머를 무효화하는 것이 중요합니다.

- (void)viewDidLoad { 
    timer = [NSTimer scheduledTimerWithTimeInterval:20 
      target:self 
     selector:@selector(initializationTimedOut:) 
     userInfo:nil 
     repeats:NO]; 

    [NSThread detachNewThreadSelector:@selector(doSomethingThatTakesALongTime:) toTarget:self withObject:nil]; 
} 

- (void)doSomethingThatTakesALongTime:(id)arg { 
    sleep(30); // for testing only 
    // web service calls etc. go here 
    [self performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:NO]; 
} 

- (void)invalidate { 
    [timer invalidate]; 
} 

- (void)initializationTimedOut:(NSTimer *)theTimer { 
    // show the alert view 
} 
+0

아주 잘 작동합니다. 내가 할 수 있었던 유일한 추가 작업은 doSomethingThatTakesALongTime 안에 NSAutoreleasePool을 초기화하는 것이 었습니다. 감사! – alexantd

+0

side note : 타이머를 무효화 할 때 일반적으로 무효화하기 전에 타이머가 0이 아닌지 확인한 후 타이머를 0으로 설정하는 것이 좋습니다. – Groot

0

[NSThread sleepforTimeInterval:30];을 사용해 보셨습니까?

0

sleep()는 주 스레드에서 발생하고 관련 실행 루프는 결코 타이머 선택기를 호출 할 수있는 기회가 없습니다.

예를 들어 스레드를 차단하지 않는 -doSomething에서 실제 작업을 수행하려는 경우 웹 서비스에 대한 비 차단 호출은 예상대로 작동합니다. 그러나 블로킹 호출은 다른 스레드에서 수행되어야하므로 기본 실행 루프가 차단되지 않습니다.