2011-03-29 28 views
3

我想在一个NSOperation子类的-(void) main {}方法中设置一个定时器。但是,我的计时器不会启动。我试过[[NSRunLoop currentRunLoop] addTimer:timer forMode: NSDefaultRunLoopMode];没有成功。我错过了吗?NSTimer在NSOperation中的主要方法?

[编辑]这会在主线程或NSOperation的线程上运行定时器吗? (猜测NSOperation,但我不确定)

回答

5

我发现需要做什么来启动计时器。我把它放在这里,如果有谁需要它:

[[NSRunLoop currentRunLoop] run]; 

不过,我仍然不知道这是否会在的NSOperation的线程中运行。

+1

你总是可以找到。在定时器调用的方法中,记录'[NSThread isMainThread]'的输出' – 2011-03-29 20:35:45

+0

谢谢!这很有帮助! – 2011-03-29 21:05:45

+0

确实在NSOperation的线程上! – 2011-03-29 21:15:22

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 2012-01-22 19:38:24

+0

这样我们可以在取消中调用[_timer invalidate]。 – edsko 2012-01-25 16:53:46