I'm creating a button in swift 2 and when I select it, I get signal SIGABRT and the app crashes. Heres the code:
let button = UIButton()//(type: UIButtonType.System) as UIButton!
button.setTitle("button", forState: .Normal)
button.setTitleColor(UIColor.blueColor(), forState: .Normal)
button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
button.frame = CGRectMake(100, 100, 100, 100)
self.view.addSubview(button)
func buttonPressed(sender: UIButton!) {
print("ButtonIsSelected")
}
It brings me to AppDelegate.swift and in the middle of the NSLog it says: unrecognized selector sent to instance...
Please help. Anton
func buttonPressed(sender: UIButton!) {
print("ButtonIsSelected")
}
This method must be in your class body not in function body . As I guess you have done.
Related
I have a setup that brings up a date picker upon clicking of a button. I have two a function that changes the value of a button upon selecting a date. In addition, I also have a function that should help dismiss the date picker when I press the done button. However, I continue to get an error stating 'unrecognized selector sent to instance'. Any idea what I could have possibly done wrong
#IBOutlet weak var dueDateSelector: UIButton!
#IBOutlet weak var myPickerView: UIPickerView!
#IBAction func changeDueDate(_ sender: Any) {
//Create the view
let inputView = UIView(frame: CGRect(x:0, y:420, width: self.view.frame.width, height: 240))
var datePickerView : UIDatePicker = UIDatePicker(frame: CGRect(x:0, y:40, width:0, height:0))
datePickerView.datePickerMode = UIDatePickerMode.date
inputView.addSubview(datePickerView) // add date picker to UIView
let doneButton = UIButton(frame: CGRect(x:270, y:0, width:100, height:50))
doneButton.setTitle("Done", for: UIControlState.normal)
doneButton.setTitle("Done", for: UIControlState.highlighted)
doneButton.setTitleColor(UIColor.black, for: UIControlState.normal)
doneButton.setTitleColor(UIColor.gray, for: UIControlState.highlighted)
inputView.addSubview(doneButton) // add Button to UIView
doneButton.addTarget(self, action: "doneButton:", for: UIControlEvents.touchUpInside) // set button click event
datePickerView.addTarget(self, action: Selector("handleDatePicker:"), for: UIControlEvents.valueChanged)
view.addSubview(inputView)
handleDatePicker(sender: datePickerView) // Set the date on start.
}
#objc func handleDatePicker(sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
dueDateSelector.setTitle(dateFormatter.string(from: sender.date), for: .normal)
}
#objc func doneButton(sender:UIButton)
{
dueDateSelector.resignFirstResponder() // To resign the inputView on clicking done.
}
This is due to an inconsistency in naming methods between Swift and Objective C. This is also why you should write selectors with the #selector syntax instead of using strings. You need to change this line:
datePickerView.addTarget(self, action: Selector("handleDatePicker:"), for: UIControlEvents.valueChanged)
Selectors are an Objective C thing. If you write it in strings, then you need to write it in an Objective C fashion. In your code, handleDatePicker is not actually called handleDatePicker: in Objective C. It is probably something like handleDatePickerWithSender:. This is because you have a sender argument there, and that becomes the WithSender part in the eyes of Objective C.
This is why we like to write selectors like this:
#selector(handleDatePicker)
No need to worry about parameters, just the method name.
datePickerView.addTarget(self, action: #selector(handleDatePicker), for: UIControlEvents.valueChanged)
Also, this line needs to be changed as well:
doneButton.addTarget(self, action: "doneButton:", for: UIControlEvents.touchUpInside)
It should be:
doneButton.addTarget(self, action: #selector(doneButton), for: UIControlEvents.touchUpInside)
I think you are having problem here,
#objc func doneButton(sender:UIButton)
{
dueDateSelector.resignFirstResponder() // To resign the inputView on clicking done.
}
here dueDateSelector is button which is not having any method called resignFirstResponder() so that's why you are getting error
instead you can do this,
#objc func doneButton(sender:UIButton)
{
//remove or hide the input view
}
You can also check that whether current component having this method or not with,
if dueDateSelector.canResignFirstResponder()
{
}
You are using deprecated string selector syntax:
doneButton.addTarget(self, action: "doneButton:", for: UIControlEvents.touchUpInside)
Should be replaced with:
doneButton.addTarget(self, action: #selector(doneButton(sender:)),
for: .touchUpInside)
It's also applied to the other method in your code:
datePickerView.addTarget(self, action: #selector(handleDatePicker(sender:)),
for: .valueChanged)
doneButton.addTarget(self, action:#selector(self.doneButton(_:)) , for:
UIControlEvents.touchUpInside) // set button click event
datePickerView.addTarget(self, action: #selector(self.handleDatePicker(_:)), for: UIControlEvents.valueChanged)
if self wont work use class reference like yourClass().doneButton
How do I add a IBAction to a button programmatically?
button.addTarget(self, action: Selector(("buttonAction:")), for:
.touchUpInside)
func buttonAction(sender: Any) {
print("test")
}
That gives me an "Thread 1: signal SIGABRT" error.
Swift 4 version:
button.addTarget(self, action: #selector(action(sender:)), for: .touchUpInside)
#objc private func action(sender: Button) {
print("test")
}
I want to add an action to a button, but I heard that the code below does not work. Does anyone know the way to add an action to a button.
button.addTarget(self, action: Selector("function:"), forControlEvents: .TouchUpInside)
Here is the code
I am using Xcode 7.3.1
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRectMake(100, 80, 30, 30))
func pressed(sender: UIButton!) {
print("button pressed")
}
button.backgroundColor = UIColor.redColor()
button.addTarget(self, action: #selector(pressed(_:)), forControlEvents: .TouchUpInside)
self.view.addSubview(button)
}
I'm guessing that your problem is with the Selector part.
In Swift 2.2 the selector syntax was changed so you now get a compile time check for your selectors. You can read more about that here.
To answer your question, this syntax:
button.addTarget(self, action: #selector(function(_:)), forControlEvents: .TouchUpInside)
should make you and - more importantly in this case (sorry :)) - the compiler happy.
Update (after looking at the code you provided)
You need to move the pressed function outside of your viewDidLoad function so that it is a separate function.
So your code ends up looking like this:
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRectMake(100, 80, 30, 30))
button.backgroundColor = UIColor.redColor()
button.addTarget(self, action: #selector(pressed(_:)), forControlEvents: .TouchUpInside)
self.view.addSubview(button)
}
func pressed(sender: UIButton) { //As ozgur says, ditch the !, it is not needed here :)
print("button pressed")
}
And that seems to work, I can see button pressed in my console now at least.
Hope that helps you.
Try These
button.addTarget(self, action: #selector(buttonAction), forControlEvents: UIControlEvents.TouchUpInside)
your method
func buttonAction (sender:UIButton)
{
}
I used the following tutorial to programmatically create a UIBarButtonItem in Swift, but the icon isn't properly aligned to the border. Here's the code for the button. Can anyone tell me how to modify the code below to properly align the UIBarButtonItem Image?
The 1st image shows the location of the programmatically created uibarbuttonitem, and the 2nd image shows the uibarbuttonitem created from storyboard. I want the programmatically created uibarbuttonitem to look like uibarbuttonitem created using storyboard. Thanks for the help!
var button: UIButton = UIButton()
button.setImage(UIImage(named: "leftArrow.png"), forState: .Normal)
button.frame = CGRectMake(0, 0, 40, 40)
button.targetForAction("actioncall:", withSender: nil)
var leftBarButtonItem:UIBarButtonItem = UIBarButtonItem()
leftBarButtonItem.customView = button
self.navigationItem.leftBarButtonItem = leftBarButtonItem
Also, how do I properly set the action for when the uibarbuttontiem is pressed? I tried the following but it's never called.
func actioncall(sender: AnyObject){
println("action")
}
Edit 1: I updated the code as follows thanks to agy's response.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
if (cond){
var button: UIButton = UIButton()
button.setImage(UIImage(named: "leftArrow.png"), forState: .Normal)
button.frame = CGRectMake(0, 0, 40, 40)
button.addTarget(self, action: "actioncall:", forControlEvents: .TouchUpInside)
var leftBarButtonItem:UIBarButtonItem = UIBarButtonItem()
leftBarButtonItem.customView = button
var negativeSpacer:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = -20; // set the value you need
self.navigationItem.leftBarButtonItems = [negativeSpacer,leftBarButtonItem]
}
}
func actioncall(sender: UIButton!){
println("action")
}
but the action still fails. The app crashes when I press the uibarbuttontiem and I get the following error message
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppName.ProfileViewController actioncall:]: unrecognized selector sent to instance 0x7a07a470'
What's the correct function for the action?
Edit 2: The actioncall is in the same class as where I'm creating the UIBarButtonItem. I'm setting the leftbarbutton on viewwillappear because depending on who views this viewcontroller, the option to go back will replace the previous option located on the leftbarbutton.
Try adding a negative spacer, and change the method targetForAction for addTarget:
var button: UIButton = UIButton()
button.setImage(UIImage(named: "leftArrow.png"), forState: .Normal)
button.frame = CGRectMake(0, 0, 40, 40)
button.addTarget(self, action: "actioncall:", forControlEvents: .TouchUpInside)
var leftBarButtonItem:UIBarButtonItem = UIBarButtonItem()
leftBarButtonItem.customView = button
var negativeSpacer:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = -5; // set the value you need
self.navigationItem.leftBarButtonItems = [negativeSpacer,leftBarButtonItem]
func actioncall(sender: UIButton!){
print("Called")
}
I have button and method
switchViewButton = UIButton.buttonWithType(.System) as? UIButton
switchViewButton!.frame = CGRectMake(15, 25, 50, 50)
switchViewButton!.setTitle("sss", forState: .Normal)
switchViewButton!.addTarget(self, action: "switchViewFunc", forControlEvents: .TouchUpInside)
switchViewButton!.backgroundColor = UIColor.redColor()
switchViewButton!.layer.cornerRadius = 25
topView.addSubview(switchViewButton)
#IBAction func switchViewFunc(sender : AnyObject){
println("Button was clicked", sender)}
This method crashes app with reason "unrecognized selector sent to instance"
I have another button and method just like this, and it's work perfect. If I'm delete (sender : AnyObject) it works. I cann't understand what is wrong
Add action this way (pay attention to ":"
switchViewButton!.addTarget(self, action: "switchViewFunc:", forControlEvents: .TouchUpInside)
#IBAction func switchViewFunc(sender : AnyObject){
println("Button was clicked", sender)} - ?????
Try this:
func switchViewFunc(sender : UIButton!){
println("Button was clicked", sender)
}
#IBAction and an argument are not needed.
func switchViewFunc(){
println("Button was clicked", sender)
}