Как убить селектор, который срабатывает после задержки (на iPhone)? - PullRequest
6 голосов
/ 14 июля 2009

Если у меня есть представление с заданным параметром executeSelector с задержкой:

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

... но я удаляю из этого просмотра вид из окна перед тем, как селектор сработает (например, из-за взаимодействия с пользователем), затем мое приложение вылетает.

Есть ли способ убить отложенный селектор в методе dealloc для этого представления?

EDIT:

Я пробовал оба:

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

и

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

и в то время как оба работают (что позволяет мне загружать новый вид), загрузка предыдущего вида заканчивается тем, что у меня появляется серый экран.

Мне не удалось найти какие-либо учебные пособия или другую информацию о cancelPerformSelector, кроме перечисленных выше документов Apple, а документация по потокам и циклам выполнения выглядит очень запутанной (в основном из-за того, что в них нет рабочего кода). образцы, которые облегчили бы мне шаг за шагом и понять, что происходит).

Ответы [ 3 ]

15 голосов
/ 16 июля 2009

Поскольку я использую executeSelector: afterDelay, единственный способ, которым я смог правильно "убить" любые ранее запрошенные, но не запущенные функции, использует:

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

В следующем примере кода показано, как это работает (создайте новый проект XCode шаблона View с именем «select» и замените файл 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
5 голосов
/ 14 июля 2009
3 голосов
/ 25 февраля 2014

Я обнаружил, что это прекрасно работает:

[NSObject cancelPreviousPerformRequestsWithTarget:self];
...