6

如果我有一个 performSelector 设置为延迟后触发的视图:

[self performSelector:@selector(generateBall) withObject:NULL afterDelay:1.5];

...但是我在选择器触发之前删除了该视图(例如,由于用户交互),然后我的应用程序崩溃了。

有没有办法杀死该视图的 dealloc 方法中的延迟选择器?

编辑:

我都试过了:

[[NSRunLoop mainRunLoop] cancelPerformSelector:theBall target:self argument:nil];

[[NSRunLoop currentRunLoop] cancelPerformSelector:theBall target:self argument:nil];

虽然两者都有效(允许我加载新视图),但加载前一个视图最终会给我一个灰屏。

除了列出的 Apple 文档之外,我找不到任何关于 cancelPerformSelector 的教程或其他信息,而且关于线程和运行循环的文档似乎非常复杂(主要是因为它们没有列出工作代码示例,其中会让我更容易逐步了解并了解正在发生的事情)。

4

3 回答 3

15

因为我正在使用 performSelector:afterDelay,所以我能够正确“杀死”任何先前请求但未启动的功能的唯一方法是使用:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:theBall object:nil];

以下代码示例展示了它是如何工作的(创建一个名为“select”的新 View 模板 XCode 项目,并将 selectViewController.h 文件替换为此):

#import "selectViewController.h"

@implementation selectViewController

UILabel *lblNum;
UIButton *btnStart, *btnStop;
int x;

- (void) incNum {
    x++;
    lblNum.text = [NSString stringWithFormat:@"%i", x];
    [self performSelector:@selector(incNum) withObject:NULL afterDelay:1.0];
}

- (void) stopCounter {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(incNum) object:NULL];
}

- (void)viewDidLoad {
    x = 0;

    lblNum = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    lblNum.textAlignment = UITextAlignmentCenter;
    [self.view addSubview:lblNum];

    btnStart = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    btnStart.frame = CGRectMake(40, 270, 240, 30);
    [btnStart setTitle:@"start" forState:UIControlStateNormal];
    [btnStart addTarget:self action:@selector(incNum) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btnStart];

    btnStop = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    btnStop.frame = CGRectMake(40, 310, 240, 30);
    [btnStop setTitle:@"stop" forState:UIControlStateNormal];
    [btnStop addTarget:self action:@selector(stopCounter) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btnStop];

    [self performSelector:@selector(incNum) withObject:NULL afterDelay:1.0];
    [super viewDidLoad];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
}

- (void)dealloc {
    [lblNum release];
    [super dealloc];
}

@end
于 2009-07-15T21:34:51.670 回答
5

-cancelPerformSelectorsWithTarget:

或者

-cancelPerformSelector:target:argument:

于 2009-07-14T03:14:35.690 回答
3

我发现这很好用:

[NSObject cancelPreviousPerformRequestsWithTarget:self];
于 2014-02-25T19:40:56.520 回答