Swift performSelectorwithObjectafterDelay is unavailable
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
performSelector:withObject:afterDelay: belongs to Objective-C's selector-based runtime style. Swift does not encourage that pattern because it is not type-safe, and the idiomatic replacement is usually DispatchQueue.asyncAfter.
Why Swift Pushes You Away from Selectors Here
Swift prefers APIs that are:
- checked at compile time
- explicit about parameter types
- harder to misuse with misspelled selector names
A selector string can fail at runtime if the method name or parameter shape is wrong. Closures are much safer and clearer in Swift, so delayed execution is usually expressed with a closure rather than a selector.
The Standard Replacement: DispatchQueue.asyncAfter
For one-shot delayed work on the main thread, use:
This is the normal replacement for "do this later on the UI thread."
Replacing the Classic Objective-C Pattern
Old Objective-C style:
Swift style:
This is easier to read and safer because the compiler understands the target method directly.
Passing Values to the Delayed Code
Instead of passing an untyped object, capture the value in the closure:
Closures make value passing straightforward and type-safe.
Cancelable Delayed Work
If you need to cancel a pending delayed action, use DispatchWorkItem:
This is a good fit for debouncing or replacing previously scheduled work.
When Timer Is Better
Use Timer when the task is naturally timer-shaped, especially if it repeats:
For one-shot delayed execution, DispatchQueue.asyncAfter is usually simpler. For repeated events or run-loop-oriented behavior, Timer may be the better abstraction.
Swift Concurrency Option
If you are already inside async Swift code, Task.sleep can be a good fit:
This keeps the delay inside the structured-concurrency model instead of dropping to GCD directly.
Choosing the Right Tool
A practical rule is:
- one delayed UI action: use
DispatchQueue.asyncAfter - cancelable delayed work: use
DispatchWorkItem - timer-oriented repeated behavior: use
Timer - async workflow already using
asyncandawait: useTask.sleep
Thinking in those categories usually leads to cleaner code than trying to reproduce the old selector API directly.
Memory Management Notes
Delayed closures can outlive the object that scheduled them. In UI code, a weak capture of self is often the right choice:
That prevents the delayed block from keeping the owner alive unnecessarily.
Common Pitfalls
The biggest mistake is looking for a one-to-one Swift spelling of performSelector:withObject:afterDelay: instead of switching to DispatchQueue.asyncAfter.
Another mistake is capturing self strongly in a delayed closure when the owner should be allowed to deallocate.
People also use Timer when they only need one delayed block, which adds unnecessary complexity.
Finally, cancellation is not automatic. If the delayed action may become irrelevant, use DispatchWorkItem or another explicit cancellation strategy.
Summary
- '
performSelector:withObject:afterDelay:is unavailable in Swift because selector-based delayed invocation is not the preferred Swift model.' - The usual replacement is
DispatchQueue.asyncAfter. - Closures let you pass values safely without untyped selector arguments.
- Use
DispatchWorkItemwhen you need cancelable delayed work. - Use
TimerorTask.sleeponly when those abstractions better match the surrounding code.

