Selector for different ViewController - ios

Inside an extension for UIButton, I create a button and add its target.
extension UIButton {
convenience init(target: AnyObject) {
self.init(type: .system)
self.addTarget(target, action: Selector("setLang:"), for: .touchUpInside)
}
}
In ViewController, when using the custom init function to create the button, as target, I pass self.
This worked fine before upgrading my code to Swift 3. Now, however, I receive an error when tapping the button saying:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyApp.ViewController setLang:]: unrecognized selector sent to instance xxx
Inside ViewController there is the following function declared that is supposed to be called:
func setLang(button: UIButton) {
//...
}
Any ideas?
Thanks in advance!

i found that solution from apple developer Forums. This may help you.
selectionButton.addTarget(self, action: #selector(SingleQuestionViewController.selected(_:)), for: .touchUpInside)

// try like this , i hope it will work for you.
self.addTarget(target, action: NSSelectorFromString("setLang:"), for: .touchUpInside)

Found the problem. Instead of declaring the function like I did before, I need to do it the following way:
func setLang(_ button: UIButton) {
//...
}
Hope this helps other peeps.

Related

How to properly use selectors in swift 4

I have read many tutorials and even the official Apple documentation and must not understand what is wrong with this code.
var dueDatePicker = UIDatePicker()
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.inputView = dueDatePicker
dueDatePicker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: UIControlEvents.valueChanged)
}
func datePickerValueChanged(_ sender: UIDatePicker){
//Do Stuff
}
At runtime, I click on the textField and the UIDatePicker appears. The function that the selector points to is executed. As soon as I click a UI object outside of the UIDatePicker, the app crashes with this error:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[YourApp.PromiseViewController
dueDateChanged:]: unrecognized selector sent to instance 0x100b12ae0'
What I don't understand is that the "selector" or pointer to the desired function is recognized initially. However, when I trigger another event from another UI Object this exception is thrown.
Why is this happening?
Shouldn't this exception be triggered when datePickerValueChanged() is called initially?
Just add #objc in front of your function
#objc func datePickerValueChanged(_ sender: UIDatePicker){
//Do Stuff
}
The error is telling you that an action with the selector dueDateChanged(_:) has been added as a target action.
More than one target action can be added to a control. Somewhere, maybe in your storyboard or xib, you have another action added to dueDatePicker.

UISwitch value changed action: unrecognized selector sent to class

I am using Xcode 8.1 and swift 3.0. and I am creating a UISwitch programmatically, and the code is:
let preconnectedSwitch = UISwitch()
preconnectedSwitch.isOn = true
preconnectedSwitch.addTarget(self, action: #selector(switchValueDidChange), for: .valueChanged)
func switchValueDidChange() {
print("file:- \(#file) , fucntion:- \(#function), line:- \(#line) ")
// print("\(sender.isOn)")
// UserDefaults.standard.set(true, forKey: Constant.USER_DEFAULT_IS_CONNECTED)
}
But when I change UISwitch value then application crash with this error
I think the problem is that this is a Swift function, not an Objective-C function. Add the #IBAction tag to your function. That will tell the compiler to create an Objective-C function.

How to call a UISwitch touch without using IBaction/InterfaceBuilder

I am trying to call a function whenever my UISwitch is tapped without using an #ib action but am having trouble finding the proper way to do this nothing is seeming to work no matter how i try to call it. I am using everything through code and not storyboard so using an ib property isn't really an option i am trying to use at going about this
I am using this but keep getting the error
terminating with uncaught exception of type NSException
func gameSwitchTapped(){
print("touched")
if gameMuteSwitch.isOn == true {
gameview.saveData.set(false, forKey: gameview.gameMuteKey)
} else {
gameview.saveData.set(true, forKey: gameview.gameMuteKey)}
}
And, elsewhere:
gameMuteSwitch.addTarget(self, action: Selector(("gameSwitchTapped")), for: UIControlEvents.valueChanged)
I think this should do it:
mySwitch.addTarget(self, action: #selector(self.switchChanged(sender:)), forControlEvents: UIControlEvents.ValueChanged)
func switchChanged(sender: UISwitch) {
let value = mySwitch.on
// Do something
}
In Objective C:
[mySwitch addTarget:self action:#selector(action:) forControlEvents:UIControlEventValueChanged];

Unrecognized selector sent to instance Swift 2.1 - Selector issues [duplicate]

I am having problems with trying to get a UIButton to work when the user presses it. I keep getting an error saying: unrecognised selector sent to instance
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: "buttonClick", forControlEvents: UIControlEvents.TouchUpInside)
button.setTitle("Print", forState: UIControlState.Normal)
button.font = UIFont(name: "Avenir Next", size: 14)
button.backgroundColor = UIColor.lightGrayColor()
self.view.addSubview(button)
}
func buttonClick(Sender: UIButton!)
{
myLabelInfo.text = "Hello"
}
For a Swift method such as func buttonClick(Sender: UIButton) what is the correct string to pass to addTarget method for the selector? Is it "buttonClick", "buttonClick:", "buttonClickSender:" or something else?
You're using an invalid method signature for the action. You're supplying buttonClick, but the method has an argument, so the signature should be buttonClick:
button.addTarget(self, action: "buttonClick:", forControlEvents: UIControlEvents.TouchUpInside)
For more information about how to format your selectors, you can refer to the accepted answer in the post linked below. The code used in this post may be Objective-C, but all its lessons can be applied here as well.
Creating a selector from a method name with parameters
And as a side note, this code would also be valid if you used Selector("buttonClicked:") as the action, but you don't have to because string literals can be implicitly cast to the Selector type.
Quoting from Using Swift with Cocoa and Objective-C
An Objective-C selector is a type that refers to the name of an
Objective-C method. In Swift, Objective-C selectors are represented by
the Selector structure. You can construct a selector with a string
literal, such as let mySelector: Selector = "tappedButton:". Because
string literals can be automatically converted to selectors, you can
pass a string literal to any method that accepts a selector.
Swift < 2.2
In Swift < 2.2 the selector method cannot be private (unrecognized selector error).
Prefered (by Apple) notation is the string "methodWithParam:" notation.
Troubleshooting: if you have troubles with NSTimer selector, maybe your class should be a subclass of NSObject.
Swift >= 2.2
Use the #selector notation. Read more here: https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md
For private methods you can use the #objc method modifier, like this: #objc private func timerTick(timer: NSTimer).
No need for subclassing NSObject anymore!
The notation for Swift > 2.2 would be:
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(YourClass.yourMethod(_:)))
Worked for me so far (Xcode 7.3)
You need to pass it an actual Selector. Try using this line instead:
button.addTarget(self, action: Selector("buttonClick:"), forControlEvents: UIControlEvents.TouchUpInside)
You also need the : at the end of the selector name because you have 1 argument. This is the same as typical Obj-C selector naming.
You have missed the colon while specifying selector.so the line should be
button.addTarget(self, action: Selector("buttonClick:"), forControlEvents: UIControlEvents.TouchUpInside)
I had the same problem - the solution ended up being prefixing the method I wanted the button to execute on click with #objc, to expose it in the Objective-C header file and thereby the Objective-C runtime.
Like:
#objc func buttonClick(Sender: UIButton!)
{
myLabelInfo.text = "Hello"
}

NSInvalidArgumentException with button tap detection

The app has a screen in which after giving the inputs, I tap OK button and it should perform input validation, if fine, then navigate and pass data back to the previous screen via protocol/delegate, otherwise, block navigation and display a warning pop-up.
This is my viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: "pushView:", forControlEvents: .TouchUpInside)
}
This is the pushView() function:
func pushView() {
//some codes to validate data and perform navigation
}
When I run the app in simulator, it crash when I tap the button and this is the error message:
2016-04-21 00:12:39.976 ToDo List[1795:1253192] -
[ToDo_List.AddReminderController pushView:]:
unrecognized selector sent to instance 0x7fa13ac16c40
2016-04-21 00:12:39.981 ToDo List[1795:1253192]
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-
[ToDo_List.AddReminderController pushView:]:
unrecognized selector sent to instance 0x7fa13ac16c40'
There may be an issue with sender or selector but I don't know what it exactly means.
When you add a : to your selector/action name like you have here:
button.addTarget(self, action: "pushView:", forControlEvents: .TouchUpInside)
It means that your selector expects a parameter.
Your pushView() function on the other hand, does not include any parameters, so to iOS/UIKit you are referencing two different things.
The solution is to:
either remove the : from your action like so:
button.addTarget(self, action: "pushView", forControlEvents: .TouchUpInside)
or add a parameter to your pushView() function like so:
func pushView(sender: AnyObject)
Fix selector:
button.addTarget(self, action: "pushView", forControlEvents: .TouchUpInside)
For future remember that latest swift 2.2 syntax has some differences in this.
button.addTarget(self, action: #selector(MyClass.pushView), forControlEvents: .TouchUpInside)

Resources