How to properly use selectors in swift 4 - ios

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.

Related

Custom tap recognizer method won’t work if implemented in other class

Is is possible create a global method accesible by any other class to add tap recognizers?
(I'm a beginner in swift)
Context/What I want to achieve:
Since I will be using a lot of tap recognizers (for labels and imageViews) in various views, I want to create a default method that helps me save a few lines of code everytime I need a tap recognizer.
-> Example of what I want
class Toolbox {
static func customTapRecognizerForLabel () {}
static func customTapRecognizerForImage () {}
}
So I can use them in different view controllers:
class ViewControllerOne{
Toolbox.customTapRecognizerForLabel()
}
class ViewControllerTwo{
Toolbox.customTapRecognizerForLabel()
}
What have I done so far?:
What didn't worked:
I created the Toolbox class in Toolbox.swift, tried to call it in other view controllers but it does not work. (Also tried to define a shared instance of the class instead of using static methods but did not worked either)
What worked:
Implementing the methods within the same view controller.
My Toolbox code:
import Foundation
import UIKit
class Toolbox: UIViewController {
static func tapRecognizerforLabel (named label: UILabel, action: Selector) {
let tapGestureForLabel = UITapGestureRecognizer(target: self, action: action)
label.addGestureRecognizer(tapGestureForLabel)
label.isUserInteractionEnabled = true
}
}
How I call it:
class ViewOne: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
Toolbox.tapRecognizerforLabel(named: nameLabel, action: #selector(self.methodAlpha))
}
func methodAlpha() {
print("It's friday my dudes")
}
}
The error I get when touching the label:
2018-07-13 11:08:22.131602-0500 MyApp[20435:1274296]
+[MyApp.Toolbox methodAlpha]: unrecognized selector
sent to class 0x1033c0038
2018-07-13 11:08:22.218289-0500 MyApp[20435:1274296]
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason:
'+[MyApp.Toolbox methodAlpha]: unrecognized selector
sent to class 0x1033c0038'
Why does it work if I implement the tapRecognizerforLabel() method in ViewOne class but it doesn't if I implement it in other class?
Suggestions to achieve what I want in other ways are welcome
Thank you :)
You need to send the target like this
func tapRecognizerforLabel (named label: UILabel, action: Selector,target:Any) {
let tapGestureForLabel = UITapGestureRecognizer(target:target, action: action)
label.addGestureRecognizer(tapGestureForLabel)
label.isUserInteractionEnabled = true
}
The target should contain the implementation of the method inside the selector , since you set self which is Toolbox and it doesn't contain it hence the crash happens , to call
Toolbox.tapRecognizerforLabel(named: nameLabel, action: #selector(self.methodAlpha),target:self)

Selector for different ViewController

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.

Swift 2 TapGesture Error: "unrecognized selector sent to instance"

I've spent 2 days trying to get a single tap to work on a single view (clicking anywhere in the screen). I've tried every variation of fixing this problem I could find. Inside the DVC Class, with #IBActions on everything, renaming the view as an #IBAction etc. I can't get any other error except : "[UIView score:]: unrecognized selector sent to instance"
class DataViewController: UIViewController, UIGestureRecognizerDelegate {
var tappy = UITapGestureRecognizer()
override func viewDidLoad() {
self.tappy = UITapGestureRecognizer(target:self.view, action:"score:")
self.tapView!.addGestureRecognizer(self.tappy)
}
}
func score(sender:UITapGestureRecognizer!) throws {
print("tapped")
}
One problem is that your action: selector, "score:", doesn't correspond to what Objective-C sees when you declare your method as func score(sender:UITapGestureRecognizer!) throws. It sees "score:error:". The simplest solution is to delete throws, since "score:error:" cannot be an action method signature for a tap gesture recognizer.
Moreover, as #dan has pointed out, score is not in self.view but in self. So you also need to change your target:.

UISwipeGestureRecognizer for swipe down keyboard error

I have:
var swipe: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "dismissKeyboard")
swipe.direction = UISwipeGestureRecognizerDirection.Down
self.view.addGestureRecognizer(swipe)
and
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
func dismissKeyboard() {
self.messageTextView.resignFirstResponder()
}
}
When I swipe down on the device I get the error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppName.ViewController dismissKeyboard]: unrecognized selector sent to instance 0x125d06500'
I have a lot of other code in my viewDidLoad plus my messageTextView is inside of a UIView which is in a UITableView. What could be the problem?
Your dismissKeyboard method is nested in your didReceiveMemoryWarning method. This is wrong. You have to declare your dismissKeyboard method as a method of your view controller. Then it should work.
By the way. You say that your messageTextView is embedded in a table view? The UITableView class already offers an opportunity to dismiss the keyboard on swipe. You simply have to set its dismissMode like this:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
Checkout the Documentation for UIScrollViewKeyboardDismissMode.

UISegmentedControl unrecognised seletor

I am trying to add a UISegmentedControl to my app, but it seems that i always get [UISegmentedControl longValue]: unrecognised selector sent to instance 0x22f44e00
This is how i declare my UISegmentedControl
#IBOutlet var speedControl: UISegmentedControl
override func viewDidLoad() {
super.viewDidLoad();
self.speedControl.addTarget(self, action: "selectedSegmentDidChange:", forControlEvents: .ValueChanged);
self.speedControl.selectedSegmentIndex = 0;
}
func selectedSegmentDidChange(segmentedControl: UISegmentedControl) {
NSLog("method called");
}
How do i solve this?
I noticed none of my codes i wrote was causing the error, but it was the storyboard itself.
I right-clicked on the UISegmentControl, I noticed there were weird connections made to unknown source. I deleted them by pressing the "X", and everything is fine now

Resources