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 ),
it will give you suggestion:
And if you select that suggestion, it will automatically update the selector:
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
Swift Setter Causing Exc_Bad_Access
Swift Date(Byadding:To:) Returns Nil for Trivial Calculation in Repl
Arkit - How to Export Obj from Iphone/iPad with Lidar
How to Specify That a Non-Generic Swift Type Should Comply to a Protocol
Identify Face of a Cube Hit on Touches Began in Swift - Scenekit
Change Color Searchbar Result Icon Swift
Use Resources in Unit Tests with Swift Package Manager
Stop a Dispatchqueue That Is Running on the Main Thread
Remove Default Padding from List in Swiftui
Array of Nested Type: Why Does the Compiler Complain
Swift. Could Not Build Objective-C Module 'Alamofire'
Why Do Enums Have Computed Properties But Not Stored Properties in Swift
Cannot Resolve Swift Packages After 15Th March 2022 in Xcode
Swift 2 iOS 9 Do Catch Try Crashing with Unexpected Nil Found