Swift 3 protocol extension using selector error - ios

I have what I thought to be a very simple protocol extension for my UIViewControllers providing the capability to dismiss a keyboard through a tap gesture. Here's my code:
#objc protocol KeyboardDismissing {
func on(tap: UITapGestureRecognizer)
}
extension KeyboardDismissing where Self: UIViewController {
func addDismissalGesture() {
let tap = UITapGestureRecognizer(target: self, action: #selector(Self.on(tap:)))
view.addGestureRecognizer(tap)
}
func on(tap: UITapGestureRecognizer) {
dismissKeyboard()
}
func dismissKeyboard() {
view.endEditing(true)
}
}
The problem is that the above code throws a compile error on this line:
let tap = UITapGestureRecognizer(target: self, action: #selector(Self.on(tap:)))
With the error message:
Argument of '#selector' refers to instance method 'on(tap:)' that is not exposed to Objective-C
with the suggestion to "fix it" by adding #objc before func on(tap: UITapGestureRecognizer)
Ok fine, I add the tag:
#objc func on(tap: UITapGestureRecognizer) {
dismissKeyboard()
}
But then, it throws a different compile error on this newly added #objc tag with the error message:
#objc can only be used with members of classes, #objc protocols, and concrete extensions of classes
with the suggestion to "fix it" by removing the exact same tag I was just told to add.
I originally thought adding #objc before my protocol definition would solve any #selector problems but apparently that's not the case, and these cyclical error messages/suggestions aren't helping in the slightest. I've gone down a wild goose chase of adding/removing #objc tags everywhere, marking methods as optional, putting methods in the protocol's definition, etc.
It also doesn't matter what I put in the protocol definition Leaving the extension the same, the following example does not work nor does any combination of the declared methods in the protocol's definition:
#objc protocol KeyboardDismissing {
func on(tap: UITapGestureRecognizer)
}
This tricks me into thinking it works by compiling as a stand alone protocol, but the second I try to add it to a view controller:
class ViewController: UIViewController, KeyboardDismissing {}
it spits back the original error.
Can someone explain what I'm doing wrong and how I can compile this?
Note:
I've looked at this question but it is for Swift 2.2 not Swift 3 nor does the answer compile as soon as you create a view controller class that inherits from the protocol defined in the example.
I've also looked at this question but the answer uses NotificationCenter which is not what I'm after.
If there are any other seemingly duplicate questions, please let me know.

Matt's answer is correct. However, I would just add that, if you are dealing with #selector to use from a NotificationCenter notification, you could try to avoid #selector by using the closure version.
Example:
Instead of writing:
extension KeyboardHandler where Self: UIViewController {
func startObservingKeyboardChanges() {
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow(_:)),
// !!!!!
// compile error: cannot be included in a Swift protocol
name: .UIKeyboardWillShow,
object: nil
)
}
func keyboardWillShow(_ notification: Notification) {
// do stuff
}
}
you could write:
extension KeyboardHandler where Self: UIViewController {
func startObservingKeyboardChanges() {
// NotificationCenter observers
NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}
}
func keyboardWillShow(_ notification: Notification) {
// do stuff
}
}

This is a Swift protocol extension. Swift protocol extensions are invisible to Objective-C, no matter what; it knows nothing of them. But #selector is about Objective-C seeing and calling your function. That is not going to happen because your on(tap:) function is defined only in the protocol extension. Thus the compiler rightly stops you.
This question is one of a large class of questions where people think they are going to be clever with protocol extensions in dealing with Cocoa by trying to inject Objective-C-callable functionality (selector, delegate method, whatever) into a class via a protocol extension. It's an appealing notion but it's just not going to work.

As Matt said, you can't implement #objc methods in a protocol. Frédéric's answer covers Notifications, but what can you do about standard Selectors?
Let's say you have a protocol & extension, like so
protocol KeyboardHandler {
func setupToolbar()
}
extension KeyboardHandler {
func setupToolbar() {
let toolbar = UIToolbar()
let doneButton = UIBarButtonItem(title: "Done",
style: .done,
target: self,
action: #selector(self.donePressed))
}
#objc func donePressed() {
self.endEditing(true)
}
}
This will generate an error, as we know. What we can do, is take advantage of callbacks.
protocol KeyboardHandler {
func setupToolbar(callback: (_ doneButton: UIBarButtonItem) -> Void))
}
extension KeyboardHandler {
func setupToolbar(callback: (_ doneButton: UIBarButtonItem) -> Void)) {
let toolbar = UIToolbar()
let doneButton = UIBarButtonItem(title: "Done",
style: .done,
target: self,
action: nil
callback(doneButton)
}
}
Then, add an extension for the class you want to implement your protocol
extension ViewController: KeyboardHandler {
func addToolbar(textField: UITextField) {
addToolbar(textField: textField) { doneButton in
doneButton.action = #selector(self.donePressed)
}
}
#objc func donePressed() {
self.view.endEditing(true)
}
}
Instead of setting the action on creation, set it just after creation in the callback.
This way, you still get your desired functionality and can call the function in your class (ex. ViewController) without even seeing the callbacks!

I have made another attempt, from another point of view. I use in many of my developments, a protocol to handle the style of UINavigationBar in a global way, from each of the UIViewController contained in it.
One of the biggest problems of doing this is the standard behavior to return to the previous UIViewController (pop) and dismiss a UIViewController shown in a modal way. Let's look at some code:
public protocol NavigationControllerCustomizable {
}
extension NavigationControllerCustomizable where Self: UIViewController {
public func setCustomBackButton(on navigationItem: UINavigationItem) {
let backButton = UIButton()
backButton.setImage(UIImage(named: "navigationBackIcon"), for: .normal)
backButton.tintColor = navigationController?.navigationBar.tintColor
backButton.addTarget(self, action: #selector(defaultPop), for: .touchUpInside)
let barButton = UIBarButtonItem(customView: backButton)
navigationItem.leftBarButtonItem = barButton
}
}
This is a very simplified (and slightly modified) version of the original protocol, although it will be worth explaining the example.
As you can see, a #selector is being set within a protocol extension. As we know, protocol extensions are not exposed to Objective-C and therefore this will generate an error.
My solution is to wrap the methods that handle the standard behaviors of all my UIViewController (pop and dismiss) in another protocol and extend UIViewController to it. Viewing this in code:
public protocol NavigationControllerDefaultNavigable {
func defaultDismiss()
func defaultPop()
}
extension UIViewController: NavigationControllerDefaultNavigable {
public func defaultDismiss() {
dismiss(animated: true, completion: nil)
}
public func defaultPop() {
navigationController?.popViewController(animated: true)
}
}
With this workaround, all UIViewController implementing the NavigationControllerCustomizable will immediately have the methods defined in NavigationControllerDefaultNavigable, with their default implementation, and therefore be accessible from Objective-C to create expressions of type #selector, without any type of error.
I hope this explanation can help someone.

Here's my idea: avoid mixing swift protocol & objc protocol.

#Frédéric Adda answer have the downside that you are responsible to unregister your observer, because it uses the block based way of adding an observer. In iOS 9 and later, the 'normal' way of adding an observer, will hold a weak reference to the observer and therefore the developer doesn't have to unregister the observer.
The following way will use the 'normal' way of adding an observer through protocol extensions. It uses a bridging class that will hold the selector.
Pro's:
You do not have the manually remove the observer
Typesafe way of using the NotificationCenter
Con's:
You have to call register manually. Do this once after self is fully initialized.
Code:
/// Not really the user info from the notification center, but this is what we want 99% of the cases anyway.
public typealias NotificationCenterUserInfo = [String: Any]
/// The generic object that will be used for sending and retrieving objects through the notification center.
public protocol NotificationCenterUserInfoMapper {
static func mapFrom(userInfo: NotificationCenterUserInfo) -> Self
func map() -> NotificationCenterUserInfo
}
/// The object that will be used to listen for notification center incoming posts.
public protocol NotificationCenterObserver: class {
/// The generic object for sending and retrieving objects through the notification center.
associatedtype T: NotificationCenterUserInfoMapper
/// For type safety, only one notification name is allowed.
/// Best way is to implement this as a let constant.
static var notificationName: Notification.Name { get }
/// The selector executor that will be used as a bridge for Objc - C compability.
var selectorExecutor: NotificationCenterSelectorExecutor! { get set }
/// Required implementing method when the notification did send a message.
func retrieved(observer: T)
}
public extension NotificationCenterObserver {
/// This has to be called exactly once. Best practise: right after 'self' is fully initialized.
func register() {
assert(selectorExecutor == nil, "You called twice the register method. This is illegal.")
selectorExecutor = NotificationCenterSelectorExecutor(execute: retrieved)
NotificationCenter.default.addObserver(selectorExecutor, selector: #selector(selectorExecutor.hit), name: Self.notificationName, object: nil)
}
/// Retrieved non type safe information from the notification center.
/// Making a type safe object from the user info.
func retrieved(userInfo: NotificationCenterUserInfo) {
retrieved(observer: T.mapFrom(userInfo: userInfo))
}
/// Post the observer to the notification center.
func post(observer: T) {
NotificationCenter.default.post(name: Self.notificationName, object: nil, userInfo: observer.map())
}
}
/// Bridge for using Objc - C methods inside a protocol extension.
public class NotificationCenterSelectorExecutor {
/// The method that will be called when the notification center did send a message.
private let execute: ((_ userInfo: NotificationCenterUserInfo) -> ())
public init(execute: #escaping ((_ userInfo: NotificationCenterUserInfo) -> ())) {
self.execute = execute
}
/// The notification did send a message. Forwarding to the protocol method again.
#objc fileprivate func hit(_ notification: Notification) {
execute(notification.userInfo! as! NotificationCenterUserInfo)
}
}
From my GitHub (you can't use the code through Cocoapods): https://github.com/Jasperav/JVGenericNotificationCenter

Here is a similar use-case, you can call a method through a selector without using #objc as in swift by using the dynamic keyword. By doing so, you are instructing the compiler to use dynamic dispatch implicitly.
import UIKit
protocol Refreshable: class {
dynamic func refreshTableData()
var tableView: UITableView! {get set}
}
extension Refreshable where Self: UIViewController {
func addRefreshControl() {
tableView.insertSubview(refreshControl, at: 0)
}
var refreshControl: UIRefreshControl {
get {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
if let control = _refreshControl[tmpAddress] as? UIRefreshControl {
return control
} else {
let control = UIRefreshControl()
control.addTarget(self, action: Selector(("refreshTableData")), for: .valueChanged)
_refreshControl[tmpAddress] = control
return control
}
}
}
}
fileprivate var _refreshControl = [String: AnyObject]()
class ViewController: UIViewController: Refreshable {
#IBOutlet weak var tableView: UITableView! {
didSet {
addRefreshControl()
}
}
func refreshTableData() {
// Perform some stuff
}
}

Related

swift: Listen for "struct variable"-change event?

I got a small problem :
How is it possible to listen for the change of a struct-instance variable declared in another ("uneditable!!") class?
I added some small code snippets to maybe clarify my thoughts.
instructions:
FixedClass is a uneditable class: I don't want to change / I'm not able to change any code of the "FixedClass"
EditableClass can be edited - I'm sure you will get it looking at the code (^_^)/
code:
let fixedClass: FixedClass = FixedClass()
class FixedClass {
struct MyObject {
var abc = 0
}
var instance = MyObject()
public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil, repeats: true) }
#objc func updateVar() {
instance.abc+=1
}
func getVar() -> Int {
return instance.abc
}
}
let editableClass: EditableClass = EditableClass()
class EditableClass {
public init() { }
func listenForChange() {
// listen for change event of FixedClass.getVar()
print("Variable: \(fixedClass.getVar())")
}
}
Calling with: editableClass.listenForChange()
To sum that up I'd like to listen for the change of the FixedClass.getVar() result - preferably avoid using loops or timers. However the most important thing is to get it working at least.
Any help would be very appreciated, thanks!
This is going to depend totally on how the 'real' FixedClass is defined. I.E. is it a subclass of NSObject, is it an ObjectiveC class, how the property you want to observe is defined.
As far as your actual example is concerned you could do it by subclassing like this:
var newFixedClass: NewFixedClass = NewFixedClass()
var editableClass: EditableClass = EditableClass()
protocol NewFixedClassProtocol: class {
func changed(newFixedClass: NewFixedClass)
}
class NewFixedClass: FixedClass {
public weak var delegate: NewFixedClassProtocol?
override var instance: FixedClass.MyObject {
didSet {
self.delegate?.changed(newFixedClass: self)
}
}
}
class EditableClass: NewFixedClassProtocol {
public init() {
newFixedClass.delegate = self
}
func changed(newFixedClass: NewFixedClass) {
print ("Value = \(newFixedClass.instance.abc)")
}
}
So you basically create a protocol which the class doing the observing supports, create a subclass of the FixedClass which has a delegate of the protocol type and overrides the property of the FixedClass you want to observe with a didSet observer which then calls the delegate method. At some point you have to assign the class observing as the delegate of the sub class (I did it in the init method as a test).
So doing that I can observe when the structure changes but I haven't touched the FixedClass.
Note however that this method relies heavily on knowing about the original FixedClass so may not work for your 'real world' case.
(Also as an aside I couldn't get it to work with the globally defined instances of the classes and had to set them inside my initial view controller but that could be to do with how I was testing and doesn't alter the method involved)
A couple of things:
If the original class was Objective-C or otherwise participated in KVO (e.g. Swift dynamic properties of NSObject subclass, etc.) then you could observe changes. But but that's a fairly narrow use case. But that's a general pattern for making one's properties observable by other objects. For more information, see the Key-Value Observing Programming Guide.
If you can’t edit the class, in some narrow cases you could theoretically subclass it and add whatever observation system you want. That obviously only works if you’re manually instantiating FixedClass and it is contingent upon how FixedClass was implemented, but in some narrow cases, you can achieve what you need via subclassing.
You asked:
Would you be so kind an share some code snippets with us?
Sure, consider your FixedClass:
class FixedClass {
struct MyObject {
var abc = 0
}
var instance = MyObject()
public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil, repeats: true) }
#objc func updateVar() {
instance.abc+=1
}
func getVar() -> Int {
return instance.abc
}
}
You could then define a subclass:
class FixedClassSubclass: FixedClass {
static let changeNotification = NSNotification.Name(rawValue: Bundle.main.bundleIdentifier! + ".FixedClassSubclassNotification")
override func updateVar() {
super.updateVar()
NotificationCenter.default.post(name: FixedClassSubclass.changeNotification, object: self)
}
}
Then you could do:
let fixed = FixedClassSubclass()
and
NotificationCenter.default.addObserver(forName: FixedClassSubclass.changeNotification, object: nil, queue: nil) { _ in
print("changed")
}
You can use whatever notification process you want. NotificationCenter. KVN. Delegate-protocol pattern. Whatever. The details of this will vary entirely based upon the details of FixedClass and you have given us a contrived example that is unlikely to be extensible in many situations.
I must confess to some general misgivings to the idea of trying to hook into the internal implementation details of a non-editable class. We generally strive for loosely coupled objects that only rely on published, supported interfaces. This endeavor violates both of those objectives. But I'll assume you have some good reason to do what you're attempting to do.
One way to do this would be to use NotificationCenter to broadcast the change, and have your EditableClass listen for that change and react to it. Your implementation could look something like this:
class FixedClass { //Class names should start with capital letters
struct MyObject { //Struct names should also start with capital letters
var abc = 0
}
var instance = myObject()
public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil, repeats: true) }
#objc func updateVar() {
instance.abc+=1
//Broadcast the change, and pass this FixedClass instance
NotificationCenter.default.post(name: Notification.Name("fixedClassChanged"), object: self)
}
func getVar() -> Int {
return instance.abc
}
}
Then you could react to this broadcast in your EditableClass like so:
class EditableClass {
public init() { }
func listenForChange() {
//Observe same notification being broadcast by the other class
NotificationCenter.default.addObserver(self, selector: #selector(processChange(_:)), name: Notification.Name("fixedClassChanged"), object: nil)
}
#objc func processChange(_ sender: Notification) {
//When the notification comes in, check to see if the object passed in was a FixedClass, and if so process whatever needs to be processed
if let fixed = sender.object as? FixedClass {
print("Class changed to \(fixed.getVar())")
}
}
}

How to call an optional function using Selector and NotificationCenter

Language: Swift 3
IDE: XCode 8.3.2 (8E2002)
I have a protocol with an optional function foo
#objc protocol SomeProtocol {
#objc optional func foo(_ notification: Notification)
}
extension SomeProtocol {
func listenToFoo() {
NotificationCenter.default.addObserver(self, selector: #selector(self.foo(_:)), name: NSNotification.Name(rawValue: "UltimateNotificationKeyLOL"), object: nil)
}
}
If I extend this code to a class, say a UIViewController.
class CrashingViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.listenToFoo()
}
}
extension CrashingViewController: SomeProtocol { }
Now here comes the problem, since foo is an optional function, if any one sends a Notification with the key NSNotification.Name(rawValue: "UltimateNotificationKeyLOL") the application will crash because I haven't implemented foo yet. So in this case, the above code will cause a crash.
However if I do this
class GodzillaViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.listenToFoo()
}
}
extension GodzillaViewController: SomeProtocol {
func foo(_ notification: Notification) {
print("lol")
}
}
No crash is created since foo(_:) is not optional anymore.
Also: This code isn't possible #selector(self.foo?(_:))
Question: Is it possible to have a selector call an optional function without crashing the application?
If I where you I would make a full-swift protocol like so:
// Protocol declaration
protocol SomeProtocol {
func foo(_ notification: Notification)
}
// Provide default implementation for optional methods of SomeProtocol
extension SomeProtocol {
func foo(_ notification: Notification) {}
}
// Extend SomeProtocol with additional methods
extension SomeProtocol {
func listenToFoo() {
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "UltimateNotificationKeyLOL"), object: nil, queue: nil) { (notification) in
self.foo(notification)
}
}
}
As you can see, doing it like this has multiple benefits:
You have a Swift only code (no #objc)
By adding a default implementation of foo, you made the function optional.
Your notification can still call foo without crashing as it will go to the default implementation if necessary
You can even add some code to the default method if you still want to do something!
UPDATE
You can see in the listenToFoo() function that I used a different addObserver function that uses a closure instead, the reason being that #selector still requires the function to be exposed to #objc and the closure doesn't:
func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: #escaping (Notification) -> Void) -> NSObjectProtocol

UIApplicationSignificantTimeChange notification is not triggered

I want to use the UIApplicationSignificantTimeChange to check when the day has changed and I encapsulated in my own class so I can easy use it in more view controllers:
public final class DayChangedObserver {
private var token: NSObjectProtocol!
public init?(handler: #escaping () -> ()) {
token = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationSignificantTimeChange, object: self, queue: nil) { _ in
handler()
}
}
deinit {
NotificationCenter.default.removeObserver(token)
}
}
And I call this code from my view controller:
override func viewDidLoad() {
super.viewDidLoad()
_ = DayChangedObserver() {
print("Day has changed")
}
}
I am testing this on my iPhone and I manually change the time. But it seems that it doesn't work using my class.
Is it something wrong with my implementation ? Because it was working when I was using this event in the past (without my own class implementation).
EDIT1:
I seems that deinit is called immediately after, so I am using an instance variable to keep a strong reference and now it's not deinit anymore, but still doesn't work.
object: self change to object: nil,try it.

How to use #objc protocol with optional and extensions at the same time?

This code does not compile and might sound stupid as it is, but i'll explain why it's so important!
#objc protocol p {
optional func f1()
func f2()
}
extension p {
func f1() { }
func f2() { }
}
class foo: p {
}
Compiler says Type c does not conform to protocol 'p' and that's maybe because you can not use #objc optional and extensions at the same time (and does not make sence in this scenario either). But consider the following example:
I want to set a selector on a non-optional method defined in protocol in my extension (main reason i used #objc):
func f1() { } -> func f1() { ... #selector(Self.f2) ... }
And i also want my f2() function to have default behaviour. If i mark f2() as optional, it can not be used in #selector because compiler does not know if this method actually exists in the case of need. Sure there're lots of nasty workarounds like global methods, sending Selectors to methods as input and etc, but is there a clean way to achieve it?
This is the practical issue
#objc
protocol Refreshable {
weak var refreshControl: UIRefreshControl? { get set }
optional func setupRefreshControl()
func refresh()
}
#objc
protocol ContentLoader {
func load(reset: Bool)
}
extension Refreshable where Self: ContentLoader {
func refresh() {
delay(0.75) { [weak self] in
self?.load(true)
}
}
}
extension Refreshable where Self: UICollectionViewController {
func setupRefreshControl() {
let newRefreshControl = UIRefreshControl()
newRefreshControl.tintColor = UIColor.grayColor()
newRefreshControl.addTarget(self, action: #selector(Self.refresh), forControlEvents: .ValueChanged)
collectionView?.addSubview(newRefreshControl)
refreshControl = newRefreshControl
}
}
Now if a ViewController implements Refreshable and ContentLoader, it does not find the default refresh function, but it does find setupRefreshControl. So i figured let's mark refresh as optional too, but by doing that, you can not send it to selector any more.
I even tried this:
func refresh() -> optional func refresh()
and
let str = "refresh"
let sel = Selector(str)
It silents the compiler yes, but does not work either... rises unrecognized selector sent to instance....
I think this is not possible in swift (because of the way it bridges to #objc protocols). But this is a work around(using Obj-c associated objects) to solve the unrecognized selector sent to instance... problem.
fileprivate class AssociatedObject: NSObject {
var closure: (() -> ())? = nil
func trigger() {
closure?()
}
}
// Keys should be global variables, do not use, static variables inside classes or structs.
private var associatedObjectKey = "storedObject"
protocol CustomProtocol: class {
func setup()
}
extension CustomProtocol where Self: NSObject {
fileprivate var associatedObject: AssociatedObject? {
get {
return objc_getAssociatedObject(self, &associatedObjectKey) as? AssociatedObject
}
set {
objc_setAssociatedObject(self, &associatedObjectKey, newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
func setup() {
let object = AssociatedObject()
object.closure = { [weak self] in // Do not forget to use weak in order to avoid retain-cycle
self?.functionToCallIndirectlyWithSelector()
}
let selector = #selector(object.trigger)
// Uncomment next line to test it's functionality
object.perform(selector)
// Here, you must add selector to the target which needs to call the selector, for example:
// refreshControl.addTarget(object, action: selector, forControlEvents: .valueChanged)
self.associatedObject = object
}
func functionToCallIndirectlyWithSelector() {
print("Function got called indirectly.")
}
}
class CustomClass: NSObject, CustomProtocol {}
let instance = CustomClass()
instance.setup()
I added Self: NSObject constraint to be able to test it's functionality in playground, I'm not sure if it's necessary or not.

Swift class add "#objc" for why

Here's a link to a Swift tutorial.
I read the protocol section,i know if protocol is marked with the #objc:
#objc protocol CounterDataSource {
optional func incrementForCount(count: Int) -> Int
optional var fixedIncrement: Int { get }
}
this mean this protocol in order to specify optional requirements and can be adopted only by classes
but tutorial didn't say why the class need to marked with the #objc too??
#objc class Counter {
var count = 0
var dataSource: CounterDataSource?
func increment() {
if let amount = dataSource?.incrementForCount?(count) {
count += amount
} else if let amount = dataSource?.fixedIncrement? {
count += amount
}
}
}
if i remove #objc from class , compiler didn't show error message too
so what different between add #objc to class or not?
Deprecation
It is no longer possible in latest Swift releases to use #objc w/o NSObject so this answer is deprecated.
Original
#objc is prefixed to classes to allow them to be used in ObjC. If you're dealing purely in Swift, it is unnecessary.
Also, if your class inherits from an ObjC class, the prefix is unnecessary.
For example #selector is owned by Obj-c,
In swift, we'll use #selector in .addTarget or in .target of an object. There we should prefix #objc for targeting method.
Example:
#objc func dummy(_ sender: UIButton) {
print("xxx")
}
above method will be using in a UIButton's target like
dummyButton.addTarget(self, action: #selector(self. dummy(_:)), for: .touchUpInside)
this is why we are using #objc as prefix in swift.

Resources