Unrecognized selector sent to instance for unhiding button - swift

import UIKit
class ViewController: UIViewController {
#IBOutlet var continueLabel: UILabel!
#IBOutlet var yesButton: UIButton!
#IBOutlet var noButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
continueLabel.isHidden=true
yesButton.isHidden=true
noButton.isHidden=true // Do any additional setup after loading the view.
}
#IBAction func continueButton(_sender: UIButton) {
continueLabel.isHidden=false
yesButton.isHidden=false
noButton.isHidden=false
}
}
I'm a bit new to IOS development and was practicing how to hide/unhide a button. On the view controller, I can get the button hidden but when I press the button to unhide - The following error is being thrown reason: '-[WelcomeApp.ViewController ContinueButton:]: unrecognized selector sent to instance 0x12b2061d0.
It was basically a button which displayed two options - Yes or No. The Yes button is linked to the next view controller modally.

Function names, as variables, are case sensitive. You seem to have linked to ContinueButton() function, and then to have renamed it to continueButton(). Remove the link and recreate it, and then it should work.

Check the connection inspector as shown in the pic:
You can see a yellow warning, you have to remove this connection first and then again make the connection.

Related

Following Apple 'Food Tracker' tutorial for Xcode - can't get button to change label text

I'm following official iOS Apps tutorial to make a basic Single View Application in Xcode.
Literally all we have done so far is:
Added a label to the UI and set initial text to 'Meal name:'
Added a textbox to the UI
Added a button to the UI
Then we've added some very simple code to the View Controller declaring the label as an outlet and a button action which, when invoked, should change the label's text to Default Text.
My ViewController code is now identical to the tutorial code namely:
class ViewController: UIViewController {
//MARK: Properties
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var mealNameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//MARK: Actions
#IBAction func setDefaultLabelText(_ sender: UIButton) {
mealNameLabel.text = "Default Text"
}
}
The problem is that when I press the button in simulator, I get an error message saying an implicitly unwrapped optional value is nil. (app launches fine, it's just when pressing the button)
As I understand it this means something is blank that can't be, but the only optionals I have are:
The textbox, which isn't blank because before I press the button I write 'biscuits' or something in it
The label text, which isn't blank because it's set to 'Meal name:' by default
I really can't work out what supposedly has a nil value that is triggering this error?
As I understand it this means something is blank that can't be
No , This means you need to make sure outlet
mealNameLabel.text = "Default Text" // here mealNameLabel is nil
is connected to the label in IB

Why would the action not be able to connect to target class NSViewController?

I'm trying to learn Swift, but I seem to have gotten stuck at this (admittedly, probably very simple) problem - the error as follows:
Could not connect action, target class NSViewController does not respond to -(encbutton/decbutton)
Here is my code. I'm designing my interface in the Storyboard and connecting it to the code through #IB(Outlet/Action).
// ViewController.swift
import Cocoa
import Foundation
class TabViewController: NSTabViewController {
// This has been changed from NSViewController to NSTabViewController as I have replaced the initial single-view with a two-tab-view.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
public class EncViewController: NSViewController {
// This is for the first tab, encrypt
#IBOutlet var encdirfield: NSTextField!
#IBOutlet var encpassfield: NSSecureTextField!
#IBOutlet var enclogfield: NSTextField!
#IBOutlet var encbutton: NSButton!
#IBAction func startenc(sender: NSButton) { // here's the problem. the function isn't triggered when the button is pressed
// get values
encdir = encdirfield.stringValue
encpass = encpassfield.stringValue
tarcrypt.enc();
// this is an function that leads to an NSTask that runs a binary I wrote (not related).
// definitely not the cause of the problem because running it independently works fine
}
}
public class DecViewController: NSViewController {
// and this is for the second tab, decrypt
#IBOutlet var decdirfield: NSTextField!
#IBOutlet var decpassfield: NSSecureTextField!
#IBOutlet var declogfield: NSTextField!
#IBOutlet var decbutton: NSButton!
#IBAction func startdec(sender: NSButton) { // here's the same problem, again. the function isn't triggered when the button is pressed
// get values
encdir = encdirfield.stringValue
encpass = encpassfield.stringValue
tarcrypt.dec();
// this is an function that leads to an NSTask that runs a binary I wrote (not related).
// definitely not the cause of the problem because running it independently works fine
}
}
For some reason, upon drawing the scene along with the NSButton, the error message as seen above is generated. What is causing the error, and how do I fix it?
I've figured it out! For anyone else who runs into this problem, here's how to fix it:
It turns out there is a little dropdown under "Custom Class" titled "Module", which is, by default, set to none. Set it to tarcrypt (or whichever available option suits you) and that should fix the errors.
Thanks for all the help!
It sounds as if you connected your UI element to the File's Owner object, which is an instance of NSApplication.
If you haven't done so already, you want to drag a NSObject out of the Object Library palette in Xcode 4 to the margin to the left of your layout. Once you've done that, and have selected it, choose the identity inspector and, in the Class field, enter "WindowController"
Swift 5 and Xcode 13.3
Recently I had the same bug. I solved it by reassigning the viewcontroller class name to the class in my nameclass.swift file and activating the MODULE entry with my project name (following the dropdown menu).

EXC_BAD_INSTRUCTION error

I know that there are a lot of questions about this error, but I haven't found solution for my problem, even if I read most of them. In view controller I'm trying to make my text view displaying top of text, instead of bottom of it. When there is only one textView, then everything works perfectly, but when I try do it with two of the, , then I get EXC_BAD_INSTRUCTION error.
import UIKit
import Social
class ViewController: UIViewController {
#IBOutlet weak var textViewA: UITextView!
#IBOutlet weak var textViewB: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
textViewA.setContentOffset(CGPointZero, animated: false)
textViewB.setContentOffset(CGPointZero, animated: false)
}
If your error is like this
Then it is because you have not hooked up your outlets, to do this go into the storyboard / nib and hook it up like so:
Make sure they are valid by seeing the circles become solid:
This code works for me. I tested it on my own. This is mostly an outlet error, if they aren't connected correctly. It could also be that you have removed an outlet from your code and still have it connected inside your storyboard.

IBOutlet and IBAction in Swift

I connected a IBOutlet and IBAction to my button variable from Interface Builder to my View Controller. How do I add an action method to the button in Swift?
This code doesn't seem to work.
#IBOutlet var OK: UIButton!
#IBAction func OK(sender: UIButton){}
The Objective-C equivalent I found is:
#interface Controller
{
IBOutlet id textField; // links to TextField UI object
}
- (IBAction)doAction:(id)sender; // e.g. called when button pushed
When you attach a button to the viewController and create an action (IBAction) using ctrl-drag, you create a method that looks likes this in Swift (if it doesn't have arguments):
#IBAction func buttonAction() {}
In Objective-C the same thing will look like this:
- (IBAction)buttonAction {}
So that means that #IBAction func OK(sender: UIButton){} is an action method.
If you want to know about the sender argument, I would recommend this SO post.
Edit:
For what you want to do, I create an IBOutlet and an IBAction, that way I can change its attributes with the outlet variable, and have the action side of things with the IBAction, like what you show above:
#IBOutlet var OK: UIButton!
#IBAction func OK(sender: UIButton){}
For example, if I want to hide the button, I would put this code in the viewDidLoad
OK.hidden = true
The OK in that code is for the outlet variable, if I wanted to print "You pressed me" to the console when the button is pressed, I would use this code:
#IBAction func OK(sender: UIButton){
println("You pressed me")
}
Above I am using the action to print "You pressed me" to the console.
A few things to note:
When Swift 2.0 gets released println will get changed to print. Also with you action and outlet, I would suggest giving them differing names, to make it easier to differentiate the two, something like this:
#IBOutlet var okOutlet: UIButton!
#IBAction func okAction(sender: UIButton){}
Along with that, you should use camel case when naming variables, constants, functions, etc.
One way to do it, is control-drag from your button to your viewcontroller and choose action:
If you have connected your button's action, your code should work just fine.
Here are the steps you can follow-
For #IBOutlet
1.Declare Your Interface builder Element property right after class name
class SomeViewController: UIViewController{
#IBOutlet weak var aTextField : UITextField! ////Your Interface builder Element
2.Hook the IB Element From Storyboard.
For #IBAction
1.Write A method inside your class(say SomeViewController)
#IBAction func anAction(_sender : AnyObject){
}
2.Hook the method from Storyboard.
Hope it might helps.
You can simply add action from your storyboard. See the image.

'[UILabel]' does not have a member named 'text'

After I upgrade to Xcode 6.3, it is failed to assign the String into the UILabel. I got the Swift compiler error message "'[UILabel]' does not have a member named 'text'" on UILabel textLabel. Any idea to fix it?
import UIKit
class ViewController: UIViewController {
#IBOutlet var nameTxt: [UITextField]!
#IBOutlet var textLabel: [UILabel]!
override func viewDidLoad() {
super.viewDidLoad()
// 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.
}
#IBAction func changeLabel(sender: UIButton) {
self.textLabel?.text = "Success"
}
}
When we are hooking up labels (or anything else) from the storyboard to our source code, we will get a pop-up menu that looks something like this:
When you click "Connect" here (all I did after getting the pop-up is type "textLabel", everything else is default), it will produce the following line of code:
#IBOutlet weak var textLabel: UILabel!
However, "Outlet" is not the only option for connecting our objects from interface builder to source code.
If we change the "Connection" drop down to select "Outlet Collection", like so:
Then the line of code generated will match exactly the line of code in your question:
#IBOutlet var textLabel: [UILabel]!
We've created an array of labels. This is useful in some cases, but perhaps not what we actually want here.
In order to fix this, we must first be sure to unhook our original connection (otherwise, we'll have runtime exceptions).
So, if you go back to Interface Builder and right click on the label in question, you'll receive a menu that looks like this:
Notice how the label is linked to a "Referencing Outlet Collection", but not a "Referencing Outlet"? This is what we need to fix. So, click the X for that connection to unlink it. Now we can go to the source code and delete the #IBOutlet that was generated.
Now, rehook your label up as a regular "Outlet" and not an "Outlet Collection", and your changeLabel method will work perfectly fine as-is.
When your label is correctly hooked up as an "Outlet" rather than an "Outlet Collection", your interface builder right click menu will look like this:
(Notice the difference between this one and the previous image.)