这是我的需要:
我正在制作一个控制设备的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语言写作,但我发现解释的事情更清楚了。)
基本上,有一种方便的方法来制作类似脚本的东西,我可以调用一个启动动作的方法。该操作进行方法调用,等待一段时间,进行更多方法调用,并永远重复此操作直到操作停止。
由于
答案 0 :(得分:1)
我不确定我是否理解你的问题,但如果你想反复调用一组延迟介于两者之间的方法,你可以使用performSelector:withObject:afterDelay
或dispatch_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];
}