@selector() in Swift?
up vote
601
down vote
favorite
I'm trying to create an NSTimer
in Swift
but I'm having some trouble.
NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)
test()
is a function in the same class.
I get an error in the editor:
Could not find an overload for 'init' that accepts the supplied
arguments
When I change selector: test()
to selector: nil
the error disappears.
I've tried:
selector: test()
selector: test
selector: Selector(test())
But nothing works and I can't find a solution in the references.
swift selector nstimer
add a comment |
up vote
601
down vote
favorite
I'm trying to create an NSTimer
in Swift
but I'm having some trouble.
NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)
test()
is a function in the same class.
I get an error in the editor:
Could not find an overload for 'init' that accepts the supplied
arguments
When I change selector: test()
to selector: nil
the error disappears.
I've tried:
selector: test()
selector: test
selector: Selector(test())
But nothing works and I can't find a solution in the references.
swift selector nstimer
11
selector: test()
would calltest
and pass it's return value to theselector
argument.
– Michael Dorst
Jun 10 '14 at 4:47
add a comment |
up vote
601
down vote
favorite
up vote
601
down vote
favorite
I'm trying to create an NSTimer
in Swift
but I'm having some trouble.
NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)
test()
is a function in the same class.
I get an error in the editor:
Could not find an overload for 'init' that accepts the supplied
arguments
When I change selector: test()
to selector: nil
the error disappears.
I've tried:
selector: test()
selector: test
selector: Selector(test())
But nothing works and I can't find a solution in the references.
swift selector nstimer
I'm trying to create an NSTimer
in Swift
but I'm having some trouble.
NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)
test()
is a function in the same class.
I get an error in the editor:
Could not find an overload for 'init' that accepts the supplied
arguments
When I change selector: test()
to selector: nil
the error disappears.
I've tried:
selector: test()
selector: test
selector: Selector(test())
But nothing works and I can't find a solution in the references.
swift selector nstimer
swift selector nstimer
edited May 11 '16 at 9:06
Mihriban Minaz
2,64222648
2,64222648
asked Jun 3 '14 at 5:21
Arbitur
20.9k1967100
20.9k1967100
11
selector: test()
would calltest
and pass it's return value to theselector
argument.
– Michael Dorst
Jun 10 '14 at 4:47
add a comment |
11
selector: test()
would calltest
and pass it's return value to theselector
argument.
– Michael Dorst
Jun 10 '14 at 4:47
11
11
selector: test()
would call test
and pass it's return value to the selector
argument.– Michael Dorst
Jun 10 '14 at 4:47
selector: test()
would call test
and pass it's return value to the selector
argument.– Michael Dorst
Jun 10 '14 at 4:47
add a comment |
22 Answers
22
active
oldest
votes
up vote
880
down vote
accepted
Swift itself doesn't use selectors — several design patterns that in Objective-C make use of selectors work differently in Swift. (For example, use optional chaining on protocol types or is
/as
tests instead of respondsToSelector:
, and use closures wherever you can instead of performSelector:
for better type/memory safety.)
But there are still a number of important ObjC-based APIs that use selectors, including timers and the target/action pattern. Swift provides the Selector
type for working with these. (Swift automatically uses this in place of ObjC's SEL
type.)
In Swift 2.2 (Xcode 7.3) and later (including Swift 3 / Xcode 8 and Swift 4 / Xcode 9):
You can construct a Selector
from a Swift function type using the #selector
expression.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
The great thing about this approach? A function reference is checked by the Swift compiler, so you can use the #selector
expression only with class/method pairs that actually exist and are eligible for use as selectors (see "Selector availability" below). You're also free to make your function reference only as specific as you need, as per the Swift 2.2+ rules for function-type naming.
(This is actually an improvement over ObjC's @selector()
directive, because the compiler's -Wundeclared-selector
check verifies only that the named selector exists. The Swift function reference you pass to #selector
checks existence, membership in a class, and type signature.)
There are a couple of extra caveats for the function references you pass to the #selector
expression:
- Multiple functions with the same base name can be differentiated by their parameter labels using the aforementioned syntax for function references (e.g.
insertSubview(_:at:)
vsinsertSubview(_:aboveSubview:)
). But if a function has no parameters, the only way to disambiguate it is to use anas
cast with the function's type signature (e.g.foo as () -> ()
vsfoo(_:)
). - There's a special syntax for property getter/setter pairs in Swift 3.0+. For example, given a
var foo: Int
, you can use#selector(getter: MyClass.foo)
or#selector(setter: MyClass.foo)
.
General notes:
Cases where #selector
doesn't work, and naming: Sometimes you don't have a function reference to make a selector with (for example, with methods dynamically registered in the ObjC runtime). In that case, you can construct a Selector
from a string: e.g. Selector("dynamicMethod:")
— though you lose the compiler's validity checking. When you do that, you need to follow ObjC naming rules, including colons (:
) for each parameter.
Selector availability: The method referenced by the selector must be exposed to the ObjC runtime. In Swift 4, every method exposed to ObjC must have its declaration prefaced with the @objc
attribute. (In previous versions you got that attribute for free in some cases, but now you have to explicitly declare it.)
Remember that private
symbols aren't exposed to the runtime, too — your method needs to have at least internal
visibility.
Key paths: These are related to but not quite the same as selectors. There's a special syntax for these in Swift 3, too: e.g. chris.valueForKeyPath(#keyPath(Person.friends.firstName))
. See SE-0062 for details. And even more KeyPath
stuff in Swift 4, so make sure you're using the right KeyPath-based API instead of selectors if appropriate.
You can read more about selectors under Interacting with Objective-C APIs in Using Swift with Cocoa and Objective-C.
Note: Before Swift 2.2, Selector
conformed to StringLiteralConvertible
, so you might find old code where bare strings are passed to APIs that take selectors. You'll want to run "Convert to Current Swift Syntax" in Xcode to get those using #selector
.
7
Putting a string with the function name worked, NSSelectorFromString() works also.
– Arbitur
Jun 3 '14 at 5:36
5
I'd like to mention that while "Interacting with Objective-C APIs" is on the website, it is NOT in 'The Swift Programming Language' book.
– user1040049
Jun 3 '14 at 20:32
9
This should probably mention that the selector needs a ":" at the end if it takes an argument. (E.g. test() -> "test" & test(this:String) -> "test:")
– Daniel Schlaug
Jul 6 '14 at 14:06
2
It should also be pointed out that the Cocoa frameworks expect an Objective-C style method name. If your method takes an argument you will need a ':' if it takes 2 arguments,size:andShape:
, if the first argument is named you may need aWith
, i.e.initWithData:
forfunc init(Data data: NSData)
– JMFR
Oct 28 '14 at 18:13
5
Is there anyway to add validation around passing the "selector" as a string? IE compiler warn us when we misspell, etc.
– yo.ian.g
Dec 13 '14 at 18:59
|
show 11 more comments
up vote
78
down vote
Here's a quick example on how to use the Selector
class on Swift:
override func viewDidLoad() {
super.viewDidLoad()
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
self.navigationItem.rightBarButtonItem = rightButton
}
func method() {
// Something cool here
}
Note that if the method passed as a string doesn't work, it will fail at runtime, not compile time, and crash your app. Be careful
12
which is horrible... is there a "NSStringFromSelector" type of thing ?
– Lena Bru
Jun 4 '14 at 22:47
11
can't believe they designed for unchecked selectors since objc had this
– malhal
Jun 6 '14 at 15:11
4
@malcomhall:@selector
is handy, but it's not enforced as formally as you might think. "Undeclared selector" is merely a warning from the compiler, because new selectors can always be introduced at run time. Verifiable/refactorable selector references in Swift would be a good feature request to make, though.
– rickster
Aug 8 '14 at 22:15
2
This answer is helpful but the answer below with @objc is more appropriate.
– cynistersix
Nov 12 '14 at 22:55
When you are passing the selector string in as a variable or parameter, you'll need to let the compiler know its a selector using the Selector() function. thanks
– levous
Aug 4 '15 at 11:53
|
show 1 more comment
up vote
44
down vote
Also, if your (Swift) class does not descend from an Objective-C class, then you must have a colon at the end of the target method name string and you must use the @objc property with your target method e.g.
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
@objc func method() {
// Something cool here
}
otherwise you will get a "Unrecognised Selector" error at runtime.
3
1. selectors w/ a colon must take an argument 2. according to Apple docs timer's actions should take NSTimer argument 3.Selector
keyword is not mandatory. So in this case signature must be@objc func method(timer: NSTimer) {/*code*/}
– Yevhen Dubinin
Dec 1 '14 at 0:31
@objc
worked for me. I didn't need to includetimer: NSTimer
in my method signature for it to be called.
– Mike Taverne
Feb 5 '15 at 19:03
add a comment |
up vote
23
down vote
For future readers, I found that I experienced a problem and was getting an unrecognised selector sent to instance
error that was caused by marking the target func
as private.
The func
MUST be publicly visible to be called by an object with a reference to a selector.
13
it doesn't have to be public you can still keep the method private but addobjc
before it's declaration. Ex:@objc private func foo() { ...
then you can use"foo"
as a selector as much you like
– apouche
Oct 28 '15 at 10:40
dynamic func foo() { ... } also works
– NAlexN
Jan 30 '17 at 14:15
It can also beinternal
, thus not specifying any access modifier. I often use this pattern://MARK: - Selector Methodsn extension MyController {n func buttonPressed(_ button: UIButton) {
– Sajjon
Apr 6 '17 at 8:27
add a comment |
up vote
23
down vote
Swift 2.2+ and Swift 3 Update
Use the new #selector
expression, which eliminates the need to use string literals making usage less error-prone. For reference:
Selector("keyboardDidHide:")
becomes
#selector(keyboardDidHide(_:))
See also: Swift Evolution Proposal
Note (Swift 4.0):
If using #selector
you would need to mark the function as @objc
Example:
@objc func something(_ sender: UIButton)
add a comment |
up vote
19
down vote
Just in case somebody else have the same problem I had with NSTimer where none of the other answers fixed the issue, is really important to mention that, if you are using a class that do not inherits from NSObject either directly or deep in the hierarchy(e.g. manually created swift files), none of the other answers will work even when is specified as follows:
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
Without changing anything else other than just making the class inherit from NSObject I stopped getting the "Unrecognized selector" Error and got my logic working as expected.
The issue with this alternative is that you can´t change a class (let´s say ViewController) to inherit from NSObject, given that you need the ViewController class implemented stuff (e.g. viewDidLoad()). Any idea how to call a Swift function within a ViewController using NSTimer?... e
– eharo2
Jul 22 '14 at 18:47
1
UIViewController already inherits from NSObject, most classes exposed by the SDK do, this example is for your own created classes that require NSTimer functionality...
– Martin Cazares
Jul 22 '14 at 19:10
add a comment |
up vote
18
down vote
Swift 4.0
you create the Selector like below.
1.add the event to a button like:
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
and the function will be like below:
@objc func clickedButton(sender: AnyObject) {
}
3
You forgot to put@objc
beforefunc
which is required in Swift 4.
– Vahid Amiri
Jan 27 at 15:49
add a comment |
up vote
14
down vote
If you want to pass a parameter to the function from the NSTimer then here is your solution:
var somethingToPass = "It worked"
let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)
func tester(timer: NSTimer)
{
let theStringToPrint = timer.userInfo as String
println(theStringToPrint)
}
Include the colon in the selector text (tester:), and your parameter(s) go in userInfo.
Your function should take NSTimer as a parameter. Then just extract userInfo to get the parameter that passed.
3
I was using NSTimer(0.01, target: self, ...) which did NOT work, whereas using NSTimer.scheduledTimerWithTimeInterval(0.01, ..) DID work!? Strange but thanks @Scooter for you answer!
– iOS-Coder
Jul 5 '15 at 12:19
1
@iOS-Coder just creating a timer with the initialiser does not add it to a runloop, whereasscheduledTimerWith...
automatically adds it to the current runloop - so there is no strange behaviour here at all ;)
– David Ganster
Oct 5 '15 at 21:30
1
@David thanks for your suggestion. I guess my misunderstanding should belong in either STFW or RTFA (Read The F...ing API) category?
– iOS-Coder
Oct 6 '15 at 22:27
1
Don't worry about it, no one can be expected to read the documentation about every single method in every API ;)
– David Ganster
Oct 7 '15 at 9:14
add a comment |
up vote
10
down vote
Selectors are an internal representation of a method name in Objective-C. In Objective-C "@selector(methodName)" would convert a source-code method into a data type of SEL. Since you can't use the @selector syntax in Swift (rickster is on point there), you have to manually specify the method name as a String object directly, or by passing a String object to the Selector type. Here is an example:
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:"logout"
)
or
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:Selector("logout")
)
add a comment |
up vote
8
down vote
Swift 4.1
With sample of tap gesture
let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))
// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))
@objc func dismiss(completion: (() -> Void)?) {
self.dismiss(animated: true, completion: completion)
}
See Apple's document for more details about: Selector Expression
Please stop doing this. It helps no one. How is this any different from Swift 3.1? And why did you think it necessary to add another answer to this when it already has about 20 answers?
– Fogmeister
Jun 9 '17 at 13:58
calling selector is different in swift 4. Try these answers in swift 4 and see. None these will work without editing. Please do not mark any statement as spam without ensuring its impotance
– Krunal
Jun 9 '17 at 13:59
So is there any reason you couldn't edit the existing, accepted answer? It would make it actually useful rather than adding on the end of a long list of answers. The "Edit" button is there for a reason.
– Fogmeister
Jun 9 '17 at 14:00
Also, which part of this is different from Swift 3?
– Fogmeister
Jun 9 '17 at 14:02
2
You have to add the objc tag to any selectors for Swift 4. This is the correct answer. And your not supposed to edit other people's answers to change their meaning. @Krunal is totally right.
– Unome
Sep 26 '17 at 15:33
|
show 1 more comment
up vote
6
down vote
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)
func tappedButton() {
print("tapped")
}
func tappedButton2(sender: UIButton) {
print("tapped 2")
}
// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton) {
// tapped
}
button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton, _ event: UIEvent) {
// tapped
}
it would have been nicer and more educative if u had an example taking two or three arguments for Swift3 or Swift4 too. Thanks.
– nyxee
Jul 19 '17 at 22:24
add a comment |
up vote
5
down vote
Create Refresh control using Selector method.
var refreshCntrl : UIRefreshControl!
refreshCntrl = UIRefreshControl()
refreshCntrl.tintColor = UIColor.whiteColor()
refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
atableView.addSubview(refreshCntrl)
//Refresh Control Method
func refreshControlValueChanged(){
atableView.reloadData()
refreshCntrl.endRefreshing()
}
add a comment |
up vote
5
down vote
Since Swift 3.0 is published, it is even a little bit more subtle to declare a targetAction appropriate
class MyCustomView : UIView {
func addTapGestureRecognizer() {
// the "_" is important
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// since Swift 3.0 this "_" in the method implementation is very important to
// let the selector understand the targetAction
func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {
if tapGesture.state == .ended {
print("TapGesture detected")
}
}
}
add a comment |
up vote
4
down vote
When using performSelector()
/addtarget()/NStimer.scheduledTimerWithInterval()
methods your method (matching the selector) should be marked as
@objc
For Swift 2.0:
{
//...
self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
//...
//...
btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
//...
//...
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
//...
}
@objc private func performMethod() {
…
}
@objc private func buttonPressed(sender:UIButton){
….
}
@objc private func timerMethod () {
….
}
For Swift 2.2,
you need to write '#selector()' instead of string and selector name so the possibilities of spelling error and crash due to that will not be there anymore. Below is example
self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
add a comment |
up vote
3
down vote
you create the Selector like below.
1.
UIBarButtonItem(
title: "Some Title",
style: UIBarButtonItemStyle.Done,
target: self,
action: "flatButtonPressed"
)
2.
flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
Take note that the @selector syntax is gone and replaced with a simple String naming the method to call. There’s one area where we can all agree the verbosity got in the way. Of course, if we declared that there is a target method called flatButtonPressed: we better write one:
func flatButtonPressed(sender: AnyObject) {
NSLog("flatButtonPressed")
}
set the timer:
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: Selector("flatButtonPressed"),
userInfo: userInfo,
repeats: true)
let mainLoop = NSRunLoop.mainRunLoop() //1
mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal
In order to be complete, here’s the flatButtonPressed
func flatButtonPressed(timer: NSTimer) {
}
Do you have any source for "Take note that the @selector syntax is gone"?
– winklerrr
Mar 21 at 15:58
add a comment |
up vote
3
down vote
I found many of these answers to be helpful but it wasn't clear how to do this with something that wasn't a button. I was adding a gesture recognizer to a UILabel in swift and struggled so here's what I found worked for me after reading everything above:
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: "labelTapped:")
Where the "Selector" was declared as:
func labelTapped(sender: UILabel) { }
Note that it is public and that I am not using the Selector() syntax but it is possible to do this as well.
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: Selector("labelTapped:"))
add a comment |
up vote
3
down vote
Using #selector will check your code at compile time to make sure the method you want to call actually exists. Even better, if the method doesn’t exist, you’ll get a compile error: Xcode will refuse to build your app, thus banishing to oblivion another possible source of bugs.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(addNewFireflyRefernce))
}
func addNewFireflyReference() {
gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
}
add a comment |
up vote
2
down vote
It may be useful to note where you setup the control that triggers the action matters.
For example, I have found that when setting up a UIBarButtonItem, I had to create the button within viewDidLoad or else I would get an unrecognized selector exception.
override func viewDidLoad() {
super.viewDidLoad()
// add button
let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
self.navigationItem.rightBarButtonItem = addButton
}
func addAction(send: AnyObject?) {
NSLog("addAction")
}
add a comment |
up vote
1
down vote
Change as a simple string naming in the method calling for selector syntax
var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)
After that, type func test().
add a comment |
up vote
0
down vote
For swift 3
let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)
Function Declaration In Same Class
func test()
{
// my function
}
add a comment |
up vote
0
down vote
For Swift 3
//Sample code to create timer
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.
func updateTimer(){
//Implemetation
}
repeats:- true/false specifies that timer should call again n again.
add a comment |
up vote
0
down vote
Selector in Swift 4:
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
add a comment |
protected by Community♦ Mar 1 '15 at 21:02
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
22 Answers
22
active
oldest
votes
22 Answers
22
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
880
down vote
accepted
Swift itself doesn't use selectors — several design patterns that in Objective-C make use of selectors work differently in Swift. (For example, use optional chaining on protocol types or is
/as
tests instead of respondsToSelector:
, and use closures wherever you can instead of performSelector:
for better type/memory safety.)
But there are still a number of important ObjC-based APIs that use selectors, including timers and the target/action pattern. Swift provides the Selector
type for working with these. (Swift automatically uses this in place of ObjC's SEL
type.)
In Swift 2.2 (Xcode 7.3) and later (including Swift 3 / Xcode 8 and Swift 4 / Xcode 9):
You can construct a Selector
from a Swift function type using the #selector
expression.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
The great thing about this approach? A function reference is checked by the Swift compiler, so you can use the #selector
expression only with class/method pairs that actually exist and are eligible for use as selectors (see "Selector availability" below). You're also free to make your function reference only as specific as you need, as per the Swift 2.2+ rules for function-type naming.
(This is actually an improvement over ObjC's @selector()
directive, because the compiler's -Wundeclared-selector
check verifies only that the named selector exists. The Swift function reference you pass to #selector
checks existence, membership in a class, and type signature.)
There are a couple of extra caveats for the function references you pass to the #selector
expression:
- Multiple functions with the same base name can be differentiated by their parameter labels using the aforementioned syntax for function references (e.g.
insertSubview(_:at:)
vsinsertSubview(_:aboveSubview:)
). But if a function has no parameters, the only way to disambiguate it is to use anas
cast with the function's type signature (e.g.foo as () -> ()
vsfoo(_:)
). - There's a special syntax for property getter/setter pairs in Swift 3.0+. For example, given a
var foo: Int
, you can use#selector(getter: MyClass.foo)
or#selector(setter: MyClass.foo)
.
General notes:
Cases where #selector
doesn't work, and naming: Sometimes you don't have a function reference to make a selector with (for example, with methods dynamically registered in the ObjC runtime). In that case, you can construct a Selector
from a string: e.g. Selector("dynamicMethod:")
— though you lose the compiler's validity checking. When you do that, you need to follow ObjC naming rules, including colons (:
) for each parameter.
Selector availability: The method referenced by the selector must be exposed to the ObjC runtime. In Swift 4, every method exposed to ObjC must have its declaration prefaced with the @objc
attribute. (In previous versions you got that attribute for free in some cases, but now you have to explicitly declare it.)
Remember that private
symbols aren't exposed to the runtime, too — your method needs to have at least internal
visibility.
Key paths: These are related to but not quite the same as selectors. There's a special syntax for these in Swift 3, too: e.g. chris.valueForKeyPath(#keyPath(Person.friends.firstName))
. See SE-0062 for details. And even more KeyPath
stuff in Swift 4, so make sure you're using the right KeyPath-based API instead of selectors if appropriate.
You can read more about selectors under Interacting with Objective-C APIs in Using Swift with Cocoa and Objective-C.
Note: Before Swift 2.2, Selector
conformed to StringLiteralConvertible
, so you might find old code where bare strings are passed to APIs that take selectors. You'll want to run "Convert to Current Swift Syntax" in Xcode to get those using #selector
.
7
Putting a string with the function name worked, NSSelectorFromString() works also.
– Arbitur
Jun 3 '14 at 5:36
5
I'd like to mention that while "Interacting with Objective-C APIs" is on the website, it is NOT in 'The Swift Programming Language' book.
– user1040049
Jun 3 '14 at 20:32
9
This should probably mention that the selector needs a ":" at the end if it takes an argument. (E.g. test() -> "test" & test(this:String) -> "test:")
– Daniel Schlaug
Jul 6 '14 at 14:06
2
It should also be pointed out that the Cocoa frameworks expect an Objective-C style method name. If your method takes an argument you will need a ':' if it takes 2 arguments,size:andShape:
, if the first argument is named you may need aWith
, i.e.initWithData:
forfunc init(Data data: NSData)
– JMFR
Oct 28 '14 at 18:13
5
Is there anyway to add validation around passing the "selector" as a string? IE compiler warn us when we misspell, etc.
– yo.ian.g
Dec 13 '14 at 18:59
|
show 11 more comments
up vote
880
down vote
accepted
Swift itself doesn't use selectors — several design patterns that in Objective-C make use of selectors work differently in Swift. (For example, use optional chaining on protocol types or is
/as
tests instead of respondsToSelector:
, and use closures wherever you can instead of performSelector:
for better type/memory safety.)
But there are still a number of important ObjC-based APIs that use selectors, including timers and the target/action pattern. Swift provides the Selector
type for working with these. (Swift automatically uses this in place of ObjC's SEL
type.)
In Swift 2.2 (Xcode 7.3) and later (including Swift 3 / Xcode 8 and Swift 4 / Xcode 9):
You can construct a Selector
from a Swift function type using the #selector
expression.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
The great thing about this approach? A function reference is checked by the Swift compiler, so you can use the #selector
expression only with class/method pairs that actually exist and are eligible for use as selectors (see "Selector availability" below). You're also free to make your function reference only as specific as you need, as per the Swift 2.2+ rules for function-type naming.
(This is actually an improvement over ObjC's @selector()
directive, because the compiler's -Wundeclared-selector
check verifies only that the named selector exists. The Swift function reference you pass to #selector
checks existence, membership in a class, and type signature.)
There are a couple of extra caveats for the function references you pass to the #selector
expression:
- Multiple functions with the same base name can be differentiated by their parameter labels using the aforementioned syntax for function references (e.g.
insertSubview(_:at:)
vsinsertSubview(_:aboveSubview:)
). But if a function has no parameters, the only way to disambiguate it is to use anas
cast with the function's type signature (e.g.foo as () -> ()
vsfoo(_:)
). - There's a special syntax for property getter/setter pairs in Swift 3.0+. For example, given a
var foo: Int
, you can use#selector(getter: MyClass.foo)
or#selector(setter: MyClass.foo)
.
General notes:
Cases where #selector
doesn't work, and naming: Sometimes you don't have a function reference to make a selector with (for example, with methods dynamically registered in the ObjC runtime). In that case, you can construct a Selector
from a string: e.g. Selector("dynamicMethod:")
— though you lose the compiler's validity checking. When you do that, you need to follow ObjC naming rules, including colons (:
) for each parameter.
Selector availability: The method referenced by the selector must be exposed to the ObjC runtime. In Swift 4, every method exposed to ObjC must have its declaration prefaced with the @objc
attribute. (In previous versions you got that attribute for free in some cases, but now you have to explicitly declare it.)
Remember that private
symbols aren't exposed to the runtime, too — your method needs to have at least internal
visibility.
Key paths: These are related to but not quite the same as selectors. There's a special syntax for these in Swift 3, too: e.g. chris.valueForKeyPath(#keyPath(Person.friends.firstName))
. See SE-0062 for details. And even more KeyPath
stuff in Swift 4, so make sure you're using the right KeyPath-based API instead of selectors if appropriate.
You can read more about selectors under Interacting with Objective-C APIs in Using Swift with Cocoa and Objective-C.
Note: Before Swift 2.2, Selector
conformed to StringLiteralConvertible
, so you might find old code where bare strings are passed to APIs that take selectors. You'll want to run "Convert to Current Swift Syntax" in Xcode to get those using #selector
.
7
Putting a string with the function name worked, NSSelectorFromString() works also.
– Arbitur
Jun 3 '14 at 5:36
5
I'd like to mention that while "Interacting with Objective-C APIs" is on the website, it is NOT in 'The Swift Programming Language' book.
– user1040049
Jun 3 '14 at 20:32
9
This should probably mention that the selector needs a ":" at the end if it takes an argument. (E.g. test() -> "test" & test(this:String) -> "test:")
– Daniel Schlaug
Jul 6 '14 at 14:06
2
It should also be pointed out that the Cocoa frameworks expect an Objective-C style method name. If your method takes an argument you will need a ':' if it takes 2 arguments,size:andShape:
, if the first argument is named you may need aWith
, i.e.initWithData:
forfunc init(Data data: NSData)
– JMFR
Oct 28 '14 at 18:13
5
Is there anyway to add validation around passing the "selector" as a string? IE compiler warn us when we misspell, etc.
– yo.ian.g
Dec 13 '14 at 18:59
|
show 11 more comments
up vote
880
down vote
accepted
up vote
880
down vote
accepted
Swift itself doesn't use selectors — several design patterns that in Objective-C make use of selectors work differently in Swift. (For example, use optional chaining on protocol types or is
/as
tests instead of respondsToSelector:
, and use closures wherever you can instead of performSelector:
for better type/memory safety.)
But there are still a number of important ObjC-based APIs that use selectors, including timers and the target/action pattern. Swift provides the Selector
type for working with these. (Swift automatically uses this in place of ObjC's SEL
type.)
In Swift 2.2 (Xcode 7.3) and later (including Swift 3 / Xcode 8 and Swift 4 / Xcode 9):
You can construct a Selector
from a Swift function type using the #selector
expression.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
The great thing about this approach? A function reference is checked by the Swift compiler, so you can use the #selector
expression only with class/method pairs that actually exist and are eligible for use as selectors (see "Selector availability" below). You're also free to make your function reference only as specific as you need, as per the Swift 2.2+ rules for function-type naming.
(This is actually an improvement over ObjC's @selector()
directive, because the compiler's -Wundeclared-selector
check verifies only that the named selector exists. The Swift function reference you pass to #selector
checks existence, membership in a class, and type signature.)
There are a couple of extra caveats for the function references you pass to the #selector
expression:
- Multiple functions with the same base name can be differentiated by their parameter labels using the aforementioned syntax for function references (e.g.
insertSubview(_:at:)
vsinsertSubview(_:aboveSubview:)
). But if a function has no parameters, the only way to disambiguate it is to use anas
cast with the function's type signature (e.g.foo as () -> ()
vsfoo(_:)
). - There's a special syntax for property getter/setter pairs in Swift 3.0+. For example, given a
var foo: Int
, you can use#selector(getter: MyClass.foo)
or#selector(setter: MyClass.foo)
.
General notes:
Cases where #selector
doesn't work, and naming: Sometimes you don't have a function reference to make a selector with (for example, with methods dynamically registered in the ObjC runtime). In that case, you can construct a Selector
from a string: e.g. Selector("dynamicMethod:")
— though you lose the compiler's validity checking. When you do that, you need to follow ObjC naming rules, including colons (:
) for each parameter.
Selector availability: The method referenced by the selector must be exposed to the ObjC runtime. In Swift 4, every method exposed to ObjC must have its declaration prefaced with the @objc
attribute. (In previous versions you got that attribute for free in some cases, but now you have to explicitly declare it.)
Remember that private
symbols aren't exposed to the runtime, too — your method needs to have at least internal
visibility.
Key paths: These are related to but not quite the same as selectors. There's a special syntax for these in Swift 3, too: e.g. chris.valueForKeyPath(#keyPath(Person.friends.firstName))
. See SE-0062 for details. And even more KeyPath
stuff in Swift 4, so make sure you're using the right KeyPath-based API instead of selectors if appropriate.
You can read more about selectors under Interacting with Objective-C APIs in Using Swift with Cocoa and Objective-C.
Note: Before Swift 2.2, Selector
conformed to StringLiteralConvertible
, so you might find old code where bare strings are passed to APIs that take selectors. You'll want to run "Convert to Current Swift Syntax" in Xcode to get those using #selector
.
Swift itself doesn't use selectors — several design patterns that in Objective-C make use of selectors work differently in Swift. (For example, use optional chaining on protocol types or is
/as
tests instead of respondsToSelector:
, and use closures wherever you can instead of performSelector:
for better type/memory safety.)
But there are still a number of important ObjC-based APIs that use selectors, including timers and the target/action pattern. Swift provides the Selector
type for working with these. (Swift automatically uses this in place of ObjC's SEL
type.)
In Swift 2.2 (Xcode 7.3) and later (including Swift 3 / Xcode 8 and Swift 4 / Xcode 9):
You can construct a Selector
from a Swift function type using the #selector
expression.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
The great thing about this approach? A function reference is checked by the Swift compiler, so you can use the #selector
expression only with class/method pairs that actually exist and are eligible for use as selectors (see "Selector availability" below). You're also free to make your function reference only as specific as you need, as per the Swift 2.2+ rules for function-type naming.
(This is actually an improvement over ObjC's @selector()
directive, because the compiler's -Wundeclared-selector
check verifies only that the named selector exists. The Swift function reference you pass to #selector
checks existence, membership in a class, and type signature.)
There are a couple of extra caveats for the function references you pass to the #selector
expression:
- Multiple functions with the same base name can be differentiated by their parameter labels using the aforementioned syntax for function references (e.g.
insertSubview(_:at:)
vsinsertSubview(_:aboveSubview:)
). But if a function has no parameters, the only way to disambiguate it is to use anas
cast with the function's type signature (e.g.foo as () -> ()
vsfoo(_:)
). - There's a special syntax for property getter/setter pairs in Swift 3.0+. For example, given a
var foo: Int
, you can use#selector(getter: MyClass.foo)
or#selector(setter: MyClass.foo)
.
General notes:
Cases where #selector
doesn't work, and naming: Sometimes you don't have a function reference to make a selector with (for example, with methods dynamically registered in the ObjC runtime). In that case, you can construct a Selector
from a string: e.g. Selector("dynamicMethod:")
— though you lose the compiler's validity checking. When you do that, you need to follow ObjC naming rules, including colons (:
) for each parameter.
Selector availability: The method referenced by the selector must be exposed to the ObjC runtime. In Swift 4, every method exposed to ObjC must have its declaration prefaced with the @objc
attribute. (In previous versions you got that attribute for free in some cases, but now you have to explicitly declare it.)
Remember that private
symbols aren't exposed to the runtime, too — your method needs to have at least internal
visibility.
Key paths: These are related to but not quite the same as selectors. There's a special syntax for these in Swift 3, too: e.g. chris.valueForKeyPath(#keyPath(Person.friends.firstName))
. See SE-0062 for details. And even more KeyPath
stuff in Swift 4, so make sure you're using the right KeyPath-based API instead of selectors if appropriate.
You can read more about selectors under Interacting with Objective-C APIs in Using Swift with Cocoa and Objective-C.
Note: Before Swift 2.2, Selector
conformed to StringLiteralConvertible
, so you might find old code where bare strings are passed to APIs that take selectors. You'll want to run "Convert to Current Swift Syntax" in Xcode to get those using #selector
.
edited Sep 26 '17 at 20:40
answered Jun 3 '14 at 5:27
rickster
99.8k21202257
99.8k21202257
7
Putting a string with the function name worked, NSSelectorFromString() works also.
– Arbitur
Jun 3 '14 at 5:36
5
I'd like to mention that while "Interacting with Objective-C APIs" is on the website, it is NOT in 'The Swift Programming Language' book.
– user1040049
Jun 3 '14 at 20:32
9
This should probably mention that the selector needs a ":" at the end if it takes an argument. (E.g. test() -> "test" & test(this:String) -> "test:")
– Daniel Schlaug
Jul 6 '14 at 14:06
2
It should also be pointed out that the Cocoa frameworks expect an Objective-C style method name. If your method takes an argument you will need a ':' if it takes 2 arguments,size:andShape:
, if the first argument is named you may need aWith
, i.e.initWithData:
forfunc init(Data data: NSData)
– JMFR
Oct 28 '14 at 18:13
5
Is there anyway to add validation around passing the "selector" as a string? IE compiler warn us when we misspell, etc.
– yo.ian.g
Dec 13 '14 at 18:59
|
show 11 more comments
7
Putting a string with the function name worked, NSSelectorFromString() works also.
– Arbitur
Jun 3 '14 at 5:36
5
I'd like to mention that while "Interacting with Objective-C APIs" is on the website, it is NOT in 'The Swift Programming Language' book.
– user1040049
Jun 3 '14 at 20:32
9
This should probably mention that the selector needs a ":" at the end if it takes an argument. (E.g. test() -> "test" & test(this:String) -> "test:")
– Daniel Schlaug
Jul 6 '14 at 14:06
2
It should also be pointed out that the Cocoa frameworks expect an Objective-C style method name. If your method takes an argument you will need a ':' if it takes 2 arguments,size:andShape:
, if the first argument is named you may need aWith
, i.e.initWithData:
forfunc init(Data data: NSData)
– JMFR
Oct 28 '14 at 18:13
5
Is there anyway to add validation around passing the "selector" as a string? IE compiler warn us when we misspell, etc.
– yo.ian.g
Dec 13 '14 at 18:59
7
7
Putting a string with the function name worked, NSSelectorFromString() works also.
– Arbitur
Jun 3 '14 at 5:36
Putting a string with the function name worked, NSSelectorFromString() works also.
– Arbitur
Jun 3 '14 at 5:36
5
5
I'd like to mention that while "Interacting with Objective-C APIs" is on the website, it is NOT in 'The Swift Programming Language' book.
– user1040049
Jun 3 '14 at 20:32
I'd like to mention that while "Interacting with Objective-C APIs" is on the website, it is NOT in 'The Swift Programming Language' book.
– user1040049
Jun 3 '14 at 20:32
9
9
This should probably mention that the selector needs a ":" at the end if it takes an argument. (E.g. test() -> "test" & test(this:String) -> "test:")
– Daniel Schlaug
Jul 6 '14 at 14:06
This should probably mention that the selector needs a ":" at the end if it takes an argument. (E.g. test() -> "test" & test(this:String) -> "test:")
– Daniel Schlaug
Jul 6 '14 at 14:06
2
2
It should also be pointed out that the Cocoa frameworks expect an Objective-C style method name. If your method takes an argument you will need a ':' if it takes 2 arguments,
size:andShape:
, if the first argument is named you may need a With
, i.e. initWithData:
for func init(Data data: NSData)
– JMFR
Oct 28 '14 at 18:13
It should also be pointed out that the Cocoa frameworks expect an Objective-C style method name. If your method takes an argument you will need a ':' if it takes 2 arguments,
size:andShape:
, if the first argument is named you may need a With
, i.e. initWithData:
for func init(Data data: NSData)
– JMFR
Oct 28 '14 at 18:13
5
5
Is there anyway to add validation around passing the "selector" as a string? IE compiler warn us when we misspell, etc.
– yo.ian.g
Dec 13 '14 at 18:59
Is there anyway to add validation around passing the "selector" as a string? IE compiler warn us when we misspell, etc.
– yo.ian.g
Dec 13 '14 at 18:59
|
show 11 more comments
up vote
78
down vote
Here's a quick example on how to use the Selector
class on Swift:
override func viewDidLoad() {
super.viewDidLoad()
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
self.navigationItem.rightBarButtonItem = rightButton
}
func method() {
// Something cool here
}
Note that if the method passed as a string doesn't work, it will fail at runtime, not compile time, and crash your app. Be careful
12
which is horrible... is there a "NSStringFromSelector" type of thing ?
– Lena Bru
Jun 4 '14 at 22:47
11
can't believe they designed for unchecked selectors since objc had this
– malhal
Jun 6 '14 at 15:11
4
@malcomhall:@selector
is handy, but it's not enforced as formally as you might think. "Undeclared selector" is merely a warning from the compiler, because new selectors can always be introduced at run time. Verifiable/refactorable selector references in Swift would be a good feature request to make, though.
– rickster
Aug 8 '14 at 22:15
2
This answer is helpful but the answer below with @objc is more appropriate.
– cynistersix
Nov 12 '14 at 22:55
When you are passing the selector string in as a variable or parameter, you'll need to let the compiler know its a selector using the Selector() function. thanks
– levous
Aug 4 '15 at 11:53
|
show 1 more comment
up vote
78
down vote
Here's a quick example on how to use the Selector
class on Swift:
override func viewDidLoad() {
super.viewDidLoad()
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
self.navigationItem.rightBarButtonItem = rightButton
}
func method() {
// Something cool here
}
Note that if the method passed as a string doesn't work, it will fail at runtime, not compile time, and crash your app. Be careful
12
which is horrible... is there a "NSStringFromSelector" type of thing ?
– Lena Bru
Jun 4 '14 at 22:47
11
can't believe they designed for unchecked selectors since objc had this
– malhal
Jun 6 '14 at 15:11
4
@malcomhall:@selector
is handy, but it's not enforced as formally as you might think. "Undeclared selector" is merely a warning from the compiler, because new selectors can always be introduced at run time. Verifiable/refactorable selector references in Swift would be a good feature request to make, though.
– rickster
Aug 8 '14 at 22:15
2
This answer is helpful but the answer below with @objc is more appropriate.
– cynistersix
Nov 12 '14 at 22:55
When you are passing the selector string in as a variable or parameter, you'll need to let the compiler know its a selector using the Selector() function. thanks
– levous
Aug 4 '15 at 11:53
|
show 1 more comment
up vote
78
down vote
up vote
78
down vote
Here's a quick example on how to use the Selector
class on Swift:
override func viewDidLoad() {
super.viewDidLoad()
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
self.navigationItem.rightBarButtonItem = rightButton
}
func method() {
// Something cool here
}
Note that if the method passed as a string doesn't work, it will fail at runtime, not compile time, and crash your app. Be careful
Here's a quick example on how to use the Selector
class on Swift:
override func viewDidLoad() {
super.viewDidLoad()
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
self.navigationItem.rightBarButtonItem = rightButton
}
func method() {
// Something cool here
}
Note that if the method passed as a string doesn't work, it will fail at runtime, not compile time, and crash your app. Be careful
answered Jun 3 '14 at 5:31
Oscar Swanros
16.4k52847
16.4k52847
12
which is horrible... is there a "NSStringFromSelector" type of thing ?
– Lena Bru
Jun 4 '14 at 22:47
11
can't believe they designed for unchecked selectors since objc had this
– malhal
Jun 6 '14 at 15:11
4
@malcomhall:@selector
is handy, but it's not enforced as formally as you might think. "Undeclared selector" is merely a warning from the compiler, because new selectors can always be introduced at run time. Verifiable/refactorable selector references in Swift would be a good feature request to make, though.
– rickster
Aug 8 '14 at 22:15
2
This answer is helpful but the answer below with @objc is more appropriate.
– cynistersix
Nov 12 '14 at 22:55
When you are passing the selector string in as a variable or parameter, you'll need to let the compiler know its a selector using the Selector() function. thanks
– levous
Aug 4 '15 at 11:53
|
show 1 more comment
12
which is horrible... is there a "NSStringFromSelector" type of thing ?
– Lena Bru
Jun 4 '14 at 22:47
11
can't believe they designed for unchecked selectors since objc had this
– malhal
Jun 6 '14 at 15:11
4
@malcomhall:@selector
is handy, but it's not enforced as formally as you might think. "Undeclared selector" is merely a warning from the compiler, because new selectors can always be introduced at run time. Verifiable/refactorable selector references in Swift would be a good feature request to make, though.
– rickster
Aug 8 '14 at 22:15
2
This answer is helpful but the answer below with @objc is more appropriate.
– cynistersix
Nov 12 '14 at 22:55
When you are passing the selector string in as a variable or parameter, you'll need to let the compiler know its a selector using the Selector() function. thanks
– levous
Aug 4 '15 at 11:53
12
12
which is horrible... is there a "NSStringFromSelector" type of thing ?
– Lena Bru
Jun 4 '14 at 22:47
which is horrible... is there a "NSStringFromSelector" type of thing ?
– Lena Bru
Jun 4 '14 at 22:47
11
11
can't believe they designed for unchecked selectors since objc had this
– malhal
Jun 6 '14 at 15:11
can't believe they designed for unchecked selectors since objc had this
– malhal
Jun 6 '14 at 15:11
4
4
@malcomhall:
@selector
is handy, but it's not enforced as formally as you might think. "Undeclared selector" is merely a warning from the compiler, because new selectors can always be introduced at run time. Verifiable/refactorable selector references in Swift would be a good feature request to make, though.– rickster
Aug 8 '14 at 22:15
@malcomhall:
@selector
is handy, but it's not enforced as formally as you might think. "Undeclared selector" is merely a warning from the compiler, because new selectors can always be introduced at run time. Verifiable/refactorable selector references in Swift would be a good feature request to make, though.– rickster
Aug 8 '14 at 22:15
2
2
This answer is helpful but the answer below with @objc is more appropriate.
– cynistersix
Nov 12 '14 at 22:55
This answer is helpful but the answer below with @objc is more appropriate.
– cynistersix
Nov 12 '14 at 22:55
When you are passing the selector string in as a variable or parameter, you'll need to let the compiler know its a selector using the Selector() function. thanks
– levous
Aug 4 '15 at 11:53
When you are passing the selector string in as a variable or parameter, you'll need to let the compiler know its a selector using the Selector() function. thanks
– levous
Aug 4 '15 at 11:53
|
show 1 more comment
up vote
44
down vote
Also, if your (Swift) class does not descend from an Objective-C class, then you must have a colon at the end of the target method name string and you must use the @objc property with your target method e.g.
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
@objc func method() {
// Something cool here
}
otherwise you will get a "Unrecognised Selector" error at runtime.
3
1. selectors w/ a colon must take an argument 2. according to Apple docs timer's actions should take NSTimer argument 3.Selector
keyword is not mandatory. So in this case signature must be@objc func method(timer: NSTimer) {/*code*/}
– Yevhen Dubinin
Dec 1 '14 at 0:31
@objc
worked for me. I didn't need to includetimer: NSTimer
in my method signature for it to be called.
– Mike Taverne
Feb 5 '15 at 19:03
add a comment |
up vote
44
down vote
Also, if your (Swift) class does not descend from an Objective-C class, then you must have a colon at the end of the target method name string and you must use the @objc property with your target method e.g.
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
@objc func method() {
// Something cool here
}
otherwise you will get a "Unrecognised Selector" error at runtime.
3
1. selectors w/ a colon must take an argument 2. according to Apple docs timer's actions should take NSTimer argument 3.Selector
keyword is not mandatory. So in this case signature must be@objc func method(timer: NSTimer) {/*code*/}
– Yevhen Dubinin
Dec 1 '14 at 0:31
@objc
worked for me. I didn't need to includetimer: NSTimer
in my method signature for it to be called.
– Mike Taverne
Feb 5 '15 at 19:03
add a comment |
up vote
44
down vote
up vote
44
down vote
Also, if your (Swift) class does not descend from an Objective-C class, then you must have a colon at the end of the target method name string and you must use the @objc property with your target method e.g.
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
@objc func method() {
// Something cool here
}
otherwise you will get a "Unrecognised Selector" error at runtime.
Also, if your (Swift) class does not descend from an Objective-C class, then you must have a colon at the end of the target method name string and you must use the @objc property with your target method e.g.
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
@objc func method() {
// Something cool here
}
otherwise you will get a "Unrecognised Selector" error at runtime.
edited Mar 8 '15 at 12:49
Leo Natan
51.4k8123173
51.4k8123173
answered Jun 24 '14 at 15:23
user3771857
57743
57743
3
1. selectors w/ a colon must take an argument 2. according to Apple docs timer's actions should take NSTimer argument 3.Selector
keyword is not mandatory. So in this case signature must be@objc func method(timer: NSTimer) {/*code*/}
– Yevhen Dubinin
Dec 1 '14 at 0:31
@objc
worked for me. I didn't need to includetimer: NSTimer
in my method signature for it to be called.
– Mike Taverne
Feb 5 '15 at 19:03
add a comment |
3
1. selectors w/ a colon must take an argument 2. according to Apple docs timer's actions should take NSTimer argument 3.Selector
keyword is not mandatory. So in this case signature must be@objc func method(timer: NSTimer) {/*code*/}
– Yevhen Dubinin
Dec 1 '14 at 0:31
@objc
worked for me. I didn't need to includetimer: NSTimer
in my method signature for it to be called.
– Mike Taverne
Feb 5 '15 at 19:03
3
3
1. selectors w/ a colon must take an argument 2. according to Apple docs timer's actions should take NSTimer argument 3.
Selector
keyword is not mandatory. So in this case signature must be @objc func method(timer: NSTimer) {/*code*/}
– Yevhen Dubinin
Dec 1 '14 at 0:31
1. selectors w/ a colon must take an argument 2. according to Apple docs timer's actions should take NSTimer argument 3.
Selector
keyword is not mandatory. So in this case signature must be @objc func method(timer: NSTimer) {/*code*/}
– Yevhen Dubinin
Dec 1 '14 at 0:31
@objc
worked for me. I didn't need to include timer: NSTimer
in my method signature for it to be called.– Mike Taverne
Feb 5 '15 at 19:03
@objc
worked for me. I didn't need to include timer: NSTimer
in my method signature for it to be called.– Mike Taverne
Feb 5 '15 at 19:03
add a comment |
up vote
23
down vote
For future readers, I found that I experienced a problem and was getting an unrecognised selector sent to instance
error that was caused by marking the target func
as private.
The func
MUST be publicly visible to be called by an object with a reference to a selector.
13
it doesn't have to be public you can still keep the method private but addobjc
before it's declaration. Ex:@objc private func foo() { ...
then you can use"foo"
as a selector as much you like
– apouche
Oct 28 '15 at 10:40
dynamic func foo() { ... } also works
– NAlexN
Jan 30 '17 at 14:15
It can also beinternal
, thus not specifying any access modifier. I often use this pattern://MARK: - Selector Methodsn extension MyController {n func buttonPressed(_ button: UIButton) {
– Sajjon
Apr 6 '17 at 8:27
add a comment |
up vote
23
down vote
For future readers, I found that I experienced a problem and was getting an unrecognised selector sent to instance
error that was caused by marking the target func
as private.
The func
MUST be publicly visible to be called by an object with a reference to a selector.
13
it doesn't have to be public you can still keep the method private but addobjc
before it's declaration. Ex:@objc private func foo() { ...
then you can use"foo"
as a selector as much you like
– apouche
Oct 28 '15 at 10:40
dynamic func foo() { ... } also works
– NAlexN
Jan 30 '17 at 14:15
It can also beinternal
, thus not specifying any access modifier. I often use this pattern://MARK: - Selector Methodsn extension MyController {n func buttonPressed(_ button: UIButton) {
– Sajjon
Apr 6 '17 at 8:27
add a comment |
up vote
23
down vote
up vote
23
down vote
For future readers, I found that I experienced a problem and was getting an unrecognised selector sent to instance
error that was caused by marking the target func
as private.
The func
MUST be publicly visible to be called by an object with a reference to a selector.
For future readers, I found that I experienced a problem and was getting an unrecognised selector sent to instance
error that was caused by marking the target func
as private.
The func
MUST be publicly visible to be called by an object with a reference to a selector.
edited May 10 '15 at 19:16
answered Apr 10 '15 at 18:08
Rob Sanders
3,21821735
3,21821735
13
it doesn't have to be public you can still keep the method private but addobjc
before it's declaration. Ex:@objc private func foo() { ...
then you can use"foo"
as a selector as much you like
– apouche
Oct 28 '15 at 10:40
dynamic func foo() { ... } also works
– NAlexN
Jan 30 '17 at 14:15
It can also beinternal
, thus not specifying any access modifier. I often use this pattern://MARK: - Selector Methodsn extension MyController {n func buttonPressed(_ button: UIButton) {
– Sajjon
Apr 6 '17 at 8:27
add a comment |
13
it doesn't have to be public you can still keep the method private but addobjc
before it's declaration. Ex:@objc private func foo() { ...
then you can use"foo"
as a selector as much you like
– apouche
Oct 28 '15 at 10:40
dynamic func foo() { ... } also works
– NAlexN
Jan 30 '17 at 14:15
It can also beinternal
, thus not specifying any access modifier. I often use this pattern://MARK: - Selector Methodsn extension MyController {n func buttonPressed(_ button: UIButton) {
– Sajjon
Apr 6 '17 at 8:27
13
13
it doesn't have to be public you can still keep the method private but add
objc
before it's declaration. Ex: @objc private func foo() { ...
then you can use "foo"
as a selector as much you like– apouche
Oct 28 '15 at 10:40
it doesn't have to be public you can still keep the method private but add
objc
before it's declaration. Ex: @objc private func foo() { ...
then you can use "foo"
as a selector as much you like– apouche
Oct 28 '15 at 10:40
dynamic func foo() { ... } also works
– NAlexN
Jan 30 '17 at 14:15
dynamic func foo() { ... } also works
– NAlexN
Jan 30 '17 at 14:15
It can also be
internal
, thus not specifying any access modifier. I often use this pattern: //MARK: - Selector Methodsn extension MyController {n func buttonPressed(_ button: UIButton) {
– Sajjon
Apr 6 '17 at 8:27
It can also be
internal
, thus not specifying any access modifier. I often use this pattern: //MARK: - Selector Methodsn extension MyController {n func buttonPressed(_ button: UIButton) {
– Sajjon
Apr 6 '17 at 8:27
add a comment |
up vote
23
down vote
Swift 2.2+ and Swift 3 Update
Use the new #selector
expression, which eliminates the need to use string literals making usage less error-prone. For reference:
Selector("keyboardDidHide:")
becomes
#selector(keyboardDidHide(_:))
See also: Swift Evolution Proposal
Note (Swift 4.0):
If using #selector
you would need to mark the function as @objc
Example:
@objc func something(_ sender: UIButton)
add a comment |
up vote
23
down vote
Swift 2.2+ and Swift 3 Update
Use the new #selector
expression, which eliminates the need to use string literals making usage less error-prone. For reference:
Selector("keyboardDidHide:")
becomes
#selector(keyboardDidHide(_:))
See also: Swift Evolution Proposal
Note (Swift 4.0):
If using #selector
you would need to mark the function as @objc
Example:
@objc func something(_ sender: UIButton)
add a comment |
up vote
23
down vote
up vote
23
down vote
Swift 2.2+ and Swift 3 Update
Use the new #selector
expression, which eliminates the need to use string literals making usage less error-prone. For reference:
Selector("keyboardDidHide:")
becomes
#selector(keyboardDidHide(_:))
See also: Swift Evolution Proposal
Note (Swift 4.0):
If using #selector
you would need to mark the function as @objc
Example:
@objc func something(_ sender: UIButton)
Swift 2.2+ and Swift 3 Update
Use the new #selector
expression, which eliminates the need to use string literals making usage less error-prone. For reference:
Selector("keyboardDidHide:")
becomes
#selector(keyboardDidHide(_:))
See also: Swift Evolution Proposal
Note (Swift 4.0):
If using #selector
you would need to mark the function as @objc
Example:
@objc func something(_ sender: UIButton)
edited Nov 22 '17 at 5:31
Joseph Francis
288417
288417
answered Apr 6 '16 at 16:06
Kyle Clegg
28.6k25117128
28.6k25117128
add a comment |
add a comment |
up vote
19
down vote
Just in case somebody else have the same problem I had with NSTimer where none of the other answers fixed the issue, is really important to mention that, if you are using a class that do not inherits from NSObject either directly or deep in the hierarchy(e.g. manually created swift files), none of the other answers will work even when is specified as follows:
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
Without changing anything else other than just making the class inherit from NSObject I stopped getting the "Unrecognized selector" Error and got my logic working as expected.
The issue with this alternative is that you can´t change a class (let´s say ViewController) to inherit from NSObject, given that you need the ViewController class implemented stuff (e.g. viewDidLoad()). Any idea how to call a Swift function within a ViewController using NSTimer?... e
– eharo2
Jul 22 '14 at 18:47
1
UIViewController already inherits from NSObject, most classes exposed by the SDK do, this example is for your own created classes that require NSTimer functionality...
– Martin Cazares
Jul 22 '14 at 19:10
add a comment |
up vote
19
down vote
Just in case somebody else have the same problem I had with NSTimer where none of the other answers fixed the issue, is really important to mention that, if you are using a class that do not inherits from NSObject either directly or deep in the hierarchy(e.g. manually created swift files), none of the other answers will work even when is specified as follows:
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
Without changing anything else other than just making the class inherit from NSObject I stopped getting the "Unrecognized selector" Error and got my logic working as expected.
The issue with this alternative is that you can´t change a class (let´s say ViewController) to inherit from NSObject, given that you need the ViewController class implemented stuff (e.g. viewDidLoad()). Any idea how to call a Swift function within a ViewController using NSTimer?... e
– eharo2
Jul 22 '14 at 18:47
1
UIViewController already inherits from NSObject, most classes exposed by the SDK do, this example is for your own created classes that require NSTimer functionality...
– Martin Cazares
Jul 22 '14 at 19:10
add a comment |
up vote
19
down vote
up vote
19
down vote
Just in case somebody else have the same problem I had with NSTimer where none of the other answers fixed the issue, is really important to mention that, if you are using a class that do not inherits from NSObject either directly or deep in the hierarchy(e.g. manually created swift files), none of the other answers will work even when is specified as follows:
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
Without changing anything else other than just making the class inherit from NSObject I stopped getting the "Unrecognized selector" Error and got my logic working as expected.
Just in case somebody else have the same problem I had with NSTimer where none of the other answers fixed the issue, is really important to mention that, if you are using a class that do not inherits from NSObject either directly or deep in the hierarchy(e.g. manually created swift files), none of the other answers will work even when is specified as follows:
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
Without changing anything else other than just making the class inherit from NSObject I stopped getting the "Unrecognized selector" Error and got my logic working as expected.
edited May 31 '15 at 6:59
royhowie
8,851133658
8,851133658
answered Jul 13 '14 at 5:31
Martin Cazares
10.9k73752
10.9k73752
The issue with this alternative is that you can´t change a class (let´s say ViewController) to inherit from NSObject, given that you need the ViewController class implemented stuff (e.g. viewDidLoad()). Any idea how to call a Swift function within a ViewController using NSTimer?... e
– eharo2
Jul 22 '14 at 18:47
1
UIViewController already inherits from NSObject, most classes exposed by the SDK do, this example is for your own created classes that require NSTimer functionality...
– Martin Cazares
Jul 22 '14 at 19:10
add a comment |
The issue with this alternative is that you can´t change a class (let´s say ViewController) to inherit from NSObject, given that you need the ViewController class implemented stuff (e.g. viewDidLoad()). Any idea how to call a Swift function within a ViewController using NSTimer?... e
– eharo2
Jul 22 '14 at 18:47
1
UIViewController already inherits from NSObject, most classes exposed by the SDK do, this example is for your own created classes that require NSTimer functionality...
– Martin Cazares
Jul 22 '14 at 19:10
The issue with this alternative is that you can´t change a class (let´s say ViewController) to inherit from NSObject, given that you need the ViewController class implemented stuff (e.g. viewDidLoad()). Any idea how to call a Swift function within a ViewController using NSTimer?... e
– eharo2
Jul 22 '14 at 18:47
The issue with this alternative is that you can´t change a class (let´s say ViewController) to inherit from NSObject, given that you need the ViewController class implemented stuff (e.g. viewDidLoad()). Any idea how to call a Swift function within a ViewController using NSTimer?... e
– eharo2
Jul 22 '14 at 18:47
1
1
UIViewController already inherits from NSObject, most classes exposed by the SDK do, this example is for your own created classes that require NSTimer functionality...
– Martin Cazares
Jul 22 '14 at 19:10
UIViewController already inherits from NSObject, most classes exposed by the SDK do, this example is for your own created classes that require NSTimer functionality...
– Martin Cazares
Jul 22 '14 at 19:10
add a comment |
up vote
18
down vote
Swift 4.0
you create the Selector like below.
1.add the event to a button like:
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
and the function will be like below:
@objc func clickedButton(sender: AnyObject) {
}
3
You forgot to put@objc
beforefunc
which is required in Swift 4.
– Vahid Amiri
Jan 27 at 15:49
add a comment |
up vote
18
down vote
Swift 4.0
you create the Selector like below.
1.add the event to a button like:
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
and the function will be like below:
@objc func clickedButton(sender: AnyObject) {
}
3
You forgot to put@objc
beforefunc
which is required in Swift 4.
– Vahid Amiri
Jan 27 at 15:49
add a comment |
up vote
18
down vote
up vote
18
down vote
Swift 4.0
you create the Selector like below.
1.add the event to a button like:
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
and the function will be like below:
@objc func clickedButton(sender: AnyObject) {
}
Swift 4.0
you create the Selector like below.
1.add the event to a button like:
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
and the function will be like below:
@objc func clickedButton(sender: AnyObject) {
}
edited Mar 15 at 17:50
Kevin Singh
14117
14117
answered Oct 15 '14 at 7:27
pravin salame
23924
23924
3
You forgot to put@objc
beforefunc
which is required in Swift 4.
– Vahid Amiri
Jan 27 at 15:49
add a comment |
3
You forgot to put@objc
beforefunc
which is required in Swift 4.
– Vahid Amiri
Jan 27 at 15:49
3
3
You forgot to put
@objc
before func
which is required in Swift 4.– Vahid Amiri
Jan 27 at 15:49
You forgot to put
@objc
before func
which is required in Swift 4.– Vahid Amiri
Jan 27 at 15:49
add a comment |
up vote
14
down vote
If you want to pass a parameter to the function from the NSTimer then here is your solution:
var somethingToPass = "It worked"
let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)
func tester(timer: NSTimer)
{
let theStringToPrint = timer.userInfo as String
println(theStringToPrint)
}
Include the colon in the selector text (tester:), and your parameter(s) go in userInfo.
Your function should take NSTimer as a parameter. Then just extract userInfo to get the parameter that passed.
3
I was using NSTimer(0.01, target: self, ...) which did NOT work, whereas using NSTimer.scheduledTimerWithTimeInterval(0.01, ..) DID work!? Strange but thanks @Scooter for you answer!
– iOS-Coder
Jul 5 '15 at 12:19
1
@iOS-Coder just creating a timer with the initialiser does not add it to a runloop, whereasscheduledTimerWith...
automatically adds it to the current runloop - so there is no strange behaviour here at all ;)
– David Ganster
Oct 5 '15 at 21:30
1
@David thanks for your suggestion. I guess my misunderstanding should belong in either STFW or RTFA (Read The F...ing API) category?
– iOS-Coder
Oct 6 '15 at 22:27
1
Don't worry about it, no one can be expected to read the documentation about every single method in every API ;)
– David Ganster
Oct 7 '15 at 9:14
add a comment |
up vote
14
down vote
If you want to pass a parameter to the function from the NSTimer then here is your solution:
var somethingToPass = "It worked"
let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)
func tester(timer: NSTimer)
{
let theStringToPrint = timer.userInfo as String
println(theStringToPrint)
}
Include the colon in the selector text (tester:), and your parameter(s) go in userInfo.
Your function should take NSTimer as a parameter. Then just extract userInfo to get the parameter that passed.
3
I was using NSTimer(0.01, target: self, ...) which did NOT work, whereas using NSTimer.scheduledTimerWithTimeInterval(0.01, ..) DID work!? Strange but thanks @Scooter for you answer!
– iOS-Coder
Jul 5 '15 at 12:19
1
@iOS-Coder just creating a timer with the initialiser does not add it to a runloop, whereasscheduledTimerWith...
automatically adds it to the current runloop - so there is no strange behaviour here at all ;)
– David Ganster
Oct 5 '15 at 21:30
1
@David thanks for your suggestion. I guess my misunderstanding should belong in either STFW or RTFA (Read The F...ing API) category?
– iOS-Coder
Oct 6 '15 at 22:27
1
Don't worry about it, no one can be expected to read the documentation about every single method in every API ;)
– David Ganster
Oct 7 '15 at 9:14
add a comment |
up vote
14
down vote
up vote
14
down vote
If you want to pass a parameter to the function from the NSTimer then here is your solution:
var somethingToPass = "It worked"
let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)
func tester(timer: NSTimer)
{
let theStringToPrint = timer.userInfo as String
println(theStringToPrint)
}
Include the colon in the selector text (tester:), and your parameter(s) go in userInfo.
Your function should take NSTimer as a parameter. Then just extract userInfo to get the parameter that passed.
If you want to pass a parameter to the function from the NSTimer then here is your solution:
var somethingToPass = "It worked"
let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)
func tester(timer: NSTimer)
{
let theStringToPrint = timer.userInfo as String
println(theStringToPrint)
}
Include the colon in the selector text (tester:), and your parameter(s) go in userInfo.
Your function should take NSTimer as a parameter. Then just extract userInfo to get the parameter that passed.
answered Aug 7 '14 at 15:29
Scooter
2,60212133
2,60212133
3
I was using NSTimer(0.01, target: self, ...) which did NOT work, whereas using NSTimer.scheduledTimerWithTimeInterval(0.01, ..) DID work!? Strange but thanks @Scooter for you answer!
– iOS-Coder
Jul 5 '15 at 12:19
1
@iOS-Coder just creating a timer with the initialiser does not add it to a runloop, whereasscheduledTimerWith...
automatically adds it to the current runloop - so there is no strange behaviour here at all ;)
– David Ganster
Oct 5 '15 at 21:30
1
@David thanks for your suggestion. I guess my misunderstanding should belong in either STFW or RTFA (Read The F...ing API) category?
– iOS-Coder
Oct 6 '15 at 22:27
1
Don't worry about it, no one can be expected to read the documentation about every single method in every API ;)
– David Ganster
Oct 7 '15 at 9:14
add a comment |
3
I was using NSTimer(0.01, target: self, ...) which did NOT work, whereas using NSTimer.scheduledTimerWithTimeInterval(0.01, ..) DID work!? Strange but thanks @Scooter for you answer!
– iOS-Coder
Jul 5 '15 at 12:19
1
@iOS-Coder just creating a timer with the initialiser does not add it to a runloop, whereasscheduledTimerWith...
automatically adds it to the current runloop - so there is no strange behaviour here at all ;)
– David Ganster
Oct 5 '15 at 21:30
1
@David thanks for your suggestion. I guess my misunderstanding should belong in either STFW or RTFA (Read The F...ing API) category?
– iOS-Coder
Oct 6 '15 at 22:27
1
Don't worry about it, no one can be expected to read the documentation about every single method in every API ;)
– David Ganster
Oct 7 '15 at 9:14
3
3
I was using NSTimer(0.01, target: self, ...) which did NOT work, whereas using NSTimer.scheduledTimerWithTimeInterval(0.01, ..) DID work!? Strange but thanks @Scooter for you answer!
– iOS-Coder
Jul 5 '15 at 12:19
I was using NSTimer(0.01, target: self, ...) which did NOT work, whereas using NSTimer.scheduledTimerWithTimeInterval(0.01, ..) DID work!? Strange but thanks @Scooter for you answer!
– iOS-Coder
Jul 5 '15 at 12:19
1
1
@iOS-Coder just creating a timer with the initialiser does not add it to a runloop, whereas
scheduledTimerWith...
automatically adds it to the current runloop - so there is no strange behaviour here at all ;)– David Ganster
Oct 5 '15 at 21:30
@iOS-Coder just creating a timer with the initialiser does not add it to a runloop, whereas
scheduledTimerWith...
automatically adds it to the current runloop - so there is no strange behaviour here at all ;)– David Ganster
Oct 5 '15 at 21:30
1
1
@David thanks for your suggestion. I guess my misunderstanding should belong in either STFW or RTFA (Read The F...ing API) category?
– iOS-Coder
Oct 6 '15 at 22:27
@David thanks for your suggestion. I guess my misunderstanding should belong in either STFW or RTFA (Read The F...ing API) category?
– iOS-Coder
Oct 6 '15 at 22:27
1
1
Don't worry about it, no one can be expected to read the documentation about every single method in every API ;)
– David Ganster
Oct 7 '15 at 9:14
Don't worry about it, no one can be expected to read the documentation about every single method in every API ;)
– David Ganster
Oct 7 '15 at 9:14
add a comment |
up vote
10
down vote
Selectors are an internal representation of a method name in Objective-C. In Objective-C "@selector(methodName)" would convert a source-code method into a data type of SEL. Since you can't use the @selector syntax in Swift (rickster is on point there), you have to manually specify the method name as a String object directly, or by passing a String object to the Selector type. Here is an example:
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:"logout"
)
or
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:Selector("logout")
)
add a comment |
up vote
10
down vote
Selectors are an internal representation of a method name in Objective-C. In Objective-C "@selector(methodName)" would convert a source-code method into a data type of SEL. Since you can't use the @selector syntax in Swift (rickster is on point there), you have to manually specify the method name as a String object directly, or by passing a String object to the Selector type. Here is an example:
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:"logout"
)
or
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:Selector("logout")
)
add a comment |
up vote
10
down vote
up vote
10
down vote
Selectors are an internal representation of a method name in Objective-C. In Objective-C "@selector(methodName)" would convert a source-code method into a data type of SEL. Since you can't use the @selector syntax in Swift (rickster is on point there), you have to manually specify the method name as a String object directly, or by passing a String object to the Selector type. Here is an example:
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:"logout"
)
or
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:Selector("logout")
)
Selectors are an internal representation of a method name in Objective-C. In Objective-C "@selector(methodName)" would convert a source-code method into a data type of SEL. Since you can't use the @selector syntax in Swift (rickster is on point there), you have to manually specify the method name as a String object directly, or by passing a String object to the Selector type. Here is an example:
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:"logout"
)
or
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:Selector("logout")
)
answered Jun 5 '14 at 5:43
Jon Tsiros
398114
398114
add a comment |
add a comment |
up vote
8
down vote
Swift 4.1
With sample of tap gesture
let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))
// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))
@objc func dismiss(completion: (() -> Void)?) {
self.dismiss(animated: true, completion: completion)
}
See Apple's document for more details about: Selector Expression
Please stop doing this. It helps no one. How is this any different from Swift 3.1? And why did you think it necessary to add another answer to this when it already has about 20 answers?
– Fogmeister
Jun 9 '17 at 13:58
calling selector is different in swift 4. Try these answers in swift 4 and see. None these will work without editing. Please do not mark any statement as spam without ensuring its impotance
– Krunal
Jun 9 '17 at 13:59
So is there any reason you couldn't edit the existing, accepted answer? It would make it actually useful rather than adding on the end of a long list of answers. The "Edit" button is there for a reason.
– Fogmeister
Jun 9 '17 at 14:00
Also, which part of this is different from Swift 3?
– Fogmeister
Jun 9 '17 at 14:02
2
You have to add the objc tag to any selectors for Swift 4. This is the correct answer. And your not supposed to edit other people's answers to change their meaning. @Krunal is totally right.
– Unome
Sep 26 '17 at 15:33
|
show 1 more comment
up vote
8
down vote
Swift 4.1
With sample of tap gesture
let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))
// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))
@objc func dismiss(completion: (() -> Void)?) {
self.dismiss(animated: true, completion: completion)
}
See Apple's document for more details about: Selector Expression
Please stop doing this. It helps no one. How is this any different from Swift 3.1? And why did you think it necessary to add another answer to this when it already has about 20 answers?
– Fogmeister
Jun 9 '17 at 13:58
calling selector is different in swift 4. Try these answers in swift 4 and see. None these will work without editing. Please do not mark any statement as spam without ensuring its impotance
– Krunal
Jun 9 '17 at 13:59
So is there any reason you couldn't edit the existing, accepted answer? It would make it actually useful rather than adding on the end of a long list of answers. The "Edit" button is there for a reason.
– Fogmeister
Jun 9 '17 at 14:00
Also, which part of this is different from Swift 3?
– Fogmeister
Jun 9 '17 at 14:02
2
You have to add the objc tag to any selectors for Swift 4. This is the correct answer. And your not supposed to edit other people's answers to change their meaning. @Krunal is totally right.
– Unome
Sep 26 '17 at 15:33
|
show 1 more comment
up vote
8
down vote
up vote
8
down vote
Swift 4.1
With sample of tap gesture
let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))
// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))
@objc func dismiss(completion: (() -> Void)?) {
self.dismiss(animated: true, completion: completion)
}
See Apple's document for more details about: Selector Expression
Swift 4.1
With sample of tap gesture
let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))
// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))
@objc func dismiss(completion: (() -> Void)?) {
self.dismiss(animated: true, completion: completion)
}
See Apple's document for more details about: Selector Expression
edited Apr 17 at 10:18
answered Jun 9 '17 at 13:43
Krunal
35.8k20130157
35.8k20130157
Please stop doing this. It helps no one. How is this any different from Swift 3.1? And why did you think it necessary to add another answer to this when it already has about 20 answers?
– Fogmeister
Jun 9 '17 at 13:58
calling selector is different in swift 4. Try these answers in swift 4 and see. None these will work without editing. Please do not mark any statement as spam without ensuring its impotance
– Krunal
Jun 9 '17 at 13:59
So is there any reason you couldn't edit the existing, accepted answer? It would make it actually useful rather than adding on the end of a long list of answers. The "Edit" button is there for a reason.
– Fogmeister
Jun 9 '17 at 14:00
Also, which part of this is different from Swift 3?
– Fogmeister
Jun 9 '17 at 14:02
2
You have to add the objc tag to any selectors for Swift 4. This is the correct answer. And your not supposed to edit other people's answers to change their meaning. @Krunal is totally right.
– Unome
Sep 26 '17 at 15:33
|
show 1 more comment
Please stop doing this. It helps no one. How is this any different from Swift 3.1? And why did you think it necessary to add another answer to this when it already has about 20 answers?
– Fogmeister
Jun 9 '17 at 13:58
calling selector is different in swift 4. Try these answers in swift 4 and see. None these will work without editing. Please do not mark any statement as spam without ensuring its impotance
– Krunal
Jun 9 '17 at 13:59
So is there any reason you couldn't edit the existing, accepted answer? It would make it actually useful rather than adding on the end of a long list of answers. The "Edit" button is there for a reason.
– Fogmeister
Jun 9 '17 at 14:00
Also, which part of this is different from Swift 3?
– Fogmeister
Jun 9 '17 at 14:02
2
You have to add the objc tag to any selectors for Swift 4. This is the correct answer. And your not supposed to edit other people's answers to change their meaning. @Krunal is totally right.
– Unome
Sep 26 '17 at 15:33
Please stop doing this. It helps no one. How is this any different from Swift 3.1? And why did you think it necessary to add another answer to this when it already has about 20 answers?
– Fogmeister
Jun 9 '17 at 13:58
Please stop doing this. It helps no one. How is this any different from Swift 3.1? And why did you think it necessary to add another answer to this when it already has about 20 answers?
– Fogmeister
Jun 9 '17 at 13:58
calling selector is different in swift 4. Try these answers in swift 4 and see. None these will work without editing. Please do not mark any statement as spam without ensuring its impotance
– Krunal
Jun 9 '17 at 13:59
calling selector is different in swift 4. Try these answers in swift 4 and see. None these will work without editing. Please do not mark any statement as spam without ensuring its impotance
– Krunal
Jun 9 '17 at 13:59
So is there any reason you couldn't edit the existing, accepted answer? It would make it actually useful rather than adding on the end of a long list of answers. The "Edit" button is there for a reason.
– Fogmeister
Jun 9 '17 at 14:00
So is there any reason you couldn't edit the existing, accepted answer? It would make it actually useful rather than adding on the end of a long list of answers. The "Edit" button is there for a reason.
– Fogmeister
Jun 9 '17 at 14:00
Also, which part of this is different from Swift 3?
– Fogmeister
Jun 9 '17 at 14:02
Also, which part of this is different from Swift 3?
– Fogmeister
Jun 9 '17 at 14:02
2
2
You have to add the objc tag to any selectors for Swift 4. This is the correct answer. And your not supposed to edit other people's answers to change their meaning. @Krunal is totally right.
– Unome
Sep 26 '17 at 15:33
You have to add the objc tag to any selectors for Swift 4. This is the correct answer. And your not supposed to edit other people's answers to change their meaning. @Krunal is totally right.
– Unome
Sep 26 '17 at 15:33
|
show 1 more comment
up vote
6
down vote
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)
func tappedButton() {
print("tapped")
}
func tappedButton2(sender: UIButton) {
print("tapped 2")
}
// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton) {
// tapped
}
button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton, _ event: UIEvent) {
// tapped
}
it would have been nicer and more educative if u had an example taking two or three arguments for Swift3 or Swift4 too. Thanks.
– nyxee
Jul 19 '17 at 22:24
add a comment |
up vote
6
down vote
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)
func tappedButton() {
print("tapped")
}
func tappedButton2(sender: UIButton) {
print("tapped 2")
}
// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton) {
// tapped
}
button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton, _ event: UIEvent) {
// tapped
}
it would have been nicer and more educative if u had an example taking two or three arguments for Swift3 or Swift4 too. Thanks.
– nyxee
Jul 19 '17 at 22:24
add a comment |
up vote
6
down vote
up vote
6
down vote
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)
func tappedButton() {
print("tapped")
}
func tappedButton2(sender: UIButton) {
print("tapped 2")
}
// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton) {
// tapped
}
button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton, _ event: UIEvent) {
// tapped
}
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)
func tappedButton() {
print("tapped")
}
func tappedButton2(sender: UIButton) {
print("tapped 2")
}
// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton) {
// tapped
}
button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton, _ event: UIEvent) {
// tapped
}
edited Jul 28 '17 at 6:01
answered Jun 1 '16 at 3:42
John Lee
9615
9615
it would have been nicer and more educative if u had an example taking two or three arguments for Swift3 or Swift4 too. Thanks.
– nyxee
Jul 19 '17 at 22:24
add a comment |
it would have been nicer and more educative if u had an example taking two or three arguments for Swift3 or Swift4 too. Thanks.
– nyxee
Jul 19 '17 at 22:24
it would have been nicer and more educative if u had an example taking two or three arguments for Swift3 or Swift4 too. Thanks.
– nyxee
Jul 19 '17 at 22:24
it would have been nicer and more educative if u had an example taking two or three arguments for Swift3 or Swift4 too. Thanks.
– nyxee
Jul 19 '17 at 22:24
add a comment |
up vote
5
down vote
Create Refresh control using Selector method.
var refreshCntrl : UIRefreshControl!
refreshCntrl = UIRefreshControl()
refreshCntrl.tintColor = UIColor.whiteColor()
refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
atableView.addSubview(refreshCntrl)
//Refresh Control Method
func refreshControlValueChanged(){
atableView.reloadData()
refreshCntrl.endRefreshing()
}
add a comment |
up vote
5
down vote
Create Refresh control using Selector method.
var refreshCntrl : UIRefreshControl!
refreshCntrl = UIRefreshControl()
refreshCntrl.tintColor = UIColor.whiteColor()
refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
atableView.addSubview(refreshCntrl)
//Refresh Control Method
func refreshControlValueChanged(){
atableView.reloadData()
refreshCntrl.endRefreshing()
}
add a comment |
up vote
5
down vote
up vote
5
down vote
Create Refresh control using Selector method.
var refreshCntrl : UIRefreshControl!
refreshCntrl = UIRefreshControl()
refreshCntrl.tintColor = UIColor.whiteColor()
refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
atableView.addSubview(refreshCntrl)
//Refresh Control Method
func refreshControlValueChanged(){
atableView.reloadData()
refreshCntrl.endRefreshing()
}
Create Refresh control using Selector method.
var refreshCntrl : UIRefreshControl!
refreshCntrl = UIRefreshControl()
refreshCntrl.tintColor = UIColor.whiteColor()
refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
atableView.addSubview(refreshCntrl)
//Refresh Control Method
func refreshControlValueChanged(){
atableView.reloadData()
refreshCntrl.endRefreshing()
}
answered Jul 19 '14 at 6:26
Renish Dadhaniya
8,35722143
8,35722143
add a comment |
add a comment |
up vote
5
down vote
Since Swift 3.0 is published, it is even a little bit more subtle to declare a targetAction appropriate
class MyCustomView : UIView {
func addTapGestureRecognizer() {
// the "_" is important
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// since Swift 3.0 this "_" in the method implementation is very important to
// let the selector understand the targetAction
func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {
if tapGesture.state == .ended {
print("TapGesture detected")
}
}
}
add a comment |
up vote
5
down vote
Since Swift 3.0 is published, it is even a little bit more subtle to declare a targetAction appropriate
class MyCustomView : UIView {
func addTapGestureRecognizer() {
// the "_" is important
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// since Swift 3.0 this "_" in the method implementation is very important to
// let the selector understand the targetAction
func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {
if tapGesture.state == .ended {
print("TapGesture detected")
}
}
}
add a comment |
up vote
5
down vote
up vote
5
down vote
Since Swift 3.0 is published, it is even a little bit more subtle to declare a targetAction appropriate
class MyCustomView : UIView {
func addTapGestureRecognizer() {
// the "_" is important
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// since Swift 3.0 this "_" in the method implementation is very important to
// let the selector understand the targetAction
func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {
if tapGesture.state == .ended {
print("TapGesture detected")
}
}
}
Since Swift 3.0 is published, it is even a little bit more subtle to declare a targetAction appropriate
class MyCustomView : UIView {
func addTapGestureRecognizer() {
// the "_" is important
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// since Swift 3.0 this "_" in the method implementation is very important to
// let the selector understand the targetAction
func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {
if tapGesture.state == .ended {
print("TapGesture detected")
}
}
}
edited Nov 20 '16 at 0:17
Suragch
189k113655716
189k113655716
answered Sep 16 '16 at 18:24
LukeSideWalker
3,89911523
3,89911523
add a comment |
add a comment |
up vote
4
down vote
When using performSelector()
/addtarget()/NStimer.scheduledTimerWithInterval()
methods your method (matching the selector) should be marked as
@objc
For Swift 2.0:
{
//...
self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
//...
//...
btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
//...
//...
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
//...
}
@objc private func performMethod() {
…
}
@objc private func buttonPressed(sender:UIButton){
….
}
@objc private func timerMethod () {
….
}
For Swift 2.2,
you need to write '#selector()' instead of string and selector name so the possibilities of spelling error and crash due to that will not be there anymore. Below is example
self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
add a comment |
up vote
4
down vote
When using performSelector()
/addtarget()/NStimer.scheduledTimerWithInterval()
methods your method (matching the selector) should be marked as
@objc
For Swift 2.0:
{
//...
self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
//...
//...
btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
//...
//...
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
//...
}
@objc private func performMethod() {
…
}
@objc private func buttonPressed(sender:UIButton){
….
}
@objc private func timerMethod () {
….
}
For Swift 2.2,
you need to write '#selector()' instead of string and selector name so the possibilities of spelling error and crash due to that will not be there anymore. Below is example
self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
add a comment |
up vote
4
down vote
up vote
4
down vote
When using performSelector()
/addtarget()/NStimer.scheduledTimerWithInterval()
methods your method (matching the selector) should be marked as
@objc
For Swift 2.0:
{
//...
self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
//...
//...
btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
//...
//...
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
//...
}
@objc private func performMethod() {
…
}
@objc private func buttonPressed(sender:UIButton){
….
}
@objc private func timerMethod () {
….
}
For Swift 2.2,
you need to write '#selector()' instead of string and selector name so the possibilities of spelling error and crash due to that will not be there anymore. Below is example
self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
When using performSelector()
/addtarget()/NStimer.scheduledTimerWithInterval()
methods your method (matching the selector) should be marked as
@objc
For Swift 2.0:
{
//...
self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
//...
//...
btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
//...
//...
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
//...
}
@objc private func performMethod() {
…
}
@objc private func buttonPressed(sender:UIButton){
….
}
@objc private func timerMethod () {
….
}
For Swift 2.2,
you need to write '#selector()' instead of string and selector name so the possibilities of spelling error and crash due to that will not be there anymore. Below is example
self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
edited Jun 1 '16 at 11:59
Patrick
1,13531334
1,13531334
answered Mar 17 '16 at 6:48
sschunara
2,0451327
2,0451327
add a comment |
add a comment |
up vote
3
down vote
you create the Selector like below.
1.
UIBarButtonItem(
title: "Some Title",
style: UIBarButtonItemStyle.Done,
target: self,
action: "flatButtonPressed"
)
2.
flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
Take note that the @selector syntax is gone and replaced with a simple String naming the method to call. There’s one area where we can all agree the verbosity got in the way. Of course, if we declared that there is a target method called flatButtonPressed: we better write one:
func flatButtonPressed(sender: AnyObject) {
NSLog("flatButtonPressed")
}
set the timer:
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: Selector("flatButtonPressed"),
userInfo: userInfo,
repeats: true)
let mainLoop = NSRunLoop.mainRunLoop() //1
mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal
In order to be complete, here’s the flatButtonPressed
func flatButtonPressed(timer: NSTimer) {
}
Do you have any source for "Take note that the @selector syntax is gone"?
– winklerrr
Mar 21 at 15:58
add a comment |
up vote
3
down vote
you create the Selector like below.
1.
UIBarButtonItem(
title: "Some Title",
style: UIBarButtonItemStyle.Done,
target: self,
action: "flatButtonPressed"
)
2.
flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
Take note that the @selector syntax is gone and replaced with a simple String naming the method to call. There’s one area where we can all agree the verbosity got in the way. Of course, if we declared that there is a target method called flatButtonPressed: we better write one:
func flatButtonPressed(sender: AnyObject) {
NSLog("flatButtonPressed")
}
set the timer:
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: Selector("flatButtonPressed"),
userInfo: userInfo,
repeats: true)
let mainLoop = NSRunLoop.mainRunLoop() //1
mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal
In order to be complete, here’s the flatButtonPressed
func flatButtonPressed(timer: NSTimer) {
}
Do you have any source for "Take note that the @selector syntax is gone"?
– winklerrr
Mar 21 at 15:58
add a comment |
up vote
3
down vote
up vote
3
down vote
you create the Selector like below.
1.
UIBarButtonItem(
title: "Some Title",
style: UIBarButtonItemStyle.Done,
target: self,
action: "flatButtonPressed"
)
2.
flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
Take note that the @selector syntax is gone and replaced with a simple String naming the method to call. There’s one area where we can all agree the verbosity got in the way. Of course, if we declared that there is a target method called flatButtonPressed: we better write one:
func flatButtonPressed(sender: AnyObject) {
NSLog("flatButtonPressed")
}
set the timer:
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: Selector("flatButtonPressed"),
userInfo: userInfo,
repeats: true)
let mainLoop = NSRunLoop.mainRunLoop() //1
mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal
In order to be complete, here’s the flatButtonPressed
func flatButtonPressed(timer: NSTimer) {
}
you create the Selector like below.
1.
UIBarButtonItem(
title: "Some Title",
style: UIBarButtonItemStyle.Done,
target: self,
action: "flatButtonPressed"
)
2.
flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
Take note that the @selector syntax is gone and replaced with a simple String naming the method to call. There’s one area where we can all agree the verbosity got in the way. Of course, if we declared that there is a target method called flatButtonPressed: we better write one:
func flatButtonPressed(sender: AnyObject) {
NSLog("flatButtonPressed")
}
set the timer:
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: Selector("flatButtonPressed"),
userInfo: userInfo,
repeats: true)
let mainLoop = NSRunLoop.mainRunLoop() //1
mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal
In order to be complete, here’s the flatButtonPressed
func flatButtonPressed(timer: NSTimer) {
}
edited Jul 11 '14 at 19:20
answered Jul 11 '14 at 19:14
Daxesh Nagar
1,2401020
1,2401020
Do you have any source for "Take note that the @selector syntax is gone"?
– winklerrr
Mar 21 at 15:58
add a comment |
Do you have any source for "Take note that the @selector syntax is gone"?
– winklerrr
Mar 21 at 15:58
Do you have any source for "Take note that the @selector syntax is gone"?
– winklerrr
Mar 21 at 15:58
Do you have any source for "Take note that the @selector syntax is gone"?
– winklerrr
Mar 21 at 15:58
add a comment |
up vote
3
down vote
I found many of these answers to be helpful but it wasn't clear how to do this with something that wasn't a button. I was adding a gesture recognizer to a UILabel in swift and struggled so here's what I found worked for me after reading everything above:
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: "labelTapped:")
Where the "Selector" was declared as:
func labelTapped(sender: UILabel) { }
Note that it is public and that I am not using the Selector() syntax but it is possible to do this as well.
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: Selector("labelTapped:"))
add a comment |
up vote
3
down vote
I found many of these answers to be helpful but it wasn't clear how to do this with something that wasn't a button. I was adding a gesture recognizer to a UILabel in swift and struggled so here's what I found worked for me after reading everything above:
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: "labelTapped:")
Where the "Selector" was declared as:
func labelTapped(sender: UILabel) { }
Note that it is public and that I am not using the Selector() syntax but it is possible to do this as well.
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: Selector("labelTapped:"))
add a comment |
up vote
3
down vote
up vote
3
down vote
I found many of these answers to be helpful but it wasn't clear how to do this with something that wasn't a button. I was adding a gesture recognizer to a UILabel in swift and struggled so here's what I found worked for me after reading everything above:
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: "labelTapped:")
Where the "Selector" was declared as:
func labelTapped(sender: UILabel) { }
Note that it is public and that I am not using the Selector() syntax but it is possible to do this as well.
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: Selector("labelTapped:"))
I found many of these answers to be helpful but it wasn't clear how to do this with something that wasn't a button. I was adding a gesture recognizer to a UILabel in swift and struggled so here's what I found worked for me after reading everything above:
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: "labelTapped:")
Where the "Selector" was declared as:
func labelTapped(sender: UILabel) { }
Note that it is public and that I am not using the Selector() syntax but it is possible to do this as well.
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: Selector("labelTapped:"))
answered Feb 14 '16 at 17:58
cynistersix
83011426
83011426
add a comment |
add a comment |
up vote
3
down vote
Using #selector will check your code at compile time to make sure the method you want to call actually exists. Even better, if the method doesn’t exist, you’ll get a compile error: Xcode will refuse to build your app, thus banishing to oblivion another possible source of bugs.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(addNewFireflyRefernce))
}
func addNewFireflyReference() {
gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
}
add a comment |
up vote
3
down vote
Using #selector will check your code at compile time to make sure the method you want to call actually exists. Even better, if the method doesn’t exist, you’ll get a compile error: Xcode will refuse to build your app, thus banishing to oblivion another possible source of bugs.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(addNewFireflyRefernce))
}
func addNewFireflyReference() {
gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
}
add a comment |
up vote
3
down vote
up vote
3
down vote
Using #selector will check your code at compile time to make sure the method you want to call actually exists. Even better, if the method doesn’t exist, you’ll get a compile error: Xcode will refuse to build your app, thus banishing to oblivion another possible source of bugs.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(addNewFireflyRefernce))
}
func addNewFireflyReference() {
gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
}
Using #selector will check your code at compile time to make sure the method you want to call actually exists. Even better, if the method doesn’t exist, you’ll get a compile error: Xcode will refuse to build your app, thus banishing to oblivion another possible source of bugs.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(addNewFireflyRefernce))
}
func addNewFireflyReference() {
gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
}
answered May 20 '16 at 11:31
Swift Developer
357114
357114
add a comment |
add a comment |
up vote
2
down vote
It may be useful to note where you setup the control that triggers the action matters.
For example, I have found that when setting up a UIBarButtonItem, I had to create the button within viewDidLoad or else I would get an unrecognized selector exception.
override func viewDidLoad() {
super.viewDidLoad()
// add button
let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
self.navigationItem.rightBarButtonItem = addButton
}
func addAction(send: AnyObject?) {
NSLog("addAction")
}
add a comment |
up vote
2
down vote
It may be useful to note where you setup the control that triggers the action matters.
For example, I have found that when setting up a UIBarButtonItem, I had to create the button within viewDidLoad or else I would get an unrecognized selector exception.
override func viewDidLoad() {
super.viewDidLoad()
// add button
let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
self.navigationItem.rightBarButtonItem = addButton
}
func addAction(send: AnyObject?) {
NSLog("addAction")
}
add a comment |
up vote
2
down vote
up vote
2
down vote
It may be useful to note where you setup the control that triggers the action matters.
For example, I have found that when setting up a UIBarButtonItem, I had to create the button within viewDidLoad or else I would get an unrecognized selector exception.
override func viewDidLoad() {
super.viewDidLoad()
// add button
let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
self.navigationItem.rightBarButtonItem = addButton
}
func addAction(send: AnyObject?) {
NSLog("addAction")
}
It may be useful to note where you setup the control that triggers the action matters.
For example, I have found that when setting up a UIBarButtonItem, I had to create the button within viewDidLoad or else I would get an unrecognized selector exception.
override func viewDidLoad() {
super.viewDidLoad()
// add button
let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
self.navigationItem.rightBarButtonItem = addButton
}
func addAction(send: AnyObject?) {
NSLog("addAction")
}
answered Jul 12 '14 at 19:33
Michael Peterson
6,42713742
6,42713742
add a comment |
add a comment |
up vote
1
down vote
Change as a simple string naming in the method calling for selector syntax
var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)
After that, type func test().
add a comment |
up vote
1
down vote
Change as a simple string naming in the method calling for selector syntax
var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)
After that, type func test().
add a comment |
up vote
1
down vote
up vote
1
down vote
Change as a simple string naming in the method calling for selector syntax
var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)
After that, type func test().
Change as a simple string naming in the method calling for selector syntax
var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)
After that, type func test().
answered Oct 14 '14 at 4:49
Thar Htet
113
113
add a comment |
add a comment |
up vote
0
down vote
For swift 3
let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)
Function Declaration In Same Class
func test()
{
// my function
}
add a comment |
up vote
0
down vote
For swift 3
let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)
Function Declaration In Same Class
func test()
{
// my function
}
add a comment |
up vote
0
down vote
up vote
0
down vote
For swift 3
let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)
Function Declaration In Same Class
func test()
{
// my function
}
For swift 3
let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)
Function Declaration In Same Class
func test()
{
// my function
}
answered Feb 28 '17 at 6:41
Mustajab Jafry
639
639
add a comment |
add a comment |
up vote
0
down vote
For Swift 3
//Sample code to create timer
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.
func updateTimer(){
//Implemetation
}
repeats:- true/false specifies that timer should call again n again.
add a comment |
up vote
0
down vote
For Swift 3
//Sample code to create timer
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.
func updateTimer(){
//Implemetation
}
repeats:- true/false specifies that timer should call again n again.
add a comment |
up vote
0
down vote
up vote
0
down vote
For Swift 3
//Sample code to create timer
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.
func updateTimer(){
//Implemetation
}
repeats:- true/false specifies that timer should call again n again.
For Swift 3
//Sample code to create timer
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.
func updateTimer(){
//Implemetation
}
repeats:- true/false specifies that timer should call again n again.
answered May 19 at 17:03
CrazyPro007
785
785
add a comment |
add a comment |
up vote
0
down vote
Selector in Swift 4:
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
add a comment |
up vote
0
down vote
Selector in Swift 4:
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
add a comment |
up vote
0
down vote
up vote
0
down vote
Selector in Swift 4:
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
Selector in Swift 4:
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
edited yesterday
Moritz
56.9k19131184
56.9k19131184
answered yesterday
Mahesh Chaudhari
293
293
add a comment |
add a comment |
protected by Community♦ Mar 1 '15 at 21:02
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
11
selector: test()
would calltest
and pass it's return value to theselector
argument.– Michael Dorst
Jun 10 '14 at 4:47