-1

我正在做一个while循环,我正在尝试延迟它。

while (mode == 1)
{
    [self performSelector:@selector(on) withObject:nil afterDelay:slider.value];
    NSLog(@"on");
    [self performSelector:@selector(off) withObject:nil afterDelay:slider.value];
    NSLog(@"off");
}

但即使我将滑块设置为 10 秒,它也会非常快速地打开和关闭。

此外,我的应用程序黑屏,我只看到状态栏和我的 nslog,但这可能与其他事情有关。

4

7 回答 7

2

这就是您告诉您的应用程序的内容:
“从现在开始slider.value几秒钟内打开某些东西”
“从现在开始几秒钟内关闭某些东西slider.value
您认为这有什么问题吗?

于 2013-08-08T11:10:17.750 回答
2

performSelector:withObject:afterDelay:不等待选择器完成。这意味着一旦您告诉选择器 A 在特定时间后运行,它会立即继续并告诉选择器 B 在特定时间后运行。有很多选项可以解决此问题:

如果您想坚持使用选择器,可以使用performSelector:onThread:withObject:waitUntilDone:. 确保你不使用主线程,否则你会遇到 UI 冻结。

[NSThread waitForInterval]是另一个选项,但与前一个选项一样,除非您在不同的线程上调用整个 while 循环,否则它将冻结 UI。我很惊讶在没有人注意到这个重要因素的情况下被提及了这么多。

GCD 是另一种选择。它不会等待它完成,因此您不应该遇到主要的 UI 冻结。

dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, slider.value * NSEC_PER_SEC);
dispatch_after(dispatchTime, dispatch_get_main_queue(), ^(void){
    [self on];
    dispatch_after(dispatchTime, dispatch_get_main_queue(), ^(void){
        [self off];
    })
});

另一种选择是保留您现在正在做的事情并让选择器 B 在 slider.value*2 之后运行。如果您以数学方式考虑这一点,那是有道理的:

A) 0-1-2-3-4-5-6-7-8-9-10
B) 0-1-2-3-4-5-6-7-8-9-10-1-2-3-4-5-6-7-8-9-10
于 2013-08-08T11:14:38.923 回答
0
double delayInSeconds = slider.value;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self off];
    //or
    [self on];
});

这会在给定时间后执行块内的任何操作!:)

于 2013-08-08T11:09:39.870 回答
0

while 循环不会等待延迟的操作完成,它只是安排它们。问题是您将所有事件安排在一个非常快速的循环中,然后在 10 秒后以同样快的速度一个接一个地运行这些事件。

于 2013-08-08T11:11:02.380 回答
0
[self performSelector:@selector(on) withObject:nil afterDelay:slider.value];

在这个语句中 afterDelay 并不意味着它会暂停几秒钟。

这意味着方法“on”将在几秒钟后执行。但是执行不会等到方法“on”的执行完成并转到下一条语句。

如果您只想延迟一些时间,则可以使用以下语句:

[NSThread sleepForTimeInterval:2.0];

这将等待 2 秒。但这可能不是一个好主意,因为它会冻结你的 UI。

我希望这能帮到您。

一切顺利.....

于 2013-08-08T11:14:10.703 回答
0

如果你想立即打开它并关闭它指定的延迟:

[self on];
NSLog(@"on");
[self performSelector:@selector(off) withObject:nil afterDelay:slider.value];
NSLog(@"off");

如果您想在指定的延迟后打开它,然后在 10 秒后再次关闭它:

[self performSelector:@selector(on) withObject:nil afterDelay:slider.value];
NSLog(@"on");
[self performSelector:@selector(off) withObject:nil afterDelay:slider.value + 10];
NSLog(@"off");
于 2013-08-08T12:48:20.143 回答
-1

尝试使用 [NSThread sleepForTimeInterval:1.0f];它将根据您提供的时间停止您的线程

于 2013-08-08T11:12:28.963 回答