NSTimer в NSOperation основной метод? - PullRequest
3 голосов
/ 29 марта 2011

Я хочу установить таймер в методе -(void) main {} подкласса NSOperation. Тем не менее, я таймер не срабатывает. Я пытался [[NSRunLoop currentRunLoop] addTimer:timer forMode: NSDefaultRunLoopMode]; безуспешно. Я скучаю по чему-то?

[EDIT] Будет ли запускать таймер в основном потоке или в потоке NSOperation? (угадывая NSOperation, но я не уверен)

Ответы [ 2 ]

5 голосов
/ 29 марта 2011

Я нашел, что нужно сделать, чтобы запустить таймер.Я помещу это здесь, если кому-нибудь когда-нибудь понадобится:

[[NSRunLoop currentRunLoop] run];

Однако я все еще не уверен, будет ли это выполняться в потоке NSOperation.

2 голосов
/ 28 августа 2011

Я считаю, что иногда полезно обернуть NSOperation вокруг метода, который запускается таймером, как вы делаете, чтобы воспользоваться преимуществами зависимостей, отмены и других функций, предоставляемых очередью операций. Однако, как правило, нет необходимости запускать таймер в отдельном потоке, а также не требуется, чтобы метод, который вызывает таймер, выполнялся в фоновом потоке. Фактически, большую часть времени он не должен выполняться в фоновом потоке, потому что метод обновляет пользовательский интерфейс. Если это верно и для вас, такая установка должна работать:

#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

Конечно, если основной поток заблокирован (например, из-за длительного сохранения базы данных), вы не увидите срабатывание таймера, но в большинстве случаев это работает нормально.

Вы можете использовать ту же настройку для работы с асинхронными API внутри NSOperations.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...