实现这个的好方法?

时间:2014-02-26 00:53:39

标签: ios objective-c

这是我的需要:

我正在制作一个控制设备的ios应用。它有一个API,可以让我做以下事情:

turnOnLights()
turnOffLights()
rotate(degrees)
move(speed)

等......(api完全是客观的c,我只是在c synthax中给出一个例子)

从这个API,我需要构建高级序列,例如:

   turn on all lights
    wait 1 second
    turn off all lights
   wait 1 second

或者

move
rotate 30 degrees
wait 1 second
move
rotate -30 degrees

我可以想到使用计时器执行这些操作的hacky方法,但我想知道ObjectiveC是否有一种很好的方法可以构建一些高级方法,所以我可以这样做:

ReturnValue flashLights()
ReturnValue moveAndRotate()

这背后的想法是,执行闪烁操作所需的命令将永远重复发送,我可以这样做:

stopAction(returnValue)

要阻止它。 (我知道我用C语言写作,但我发现解释的事情更清楚了。)

基本上,有一种方便的方法来制作类似脚本的东西,我可以调用一个启动动作的方法。该操作进行方法调用,等待一段时间,进行更多方法调用,并永远重复此操作直到操作停止。

由于

2 个答案:

答案 0 :(得分:1)

我不确定我是否理解你的问题,但如果你想反复调用一组延迟介于两者之间的方法,你可以使用performSelector:withObject:afterDelaydispatch_after来构建一个循环。 (并且有许多方法可以离开循环)

[self performSelector:@selector(resetIsBad) withObject:nil afterDelay:0.1];

int delayInSecond = 10;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delayInSecond * NSEC_PER_SEC), 
dispatch_get_main_queue(), ^{
   //doing something    
});

performSelector:withObject:afterDelay在延迟后使用默认模式在当前线程上调用接收器的方法。

  

此方法设置一个计时器来执行aSelector消息   当前线程的运行循环。计时器配置为在。中运行   默认模式(NSDefaultRunLoopMode)。当计时器触发时,线程   尝试从运行循环中取消消息并执行   选择。如果运行循环正在运行并且在默认情况下,它会成功   模式;否则,计时器等待直到运行循环处于默认状态   模式。

dispatch_after将您的块添加到队列中,如果队列为空,则在添加到队列后立即运行。否则,它必须等待队列中的其他任务完成才能运行。

有关dispatch_after的更多信息:

  

<强> dispatch_after

     

将一个块排队以便在指定时间执行。

void dispatch_after( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);
     

参数:

     

何时时间   dispatch_time或dispatch_walltime返回的里程碑。

     

队列   提交块的队列。队列由。保留   系统直到块运行完成。这个参数不能   空值。

     

阻止要提交的阻止。此函数执行Block_copy   和Block_release代表调用者。这个参数不能   空值。

     

讨论

     

此功能等待到指定的时间然后   异步将块添加到指定的队列。

     

支持DISPATCH_TIME_NOW作为when参数,但是   不像调用dispatch_async那样最优。通过   DISPATCH_TIME_FOREVER未定义。

     

在dispatch / queue.h中声明

答案 1 :(得分:0)

就个人而言,只要你正确地实施它,我认为使用NSTimer不会是'hacky'。完成后,您需要确保使计时器无效;有关NSTimer最佳做法的详情,请查看this thread

// in YourViewController.h
@property (nonatomic) BOOL flag;
@property (nonatomic, strong) NSTimer* timer;

// in YourViewController.m
-(void)viewDidLoad
{
    [super viewDidLoad];

    self.flag = YES;
    [self flashLights];

    // other code here
}

-(void)flashLights
{
    CGFloat interval = 1.0f;    // measured in seconds

    self.timer = [NSTimer scheduledTimerWithTimeInterval:interval 
                                                  target:self
                                                selector:@selector(timerEventHandler)
                                                userInfo:nil
                                                 repeats:YES];
}

-(void)timerEventHandler
{
    // your API calls might take a while to execute, so consider running them asynchronously:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
    {
        if (self.flag) turnOnLights();
        else turnOffLights();

        self.flag = !self.flag;
    });
}

-(void)stopAction
{
    [self.timer invalidate];
}