Работа с таймерами

Таймеры предоставляют способ выполнять отсроченное действие, или периодически повторяющиеся действия. Таймер ждет заданное время и посылает сообщение к заданному объекту.

Таймеры работают совместно с NSRunLoop объектами. Таймер не является механизмом, работающим в реальном времени, он срабатывает, только когда один из режимов цикла выполнения, к которому был добавлен таймер, работает и в состоянии проверить, что пришло время для срабатывания таймера. Поскольку различными источниками ввода управляет типичный цикл выполнения, эффективный временной интервал для таймера составляет 50-100 миллисекунд. Если таймер пропустил очередной период срабатывания, то при очередном прохождении цикла выполнения, если наступило время еще одного срабатывания, он сработает только один раз.

Должен-ли таймер быть повторяющимся или нет, вы указываете при его создании. Неповторяющийся таймер срабатывает только один раз, а затем сам себя аннулирует. Повторяющийся таймер после срабатывания перезапускается автоматически на том же цикле выполнения.

Повторяющийся таймер всегда старается сработать в запланированное время, т.е. если первое срабатывание произошло с задержкой, то следующее отсчитывается не от времени фактического последнего срабатывания, а от фактически запланированного, как говорилось выше, если таймер пропустил очередное срабатывание между своими периодами, он срабатывает только один раз, не допосылая пропущенные срабатывания.

Альтернатива таймерам

Если у вас имеется необходимость послать сообщение какому либо объекту в будущем, вы можете обойтись без использования таймеров. Класс NSObject, от которого унаследованы все классы Cocoa предоставляет эти методы. Используйте performSelector:withObject:afterDelay: для вызова напрямую метода из другого объекта. Как вариант можно использовать performSelectorOnMainThread:withObject:waitUntilDone: для вызова метода на основном потоке. Вы можете также отменить отсроченное сообщение, размещенное первым методом, используя cancelPreviousPerformRequestsWithTarget:.

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

Создавая таймер вы должны его сконфигурировать таким образом, чтобы он понимал какой метод и на каком объекте вызвать при срабатывании. Далее вы дожны разместить его на цикле выполнения, на котором он будет срабатывать, некоторые методы делают это за вас. И наконец, если вы создаете повторяющийся таймер, вы должны его освободить, когда захотите его остановить. Способы создания приведены во введении в класс NSTimer.

Пример:

Создадим в Xcode новый проект OS X - Cocoa Application. Откроем главное окно и сотворим нечто подобное:

Назначаем для текстового поля отображать doubleValue от элемента Stepper, в свою очередь для него назначаем шаг 0.1 и начальное значение 1.

Реализация AppDelegate.m

#import "AppDelegate.h"

@interface AppDelegate ()

- (void)stopTimer;

@property (weak) IBOutlet NSWindow *window;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
  // Insert code here to initialize your application
  formatter =[[NSDateFormatter alloc] init]; // форматтер для вывода даты и время
  [formatter setDateFormat:@"dd.MM.yyyy - HH:mm:ss"];
  tfInterval.doubleValue = stepperInterval.doubleValue;
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
  // Insert code here to tear down your application
}

- (IBAction)goStartStop:(id)sender {
  if(!activeState){ // start new Timer
    currentTimer = [NSTimer scheduledTimerWithTimeInterval:stepperInterval.doubleValue target:self
        selector:@selector(timerMethod:) userInfo:nil repeats:btRepeats.state];
    activeState = YES;
    btRepeats.enabled = NO;
    btStartStop.title = @"Stop";
  }
  else{ // stop Timer
    [self stopTimer];
  }
}

- (void)timerMethod:(id)object {
  NSDate* dt = [NSDate date]; // текущая дата и время
  NSString* s = [formatter stringFromDate:dt];
  tvResult.string = [NSString stringWithFormat:@"%@\n%@",tvResult.string,s];
  if(!btRepeats.state){ // неперезапускаемый таймер
    [self stopTimer];
  }
}

- (void)stopTimer{
  if(currentTimer.valid) // таймер действующий
    [currentTimer invalidate]; // отмена таймера
  activeState = NO;
  btRepeats.enabled = YES;
  btStartStop.title = @"Start";
  currentTimer = nil;
  tvResult.string = [NSString stringWithFormat:@"%@\n - Timer stoped",tvResult.string];
}
@end

Необходимо отметить, что метод valid появился только начиная с OS X 10.10 и iOS 8.

 
 
homeЗаметили ошибкукарта сайта 
   Made on a Mac