views:

676

answers:

2

If I have a view with a performSelector set to fire after a delay:

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

...but I removeFromSuperview that view before the selector fires (for example, due to user interaction), then my app crashes.

Is there a way to kill the delayed selector in the dealloc method for that view?

EDIT:

I've tried both:

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

and

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

and while both work (allowing me to load a new view), loading the previous view ends up giving me a gray screen.

I haven't been able to find any tutorials or other information about cancelPerformSelector other than those Apple docs that were listed, and the documentation on threads and run loops seem to be very convoluted (mostly because they don't list working code samples, which would make it easier for me to step through and understand what was going on).

+3  A: 

-cancelPerformSelectorsWithTarget:

or

-cancelPerformSelector:target:argument:

kperryua
Thanks for adding the links.
kperryua
No problem. You need the rep more than I do =).
Adam Rosenfield
Any idea where I could see a working code sample that uses these? This is all I've found so far... http://www.oomori.com/cocoafw/Foundation/NSRunLoop/cancelPerforrsWithTarget.html
Jeffrey Berthiaume
+1  A: 

Because I'm using performSelector:afterDelay, the only way I've been able to properly "kill" any previously requested but not launched functionality is using:

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

The following code sample shows how this works (create a new View template XCode project called "select", and replace the selectViewController.h file with this):

#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
Jeffrey Berthiaume