2011-03-29 6 views
3

-(void) main {} NSOperation 하위 클래스의 메서드에 타이머를 설정하고 싶습니다. 그러나 나는 타이머가 작동하지 않는다. 나는 성공한 [[NSRunLoop currentRunLoop] addTimer:timer forMode: NSDefaultRunLoopMode];을 시도했다. 내가 잃어버린 재치가 있습니까?NSOperation 기본 방법의 NSTimer?

[편집] 주 스레드 또는 NSOperation의 스레드에서 타이머가 실행됩니까? (NSOperation 추측하지만 확실하지 않습니다.)

답변

5

타이머를 시작하기 위해 수행해야 할 작업을 발견했습니다.

[[NSRunLoop currentRunLoop] run]; 

는 그러나, 나는 여전히이 NSOperation의 스레드에서 실행됩니다 있는지 확실하지 않습니다 : 누구도 그것을 필요로하는 경우 여기를 넣을 수 있습니다.

+1

언제든지 확인할 수 있습니다. 타이머에 의해 호출되는 메소드에서,'[NSThread isMainThread]'의 결과를 로그에 기록하십시오. –

+0

고마워요! 도움이됩니다! –

+0

실제로 NSOperation의 스레드에 있습니다! –

2

작업 대기열에서 제공하는 종속성, 취소 및 기타 기능을 활용하기 위해 타이머와 같은 방법으로 NSOperation을 래핑하는 것이 유용 할 때가 있습니다. 그러나 일반적으로 타이머가 별도의 스레드에서 실행될 필요는 없으며 타이머가 호출하는 메소드가 백그라운드 스레드에서 실행될 필요도 없습니다. 실제로 대부분의 경우 은 UI가 업데이트되기 때문에 배경 스레드에서을 실행하면 안됩니다. 이것이 사실이라면 다음과 같은 설정이 필요합니다.

#import <Foundation/Foundation.h> 

@interface TimerOperation : NSOperation { 
@private 
    NSTimer* _timer; 
} 

@property (nonatomic, readonly) BOOL isExecuting; 
@property (nonatomic, readonly) BOOL isFinished; 

@end 

(자신의 상태, 맞춤 생성자 등을 추가).

@implementation TimerOperation 

@synthesize isExecuting = _executing; 
@synthesize isFinished = _finished; 

- (id) init { 
    if ((self = [super init])) { 
     _executing = NO; 
     _finished = NO; 
    } 

    return self; 
} 

- (void) dealloc { 
    [_timer release]; 
    [super dealloc]; 
} 

- (BOOL) isConcurrent { 
    return YES; 
} 

- (void) finish { 
    [self willChangeValueForKey:@"isFinished"]; 
    [self willChangeValueForKey:@"isExecuting"]; 
    _executing = NO; 
    _finished = YES; 
    [self didChangeValueForKey:@"isExecuting"]; 
    [self didChangeValueForKey:@"isFinished"]; 
} 

- (void) start { 
    if ([self isCancelled]) { 
     [self willChangeValueForKey:@"isFinished"]; 
     _finished = YES; 
     [self didChangeValueForKey:@"isFinished"]; 
    } else { 
     [self willChangeValueForKey:@"isExecuting"]; 
     [self performSelectorOnMainThread:@selector(main) 
           withObject:nil 
          waitUntilDone:NO]; 
     _executing = YES; 
     [self didChangeValueForKey:@"isExecuting"]; 
    } 
} 

- (void) timerFired:(NSTimer*)timer { 
    if (![self isCancelled]) { 
     // Whatever you want to do when the timer fires 
    } 
} 

- (void) main { 
    _timer = [[NSTimer scheduledTimerWithTimeInterval:1.0 
               target:self 
              selector:@selector(timerFired:) 
              userInfo:nil 
               repeats:YES] retain]; 
} 

- (void) cancel { 
    [_timer invalidate]; 
    [super cancel]; 
} 

@end 
물론

, 메인 쓰레드는 당신이 타이머 발사를 볼 수 없습니다 (때문에 긴 데이터베이스에 저장 예를 들어,) 차단되면,하지만 대부분의 시간이 잘 작동합니다.

동일한 설정을 사용하여 NSOperations에서 비동기 API를 처리 할 수 ​​있습니다.

+0

이 예제에서 타이머에 대한 참조를 유지하는 이유는 무엇입니까? – Tony

+0

취소 할 때 [_timer invalidate]를 호출 할 수 있습니다. – edsko