在iOS中执行具有时间顺序的任务

时间:2014-11-07 10:35:39

标签: ios objective-c nstimer

我想用[5s,10s,10s,20s]这样的时间序列执行一些代码,这意味着它在5秒后执行代码,并在10s后第二次执行。我想使用NSTimer,但我无法弄清楚我该怎么做。

2 个答案:

答案 0 :(得分:0)

创建一个数据结构来保存时间间隔,目标和要执行的操作:

(未测试的)

typedef struct {
    NSTimeInterval interval;
    id target;
    SEL selector;
} ScheduledItem;

然后创建这些项目的数组:

static ScheduledItem _schedule[] = {
    { 5.0, someTarget, @selector(someMethod) },
    { 10.0, someTarget, @selector(someMethod) },
    { 15.0, someTarget, @selector(someMethod) }
};
#define NUM_SCHEDULED_ITEMS (sizeof(schedule) / sizeof(schedule[0]))

然后在某处创建一个计时器来分派工作:

@interface MyClass ()
{
    NSTimer *_timer;
    unsigned _scheduledItem;
}
- (void)_setupTimer;
- (void)_timerFired:(NSTimer *)timer;
@end

@interface MyClass

- (instancetype)init
{
    self = [super init];
    if (self) {
        _scheduledItem = 0;
        [self _setupTimer];
    }
    return self;
}

- (void)_setupTimer
{
    _timer = nil;
    if (_scheduledItem < NUM_SCHEDULED_ITEMS) {
        NSTimeInterval interval = _schedule[_scheduledItem].interval
        _timer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                  target:self
                                                selector:@selector(_timerFired:)
                                                userInfo:nil
                                                 repeats:NO];
    }
}

- (void)_timerFired:(NSTimer *)timer
{
    id target = _schedule[_scheduledItem].target;
    SEL action = _schedule[_scheduleItem].action;
    [target performSelector:action withObject:nil];
    _scheduledItem++;
    [self _setupTimer];
}

您很可能必须在运行时设置_schedule数组,因为target在编译时不可用。如果它始终为self,那么您可以将它完全排除在计划之外,如果您总是调用相同的选择器,那么您也可以将其保留,只留下一系列时间间隔。

答案 1 :(得分:0)

我的方法实现起来有点简单。

- (void)startExecute
  { 
    intervals=@[@(5),@(10),@(10),@(20)]; // class member
    isExecuting=YES; // class member
    [self executeTaskAtIndex:0]; // start first task
  }

- (void)executeTaskAtIndex:(NSUInteger)index
  { 
   if (index>=intervals.count || !isExecuting) // no intervals left or reset execution
       return;
   NSNumber *intervalNumber=intervals[index];
   NSTimeInterval interval=intervalNumber.doubleValue;
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      if(!isExecuting)
         return;
      // execute your task here
      //...
      index++;
      [self executeTaskAtIndex:index]; // another iteration
   });
  }