Selector syntax for swift 3.0
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Swift 3.0 replaced string-based selectors with the #selector expression, giving compile-time checking for method references used in target-action patterns and notification observers. Before Swift 3, selectors were raw strings like "buttonTapped:" that would crash at runtime if misspelled. The #selector syntax catches these errors at compile time and auto-completes in Xcode. Any method referenced by #selector must be exposed to Objective-C with @objc.
Basic #selector Syntax
The #selector(buttonTapped) expression resolves to a Selector value at compile time. If buttonTapped does not exist or is not marked @objc, the compiler emits an error.
Selectors with Parameters
When the method takes a parameter, include the argument label in the #selector expression. #selector(handleTap(_:)) matches func handleTap(_ sender: UITapGestureRecognizer).
Disambiguating Overloaded Methods
When multiple methods share the same base name, cast to the specific function signature to tell the compiler which overload you mean.
Selectors for Properties (Getter/Setter)
Use #selector(getter:) and #selector(setter:) to reference property accessors, commonly used with KVO and key-value observing APIs.
Notification Observers
Migration from Swift 2 to Swift 3
String-based selectors compile but produce a deprecation warning in Swift 3 and are removed in later versions. Always use #selector for compile-time safety.
@objc Requirement
Every method referenced by #selector must be @objc. In Swift 4+, methods are not implicitly @objc even if the class inherits from NSObject, so the annotation is always required.
Common Pitfalls
- Forgetting @objc:
#selectoronly works with methods exposed to Objective-C. Omitting@objcproduces a compile error. In Swift 4+, inheriting fromNSObjectalone is not enough. - Wrong argument labels:
#selector(handleTap)fails if the method isfunc handleTap(_ sender: UITapGestureRecognizer). You need#selector(handleTap(_:))with the argument label. - Using string selectors:
Selector("methodName")bypasses compile-time checking and crashes at runtime if the method does not exist. Always use#selector. - Ambiguous overloads without cast: When multiple methods share a name,
#selector(process)is ambiguous. Disambiguate with#selector(process as () -> Void). - Structs and enums:
#selectorrequires Objective-C compatibility, which means the containing type must be a class (inheriting fromNSObject). Structs and enums cannot use#selector.
Summary
- Use
#selector(methodName)for compile-time checked selectors in Swift 3+ - Include argument labels for methods with parameters:
#selector(handleTap(_:)) - Disambiguate overloads with type casts:
#selector(method as (String) -> Void) - Use
#selector(getter:)and#selector(setter:)for property accessors - All selector targets must be marked
@objc— Swift 4+ does not infer this - Never use string-based
Selector("...")— it bypasses compile-time safety

