How do we stop a "performSelector:withObject:afterDelay:"

Hello all,

I’ve been successfully using performSelector:withObject:afterDelay: for a while now and find it very usefull, but I got to a point now where I would need it to be cancelled because the situation that generated it in the first place has changed and causes refresh problems.

I have looked at the docs and found:

  • cancelPreviousPerformRequestsWithTarget:
  • cancelPreviousPerformRequestsWithTarget:selector:object:

but none of them work. It gives this error:

unrecognized selector sent to object <MYDelegate @0x2008b6a40: OSAID(81)> (error -10000)

I used them like this:

	cancelPreviousPerformRequestsWithTarget_selector_object_(me, "mySelector:", missing value)

before calling the performSelector…

	performSelector_withObject_afterDelay_("mySelector:", myObject, 10)

Also, this would cause a timing problem I think. Since I call a cancel before I ever made any performSelector, what is there to cancel I wonder? Of course this would cause an error, but even after I have confirmed there was one running, it still doesn’t work. I think only my sequence is wrong, but how to implement it correctly is beyond me right now. I have also looked for a method that verifies the presence of a pre-existing performSelector, but no result yet.

Any ideas?


performSelector_withObject_afterDelay_("mySelector:", myObject, 10)

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

The two methods:
cancelPreviousPerformRequestsWithTarget_selector_object_(me, “mySelector:”, missing value)

are both class methods of NSObject, so I think you have to invoke them like this:

current application’s NSObject’s cancelPreviousPerformRequestsWithTarget_(me)


Ah! Thats true! I keep forgetting about that. Thanks I’ll have a try and post the results. :slight_smile:

Browser: Safari 6533.18.5
Operating System: Mac OS X (10.6)

You can also step around the problem by setting a boolean property. Have the delayed handler check the value of the property and only proceed if its true.

Yep, the boolean value is a good idea. But turns out there is no error that pops-up after modifying this:



current application's NSObject's cancelPreviousPerformRequestsWithTarget_(me)

as suggested.

But what is the main difference between cancelPreviousPerformRequestsWithTarget: and cancelPreviousPerformRequestsWithTarget:selector:object: ? My feeling is that the first one will cancel pretty much any scheduled task without discerning which is which, so I may end up killing a schedule that I did not intent to while leaving the one I wanted gone still alive. As for the second one, feels like I can be more specific, but it totally crashed my app without any error message in the log when used like this:

cancelPreviousPerformRequestsWithTarget_selector_object_(me, "mySelector:", missing value)

Maybe I need to pass it an object to be happy, dunno which one though, I don’t see what could be helping…

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

I think so – you can’t have a selector ending in a colon and then no argument. I presume it wants the object you used originally, myObject.

I wonder if you’d be better off using NSTimer directly, rather than performSelector:withObject:afterDelay:, if you are going to be cancelling stuff regularly. Then you could just invalidate the particular timer.

Yes, I see what you mean… scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: indeed looks interesting. There is an invalidate instance method, which is exactly what I wanted. Also there is a isValid method… cool!

Got a last question about NSTimer: how would you set it to fire at a precise point in time instead of every n seconds? I only see seconds as being the only valid option when creating this NSTimer object… maybe invoke setFireDate: on the NSTimer object after it’s creation with, say, 3600 seconds as the time interval value?

Thanks everyone for your help!

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)