Swift unrecognized selector sent to instance - What am I missing? - ios

I can't see why the following button is throwing an error:2014-08-13 00:29:57.674 view1[26581:842344] -[view1.ViewController buttonAction:]: unrecognized selector sent to instance 0x797731c0
2014-08-13 00:29:57.677 view1[26581:842344] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[view1.ViewController buttonAction:]: unrecognized selector sent to instance 0x797731c0'. Any help appreciated. Many Thanks
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
func buttonAction(sender:UIButton)
{
println("Button tapped")
}
let windowsize = CGRect(x: 0, y: 0, width: 320, height: 480)
let labelsize = CGRect(x: 0, y: 200, width: 140, height: 60)
let myButton = UIButton(frame: CGRectMake(0, 0, 100, 100))
let myView = UIView(frame: windowsize)
let viewwidth = myView.frame.width
let spaceleft = (viewwidth - labelsize.width)/2
myView.backgroundColor = UIColor .blackColor()
let myLabel = UILabel(frame:labelsize)
myLabel.frame.origin.x = spaceleft
myLabel.text = "Hello"
myLabel.font = UIFont(name: "Chalkduster", size: 22)
myLabel.textColor = UIColor .whiteColor()
myLabel.textAlignment = NSTextAlignment.Center
myLabel.backgroundColor = UIColor .redColor()
//myView.addSubview(myButton)
myView.addSubview(myLabel)
self.view.addSubview(myView)
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(100, 100, 100, 50)
button.backgroundColor = UIColor.greenColor()
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
myView.addSubview(button)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Your buttonAction target is nested inside your viewDidLoad() method. Move it outside and it should be reachable.
class ViewController: UIViewController {
func buttonAction(sender:UIButton)
{
println("Button tapped")
}
override func viewDidLoad() {
super.viewDidLoad()
// ...
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
// ...
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
myView.addSubview(button)
}
}

Related

Why is my button not working in Swift Playgrounds?

I am trying to make a playground and I have a button that says "Let's play!" and moves into a new view controller.
I looked at the code from this website and put it into my code:
http://lab.dejaworks.com/ios-swift-3-playground-uibutton-action/
This is all of my code (like, all of it):
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
//Introduction
let view = UIView()
view.backgroundColor = .red
//title
func labelCool() {
let label = UILabel()
label.frame = CGRect(x: 50, y: 300, width: 400, height: 100)
label.text = "Add-Add - A Wonderful Game!"
//label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
label.numberOfLines = 3
label.font = UIFont(name: "HelveticaNeue-Bold", size: 30)
UILabel.animate (withDuration: 10.0, animations:{
label.textColor = .black
})
UILabel.animate(withDuration: 5.0, animations:{
label.textColor = .blue
})
view.addSubview(label)
}
labelCool()
//subtitle
let subtitle = UILabel()
subtitle.frame = CGRect(x: 50, y: 400, width: 200, height: 50)
subtitle.text = "Curated and Created by Yours Truly, Adit Dayal!"
subtitle.numberOfLines = 4
self.view = view
view.addSubview(subtitle)
}
override func viewDidLoad() {
class Responder : NSObject {
#objc func action() {
print("Yay!")
}
}
let responder = Responder()
//next page
let button = UIButton(frame : CGRect(x: 0, y: 500, width: 200, height: 50))
button.setTitle("Let's Play!", for: .normal)
button.backgroundColor = .blue
button.addTarget(responder, action: #selector(Responder.action), for: .touchUpInside)
view.addSubview(button)
}
}
class gameViewController: UIViewController {
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
For now, I just want the button to display "Yay!" when clicked, but it is doing nothing!
Does anyone know why? (I'm on a bit of a time constraint)
Thank you so much,
Adit Dayal
Your Responder class is inside the viewDidLoad() function put the class outside like so
class Responder : NSObject {
#objc func action() {
print("Yay!")
}
}
override func viewDidLoad() {
let responder = Responder()
//next page
let button = UIButton(frame : CGRect(x: 0, y: 500, width: 200, height: 50))
button.setTitle("Let's Play!", for: .normal)
button.backgroundColor = .blue
button.addTarget(responder, action: #selector(responder.action), for: .touchUpInside)
view.addSubview(button)
}
The problem is that you are creating the responder object inside the viewDidLoad, as a local variable; this cause the object to be destroyed when the function ends (but we want that object alive even after). You have to retain that object, so instead of creating a local variable, create an instance variable by simply saving it as a class scope:
class Responder : NSObject {
#objc func action() {
print("Yay!")
}
}
let responder = Responder() // this is now outside the viewDidLoad, so it's an instance variable
override func viewDidLoad() {
//next page
let button = UIButton(frame : CGRect(x: 0, y: 500, width: 200, height: 50))
button.setTitle("Let's Play!", for: .normal)
button.backgroundColor = .blue
button.addTarget(responder, action: #selector(Responder.action), for: .touchUpInside)
view.addSubview(button)
}

Button playground swift

I'm just trying to add a button actions which create a view.
Someone can help me?
import UIKit
import PlaygroundSupport
class ViewController : UIViewController {
override func viewDidLoad() {
view.backgroundColor = UIColor.black
navigationController?.isNavigationBarHidden = true
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.backgroundColor = UIColor.white
view.addSubview(button)
class Button: ViewController {
#objc func fbtn () {
let newView = UIView()
newView.backgroundColor = UIColor.yellow
view.addSubview(newView)
}
}
button.addTarget(button, action: #selector(Button.fbtn), for: .touchUpInside)
}
}
PlaygroundPage.current.liveView = UINavigationController(rootViewController: ViewController())
There seems to be no point to your nested Button class. Just make fbtn a function of your ViewController class. And make self the target of the button action.
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
navigationController?.isNavigationBarHidden = true
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.backgroundColor = .white
view.addSubview(button)
button.addTarget(self, action: #selector(fbtn), for: .touchUpInside)
}
#objc func fbtn() {
let newView = UIView()
newView.backgroundColor = .yellow
view.addSubview(newView)
}
}
Also, give newView a useful frame inside the fbtn function.

Swift 3: How do I increase a variable being displayed as a UILabel, and then update the UILabel programmatically?

I have a label that is supposed to display a score, and a button that is supposed to increase that score each time it's pressed. My problem is that I get an error no matter where I put my function.
If I have the function above the viewDidLoad class then I get an error because it comes before my label, but if I put it anywhere inside viewDidLoad I get an error because I can't call a local function, and if I put it anywhere after, then my button calling the function comes before the function.
Where am I supposed to put these things? Is there a better way of doing this all together? This was supposed to be so simple...
import UIKit
class ViewController: UIViewController {
let phrase = "Your score: "
var increasingNum = 0
func scoreGoUp (sender: UIButton){
increasingNum += 1
label.text = "\(phrase) \(increasingNum)"
}
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: CGRect(x: self.view.frame.size.width / 2 - 100, y: self.view.frame.size.height / 2 - 10, width: 200, height: 20))
label.textAlignment = .center
label.text = "\(phrase) \(increasingNum)"
self.view.addSubview(label)
let button = UIButton(frame: CGRect(x: self.view.frame.size.width / 2 - 150, y: 100, width: 300, height: 50))
button.backgroundColor = UIColor.cyan
button.addTarget(self, action: #selector(scoreGoUp), for: .touchUpInside)
self.view.addSubview(button)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I have modified your code. Hope this help you.
class ViewController: UIViewController {
var label:UILabel!
let phrase = "Your score: "
var increasingNum = 0
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel(frame: CGRect(x: self.view.frame.size.width / 2 - 100, y: self.view.frame.size.height / 2 - 10, width: 200, height: 20))
label.textAlignment = .center
label.text = "\(phrase) \(increasingNum)"
self.view.addSubview(label)
let button = UIButton(frame: CGRect(x: self.view.frame.size.width / 2 - 150, y: 100, width: 300, height: 50))
button.backgroundColor = UIColor.cyan
button.addTarget(self, action: #selector(scoreGoUp), for: .touchUpInside)
self.view.addSubview(button)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func scoreGoUp (sender: UIButton){
increasingNum += 1
label.text = "\(phrase) \(increasingNum)"
}
}
Here is the output
You need to define your label outside of viewDidLoad (like increasingNum), at the moment, your label variable is only visible inside viewDidLoad
var label:UILabel!
I have cleared up your code. The problem was that, you are not keeping track of you UILabel. Just declare a label to be visible in the class.
import UIKit
class ViewController: UIViewController {
let phrase = "Your score: "
var increasingNum = 0
var label: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: CGRect(x: self.view.frame.size.width / 2 - 100, y: self.view.frame.size.height / 2 - 10, width: 200, height: 20))
label.textAlignment = .center
label.text = "\(phrase) \(increasingNum)"
self.view.addSubview(label)
self.label = label
let button = UIButton(frame: CGRect(x: self.view.frame.size.width / 2 - 150, y: 100, width: 300, height: 50))
button.backgroundColor = UIColor.cyan
button.addTarget(self, action: #selector(scoreGoUp), for: .touchUpInside)
self.view.addSubview(button)
}
func scoreGoUp (sender: UIButton){
increasingNum += 1
self.label?.text = "\(phrase) \(increasingNum)"
}
}
Hope this helps!

Unrecognized selector sent to instance, Tap Gesture Recognizer [duplicate]

I can't see why the following button is throwing an error:2014-08-13 00:29:57.674 view1[26581:842344] -[view1.ViewController buttonAction:]: unrecognized selector sent to instance 0x797731c0
2014-08-13 00:29:57.677 view1[26581:842344] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[view1.ViewController buttonAction:]: unrecognized selector sent to instance 0x797731c0'. Any help appreciated. Many Thanks
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
func buttonAction(sender:UIButton)
{
println("Button tapped")
}
let windowsize = CGRect(x: 0, y: 0, width: 320, height: 480)
let labelsize = CGRect(x: 0, y: 200, width: 140, height: 60)
let myButton = UIButton(frame: CGRectMake(0, 0, 100, 100))
let myView = UIView(frame: windowsize)
let viewwidth = myView.frame.width
let spaceleft = (viewwidth - labelsize.width)/2
myView.backgroundColor = UIColor .blackColor()
let myLabel = UILabel(frame:labelsize)
myLabel.frame.origin.x = spaceleft
myLabel.text = "Hello"
myLabel.font = UIFont(name: "Chalkduster", size: 22)
myLabel.textColor = UIColor .whiteColor()
myLabel.textAlignment = NSTextAlignment.Center
myLabel.backgroundColor = UIColor .redColor()
//myView.addSubview(myButton)
myView.addSubview(myLabel)
self.view.addSubview(myView)
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(100, 100, 100, 50)
button.backgroundColor = UIColor.greenColor()
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
myView.addSubview(button)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your buttonAction target is nested inside your viewDidLoad() method. Move it outside and it should be reachable.
class ViewController: UIViewController {
func buttonAction(sender:UIButton)
{
println("Button tapped")
}
override func viewDidLoad() {
super.viewDidLoad()
// ...
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
// ...
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
myView.addSubview(button)
}
}

iOS Swift - Function from other class doesn't run

I want to create a class with a blurred view that should appear on the existing view if any problems occurred. Here is the code:
import Foundation
import UIKit
class checkProblems{
let effectView:UIVisualEffectView = UIVisualEffectView (effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
var view: UIView
let label = UILabel()
let retry = UIButton()
init(view: UIView){
self.view = view
self.check()
}
func check(){
effectView.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
label.frame = CGRectMake(0, (self.view.frame.height/2)-20, self.view.frame.width, 40)
label.text = "Server connection problems."
label.textAlignment = NSTextAlignment.Center
label.textColor = UIColor.darkGrayColor()
label.font = UIFont (name: "HelveticaNeue-Light", size: 20)
retry.frame = CGRectMake(0, (self.view.frame.height/2)+10, self.view.frame.width, 40)
retry.setTitle("Tap here to retry.", forState: UIControlState.Normal)
retry.addTarget(self, action: "pressed:", forControlEvents: .TouchUpInside)
self.view.addSubview(effectView)
effectView.addSubview(label)
effectView.addSubview(retry)
}
func pressed(sender: UIButton!){
println("here")
}
}
And this is how I call it on the view controller:
let checkObject = checkProblems(view: view)
Everything works fine until I press the button "Tap here to retry".
Then, my app crashes.
I think you break the MVC-Pattern with your approach. Followed by problems with the corresponding references for the addAction method.
Please add all view-creating or -alternating code to the viewController. This will make your app a lot easier to understand.
I changed your code to correctly implement the MVC-Pattern (and making it runnable altogether)
import UIKit
class ViewController: UIViewController {
let effectView:UIVisualEffectView = UIVisualEffectView (effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
let label = UILabel()
let retry = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
check()
}
func check(){
effectView.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
label.frame = CGRectMake(0, (self.view.frame.height/2)-20, self.view.frame.width, 40)
label.text = "Server connection problems."
label.textAlignment = NSTextAlignment.Center
label.textColor = UIColor.darkGrayColor()
label.font = UIFont (name: "HelveticaNeue-Light", size: 20)
retry.frame = CGRectMake(0, (self.view.frame.height/2)+10, self.view.frame.width, 40)
retry.backgroundColor = .blueColor()
retry.setTitle("Tap here to retry.", forState: UIControlState.Normal)
retry.addTarget(self, action: "pressed:", forControlEvents: UIControlEvents.TouchUpInside)
effectView.addSubview(label)
effectView.addSubview(retry)
view.addSubview(effectView)
}
func pressed(sender: UIButton){
println("here")
}
}
In addition to your comment, I show you an example of a MVC-conserving approach, which will subclass UIViewController. You can then load your checkProblems class with presentViewController:
Code from the calling VC:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let checkProblemsVC = CheckProblemsViewController()
presentViewController(checkProblemsVC, animated: true, completion: nil)
}
}
And the new subclassed CheckProblemsViewController:
import UIKit
class CheckProblemsViewController: UIViewController {
let effectView:UIVisualEffectView = UIVisualEffectView (effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
let label = UILabel()
let retry = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
check()
}
func check(){
effectView.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
label.frame = CGRectMake(0, (self.view.frame.height/2)-20, self.view.frame.width, 40)
label.text = "Server connection problems."
label.textAlignment = NSTextAlignment.Center
label.textColor = UIColor.darkGrayColor()
label.font = UIFont (name: "HelveticaNeue-Light", size: 20)
retry.frame = CGRectMake(0, (self.view.frame.height/2)+10, self.view.frame.width, 40)
retry.backgroundColor = .blueColor()
retry.setTitle("Tap here to retry.", forState: UIControlState.Normal)
retry.addTarget(self, action: "pressed:", forControlEvents: UIControlEvents.TouchUpInside)
effectView.addSubview(label)
effectView.addSubview(retry)
view.addSubview(effectView)
}
func pressed(sender: UIButton){
println("here")
}
}

Resources