Xcode 7.3/Swift 2: "No Method Declared with Objective-C Selector" Warning

Xcode 7.3 / Swift 2: No method declared with Objective-C selector warning

Since Swift 2.2 / Xcode 7.3 there is a new way to use a selector:
Selector("funcName") was changed to #selector(ClassName.funcName)

Have a look at https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md ,

tl;dr;

Replace Selector("Start") with #selector(YOUR_CLASS.Start)

where YOUR_CLASS = class of target in given context.

If you don't want to do it manually, Xcode provides easy fix itself by default, when you have the following situation, tap on the Yellow triangles ( sometimes required to tap/click multiple times ),

Sample Image

it will give you suggestion:
Sample Image

And if you select that suggestion, it will automatically update the selector:
Sample Image

No method declared with Objective-C selector ('nextPage')

You need to put nextPage out of viewDidLoad() and then #selector(VC1.nextPage)

func nextPage(sender:UISwipeGestureRecognizer) {

switch sender.direction {
case UISwipeGestureRecognizerDirection.Left:

print("SWIPED LEFT", terminator: "")

self.performSegueWithIdentifier("seg1", sender: nil)

default:

break

}
}

override func viewDidLoad() {

super.viewDidLoad()

let leftSwipe = UISwipeGestureRecognizer (target: self, action: #selector(VC1.nextPage))

let rightSwipe = UISwipeGestureRecognizer (target: self, action: #selector(VC1.nextPage))
}

Xcode 7 swift, ''no method declared with objective-c selector (function) warning

I'm guessing that your problem is with the Selector part.

In Swift 2.2 the selector syntax was changed so you now get a compile time check for your selectors. You can read more about that here.

To answer your question, this syntax:

button.addTarget(self, action: #selector(function(_:)), forControlEvents: .TouchUpInside)

should make you and - more importantly in this case (sorry :)) - the compiler happy.

Update (after looking at the code you provided)

You need to move the pressed function outside of your viewDidLoad function so that it is a separate function.

So your code ends up looking like this:

override func viewDidLoad() {
super.viewDidLoad()

let button = UIButton(frame: CGRectMake(100, 80, 30, 30))
button.backgroundColor = UIColor.redColor()
button.addTarget(self, action: #selector(pressed(_:)), forControlEvents: .TouchUpInside)
self.view.addSubview(button)
}

func pressed(sender: UIButton) { //As ozgur says, ditch the !, it is not needed here :)
print("button pressed")
}

And that seems to work, I can see button pressed in my console now at least.

Hope that helps you.

Referencing the Objective-C selector of a method

For solving of your issue at first read new documentation about Selectors in Swift2.2.

Example:
Use #selector(CLASS.sync) instead of Selector("sync"). Where CLASS it is actual class that contains this method.

And this was done due to this reason:

The use of string literals for selector names is extremely
error-prone: there is no checking that the string is even a
well-formed selector, much less that it refers to any known method, or
a method of the intended class. Moreover, with the effort to perform
automatic renaming of Objective-C APIs, the link between Swift name
and Objective-C selector is non-obvious. By providing explicit "create
a selector" syntax based on the Swift name of a method, we eliminate
the need for developers to reason about the actual Objective-C
selectors being used.

Method with Objective-C selector conflicts - 'with' at the end

#str will be translated to withStr in objc. You can use the @objc(someOtherSelectorName:) annotation to specify a different selector name for objc and avoid the conflict.

Why is there no Swift equivalent for adding an action to a view?

The target/selector mechanism is how UIControl (and similar classes) was written long ago, in Objective-C, before even Objective-C blocks were a thing.

Your question is just as valid for Objective-C. Why doesn't UIControl (and similar) provide a block based API instead of the dated target/selector pattern?

So it's not a matter of updating Swift. It's a question of adding a block/closure based API to relevant classes that use the target/selector pattern.

If you do a little searching on GitHub you will find a closure based Swift API that actually does what you want. Of course, its implementation is to use the old target/selector APIs.

Error declaring method with Objective-C selector

Selectors have changed with Xcode 7.3. You need to explicitly declare the selector that belongs to your class:

class MyClass {
func someFunc() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyClass.itemDroppedOnCharacter(_:)), name: "onTargetDropped", object: nil)
}

@objc func itemDroppedOnCharacter(notif: AnyObject) {
print("Item Dropped On Character")
}
}

You can also have MyClass inherit from NSObject if you don't want to add @objc to expose the selector to Objective-C:

class MyClass: NSObject {
func someFunc() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyClass.itemDroppedOnCharacter(_:)), name: "onTargetDropped", object: nil)
}

func itemDroppedOnCharacter(notif: AnyObject) {
print("Item Dropped On Character")
}
}


Related Topics



Leave a reply



Submit