Как использовать NSTimer?

Как использовать NSTimer? Может ли кто-нибудь дать мне пошаговые инструкции?

Ответ 1

Во-первых, я хотел бы обратить ваше внимание на документацию Cocoa/CF (которая всегда является отличным первым портом захода). В документах Apple есть раздел в верхней части каждой справочной статьи под названием "Путеводители компаньонов", в которой перечислены руководства для документируемого документа (если таковые существуют). Например, при NSTimer, в документации перечислены два справочника для компаньонов:

В вашей ситуации статья "Темы программирования таймера", вероятно, будет наиболее полезной, в то время как темы потоков связаны, но не могут быть непосредственно связаны с документированным классом. Если вы посмотрите на статью о программировании таймера, она разделена на две части:

  • Таймеры
  • Использование таймеров

В статьях, которые принимают этот формат, часто присутствует обзор класса и того, для чего он использовался, а затем пример кода для его использования, в этом случае в разделе "Использование таймеров". Существуют разделы "Создание и планирование таймера", "Остановка таймера" и "Управление памятью". Из этой статьи создание запланированного, не повторяющегося таймера можно сделать примерно так:

[NSTimer scheduledTimerWithTimeInterval:2.0
    target:self
    selector:@selector(targetMethod:)
    userInfo:nil
    repeats:NO];

Это создаст таймер, который запускается через 2.0 секунды и вызывает targetMethod: on self с одним аргументом, который является указателем на экземпляр NSTimer.

Если вы хотите более подробно ознакомиться с этим методом, вы можете обратиться к документам за дополнительной информацией, но также есть объяснение вокруг кода.

Если вы хотите остановить таймер, который повторяется, (или остановить не повторяющийся таймер перед его запуском), вам нужно сохранить указатель на созданный экземпляр NSTimer; часто это должна быть переменная экземпляра, чтобы вы могли ссылаться на нее другим методом. Затем вы можете вызвать invalidate в экземпляре NSTimer:

[myTimer invalidate];
myTimer = nil;

Это также хорошая практика для nil из переменной экземпляра (например, если ваш метод, который делает недействительным таймер, вызывается более одного раза, а переменная экземпляра не была установлена ​​на nil, а экземпляр NSTimer был отменен, он выдает исключение).

Обратите внимание также на пункт управления памятью в нижней части статьи:

Поскольку цикл выполнения поддерживает таймер, с точки зрения управления памятью обычно нет необходимости хранить ссылку на таймер после того, как вы запланировали его. Поскольку таймер передается в качестве аргумента, когда вы указываете его метод как селектор, вы можете аннулировать повторяющийся таймер, когда это необходимо, в этом методе. Однако во многих ситуациях вы также хотите отключить таймер, возможно, даже до его запуска. В этом случае вам необходимо сохранить ссылку на таймер, чтобы при необходимости можно было отправить сообщение о недействительности. Если вы создаете незапланированный таймер (см. "Невыпланированные таймеры" ), вы должны поддерживать сильную ссылку на таймер (в среде с подсчетом ссылок, вы его сохраняете), чтобы он не был освобожден до того, как вы его используете.

Ответ 2

существует несколько способов использования таймера:

1) запланированный таймер и с помощью селектора

NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
                      target: self
                      selector:@selector(onTick:)
                      userInfo: nil repeats:NO];
  • Если вы установите повторы на NO, таймер будет ждать 2 секунды перед запуском селектора, после чего он остановится;
  • если повтор: ДА, таймер начнет немедленно и повторит вызов селектора каждые 2 секунды;
  • чтобы остановить таймер, который вы вызываете методом таймера: -valvalate: [t invalidate];

В качестве побочного примечания вместо использования таймера, который не повторяется, и вызывает селектор через указанный интервал, вы можете использовать простой оператор, подобный этому:

[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];

это будет иметь тот же эффект, что и примерный код выше; но если вы хотите вызвать селектор каждый n-й раз, вы используете таймер с повторами: YES;

2) самонастраиваемый таймер

NSDate *d = [NSDate dateWithTimeIntervalSinceNow: 60.0];
NSTimer *t = [[NSTimer alloc] initWithFireDate: d
                              interval: 1
                              target: self
                              selector:@selector(onTick:)
                              userInfo:nil repeats:YES];

NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer:t forMode: NSDefaultRunLoopMode];
[t release];
  • это создаст таймер, который запустится сам по заданной вами заданной дате (в этом случае через минуту) и повторяется каждую секунду

3) незапланированный таймер и использование вызова

NSMethodSignature *sgn = [self methodSignatureForSelector:@selector(onTick:)];
NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sgn];
[inv setTarget: self];
[inv setSelector:@selector(onTick:)];

NSTimer *t = [NSTimer timerWithTimeInterval: 1.0
                      invocation:inv 
                      repeats:YES];

и после этого вы запускаете таймер вручную, когда вам это нужно:

NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];



И как примечание, метод onTick: выглядит следующим образом:

-(void)onTick:(NSTimer *)timer {
   //do smth
}

Ответ 3

Что-то вроде этого:

NSTimer *timer;

    timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
                     target: self
                     selector: @selector(handleTimer:)
                     userInfo: nil
                     repeats: YES];

Ответ 4

#import "MyViewController.h"

@interface MyViewController ()

@property (strong, nonatomic) NSTimer *timer;

@end

@implementation MyViewController

double timerInterval = 1.0f;

- (NSTimer *) timer {
    if (!_timer) {
        _timer = [NSTimer timerWithTimeInterval:timerInterval target:self selector:@selector(onTick:) userInfo:nil repeats:YES];
    }
    return _timer;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

-(void)onTick:(NSTimer*)timer
{
    NSLog(@"Tick...");
}

@end

Ответ 5

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];

-(void)timerCalled
{
     NSLog(@"Timer Called");
     // Your Code
}

Ответ 6

В ответах отсутствует определенное время суток, в течение следующего часа:

NSCalendarUnit allUnits = NSCalendarUnitYear   | NSCalendarUnitMonth |
                          NSCalendarUnitDay    | NSCalendarUnitHour  |
                          NSCalendarUnitMinute | NSCalendarUnitSecond;

NSCalendar *calendar = [[ NSCalendar alloc]  
                          initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *weekdayComponents = [calendar components: allUnits 
                                                  fromDate: [ NSDate date ] ];

[ weekdayComponents setHour: weekdayComponents.hour + 1 ];
[ weekdayComponents setMinute: 0 ];
[ weekdayComponents setSecond: 0 ];

NSDate *nextTime = [ calendar dateFromComponents: weekdayComponents ];

refreshTimer = [[ NSTimer alloc ] initWithFireDate: nextTime
                                          interval: 0.0
                                            target: self
                                          selector: @selector( doRefresh )
                                          userInfo: nil repeats: NO ];

[[NSRunLoop currentRunLoop] addTimer: refreshTimer forMode: NSDefaultRunLoopMode];

Конечно, замените "doRefresh" на ваш желаемый метод класса

попытайтесь создать объект календаря один раз и сделать allUnits статическим для эффективности.

добавление компонента "один час" отлично работает, нет необходимости в полночь (ссылка)