작업 대기열에서 제공하는 종속성, 취소 및 기타 기능을 활용하기 위해 타이머와 같은 방법으로 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를 처리 할 수 있습니다.
언제든지 확인할 수 있습니다. 타이머에 의해 호출되는 메소드에서,'[NSThread isMainThread]'의 결과를 로그에 기록하십시오. –
고마워요! 도움이됩니다! –
실제로 NSOperation의 스레드에 있습니다! –