How to get label name from Button? - ios

I am new in Swift and I am making a simple calculator where I wan't to detect a button which was pressed and my code is below.
#IBAction func ButtonTapped(TheButton : UIButton){
println(TheButton.titleLabel.text)
}
But It Shows me error like "UILabel? Does not have a member a named text"
and it tell me to modify code like this
println(TheButton.titleLabel?.text)
This Prints Optional("1") (1 is my button name)
So anybody can help me why this is happend to me and how can I print my button name without Optional?

If you are sure that titleLabel is not nil:
println(TheButton.titleLabel!.text)
else
if let text = TheButton.titleLabel?.text {
println(text)
}

More simply, you could just do:
let titleValueString = TheButton.currentTitle!
If the button's title is not nil, the exclamation point (!) will implicitly unwrap the optional (currentTitle without the exclamation point) and you will have a string value for the title of the button in your constant, titleValueString

The top answer no longer works. Here is the corrected version for Swift 2.2:
If you are sure that titleLabel is not nil:
print(TheButton.titleLabel!.text!)
If you are not:
if let text = TheButton.titleLabel?.text {
print(text)
}

for Swift 5
There are many ways to do this but the easiest is just what I mentioned below:
#IBAction func keyPressed(_ sender:UIButton){
print(sender.currentTitle!)
}

Swift 5: I found this much cleaner
#IBAction func ButtonTapped(_ sender : UIButton){
guard let btnTxt = sender.titleLabel!.text else{
return
}
print(btnTxt)
// now you can make use of this variable
if btnTxt == "something" {
.......
}
}

Related

pass a UIButton into a function

I have a function that runs when a button is pressed.
Inside that function is another function.
I would like to pass the pressed button into the inner function so that I can change the text of the button depending on stuff in that inner function.
#IBAction func newItem(sender: AnyObject) {
let urlFetch:String = urlField.text!
self.service.createNewItem(urlFetch, I_WANT_BUTTON_HERE)
}
How do I pass the button into the function?
If it helps this is the function that I am passing it to:
func createNewItem(item_url: String, plus_button: UIButton) {
let dataDictionary = ["url" : item_url]
self.post("item/create", data: dataDictionary).responseJSON { (response) -> Void in
plus_button.titleLabel!.text = "success"
}
}
Later I will add an if statement that changes the text depending on what the response is.
The object passed into newItem method is actually the button you tapped so you can securely convert the type of parameter sender into UIButton like below:
#IBAction func newItem(sender: UIButton) {
...
self.service.createNewItem(urlFetch, sender)
}
There is also one thing though. Setting the text of titleLabel is not the right way of updating the title of button. You should be using setTitle:forState instead:
func createNewItem(item_url: String, plus_button: UIButton) {
...
plus_button.setTitle("success", forState: .Normal)
}
Instead of sending AnyObject as parameter in the newItem function, pass a UIButton.
#IBAction func newItem(sender: UIButton) {
let urlFetch:String = urlField.text!
self.service.createNewItem(urlFetch, sender)
}

How to pass a string with a function?

I want to have a function that gives the time. I already have a time label in my app that displays the current time, and updates every second. But I want to have a label that only holds the time a button is pressed. There are multiple buttons that store the current time in different labels.
func fetchTime() -> String {
return NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: NSDateFormatterStyle.NoStyle, timeStyle: NSDateFormatterStyle.MediumStyle)
}
#IBAction func clockIn(sender: AnyObject) {
testLabel = fetchTime()
The error I get is "Use of unresolved identifier 'fetch time'
I had this working awhile ago, but I accidentally deleted the app...
I also tried
func fetchTime(label: String) -> String{
label.text = NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: NSDateFormatterStyle.NoStyle, timeStyle: NSDateFormatterStyle.MediumStyle)
}
But that failed badly, and I understand why, just not how to do it correctly.
Here is your both tried working version...
version1
func fetchTime(label: UILabel){
label.text = "its with parameter"
}
#IBAction func btnClicked(sender: UIButton) {
fetchTime(label)
}
And the another one...
func fetchTime() -> String {
return "without parameter"
}
#IBAction func btnClicked(sender: UIButton) {
lbl.text = fetchTime()
}
What you want to fetch is a string and that should be assigned as a label's text value.
Update
testLabel = fetchTime()
to
testlabel.text = fetchTime()
This will update the label's value each time when button is pressed.
The picture you posted was helpful. You've declared the fetchTime function inside the scope of the updateTime function. You'll notice the curly braces for updateTime wrap around fetchTime.
This being the case you can not call fetchTime outside of updateTime. Move fetchTime out of updateTime and you'll be ok. That is why you are seeing the undefined function error message.

Calling IBAction from another method without parameter

In my program 2 functions (IBAction player.Move(UIButton) and autoMove()) are supposed to be called by turns till all of the fields (UIButtons) has been clicked. For this I've created a function play(). However, I don't know how can I put the IBAction playerMove inside of play() function, because I need no parameter here.
I've found some answers and tried self.playerMove(nil) and self.playerMove(self) but it doesn't work.
import UIKit
class ViewController: UIViewController {
#IBOutlet var cardsArray: Array<UIButton> = []
var randomCard = 0
override func viewDidLoad() {
super.viewDidLoad()
self.play()
// Do any additional setup after loading the view, typically from a nib.
}
func play () {
self.autoMove()
self.playerMove(self) // <----- here is my problem
}
#IBAction func playerMove(sender: UIButton) {
switch (sender) {
case self.cardsArray[0]:
self.cardPressedAll(0)
case self.cardsArray[1]:
self.cardPressedAll(1)
case self.cardsArray[2]:
self.cardPressedAll(2)
case self.cardsArray[3]:
self.cardPressedAll(3)
default: break
}
}
func cardPressedAll (cardNumber: Int) {
self.cardsArray[cardNumber].enabled = false
self.cardsArray[cardNumber].setBackgroundImage(UIImage(named: "cross"), forState: UIControlState.Normal)
self.cardsArray.removeAtIndex(cardNumber)
}
func autoMove (){
self.randomCard = Int(arc4random_uniform(UInt32(self.cardsArray.count)))
self.cardsArray[self.randomCard].enabled = false
self.cardsArray[self.randomCard].setBackgroundImage(UIImage(named: "nought"), forState: UIControlState.Normal)
self.cardsArray.removeAtIndex(self.randomCard)
}
}
Either you have to call playerMove: without a button, in which case you have to declare the sender parameter as an optional. Like:
#IBAction func playerMove(sender: UIButton?) {
UIButton means that you have to pass in a button. nil is not a button, but with UIButton?, that is to say Optional<UIButton>, nil is a valid value meaning the absence of a button.
Or you have to work out which button you want to pass to playerMove: to make it do what you want. Sit down and work out what you want to have happen, and what the code needs to do in order to make that happen.
Try
self.playerMove(UIButton())
Your func playerMove has parameters expecting sender to be of type UIButton, self or nil would be an unexpected object.
Edit:
You could us optional parameters by placing ?. This would allow you to call self.playerMove(nil) if needed.
#IBAction func playerMove(sender: UIButton?) {
if sender != nil {
//handle when button is passed
} else {
//handle when nil is passed
}
}
doSomeTask(UIButton()) in swift 5.0 and onward worked for me

fatal error: unexpectedly found nil while unwrapping an Optional value [duplicate]

This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 2 years ago.
I am trying to run this code but I keep on getting this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
I don't understand what it means or why I'm getting it. Any hint?
import UIKit
class ViewController: UIViewController {
var lastNumber: String = ""
#IBOutlet var answerField: UILabel
#IBOutlet var operaterLabel: 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 buttonTapped(theButton: UIButton) {
if answerField.text == "0"
{
answerField.text = theButton.titleLabel.text
}
else
{
answerField.text = answerField.text + theButton.titleLabel.text
}
}
#IBAction func plusTapped(theButton: UIButton) {
// error is talking about the next line
if operaterLabel.text == ""
{
operaterLabel.text = "+"
lastNumber = answerField.text
answerField.text = "0"
}
else
{
enterTapped(nil)
operaterLabel.text = "+"
}
}
#IBAction func minusTapped(theButton: UIButton) {
if operaterLabel.text == ""
{
operaterLabel.text = "-"
lastNumber = answerField.text
answerField.text = "0"
}
else
{
enterTapped(nil)
operaterLabel.text = "-"
}
}
#IBAction func clearTapped(AnyObject) {
answerField.text = "0"
operaterLabel.text = ""
lastNumber = ""
}
#IBAction func enterTapped(AnyObject?) {
var num1 = lastNumber.toInt()
var num2 = answerField.text.toInt()
if !num1 || !num2
{
showError()
return
}
var answer = 0
if operaterLabel.text == "-"
{
var answer = num1! - num2!
}
else if operaterLabel.text == "+"
{
var answer = num1! + num2!
}
else
{
showError()
return
}
answerField.text = "\(answer)"
}
func showError()
{
println("Ther was an error")
}
}
the error refers to the fact that you're accessing the parameter of an optional value when the optional value is set to nil (e.g. accessing answerField.text when answerField is nil), likely one of your two UILabels.
If the line operaterLabel.text == "" is throwing the exception, then your operaterLabel is nil. Verify that you have connected it successfully to the label in your Interface Builder file.
In my case, I was trying to access the labels in a function that I created which was used after the set of a variable.
var something: String {
didSet {
updateUI()
}
}
func updateUI() {
label.text = "Hello"
}
I solved it by:
var something: String
override func viewDidLoad() {
label.text = "hello"
}
My theory is that my function updateUI was accessed before the views and labels were created.
some times the problem that you have initiate view controller before present it like this:
let myViewController = MyViewController()
replace that by
let myViewController = self.storyboard?.instantiateViewController(withIdentifier: "storyboardID") as! MyViewController
check your outlets, I've had this before labels and buttons can just become dis connected (if for instance you have adjusted constraints ect)
a simple re connection can sometimes fix the issue
If you make sure the xib for your cell is no problem,
Then I occur this issue, my error was register the cell method :
1)
self.tableView.register(TerantInfoTabCell.self, forCellReuseIdentifier: "TerantInfoTabCell")
2)
self.tableView.register(UINib(nibName:"TerantInfoTabCell", bundle: nil), forCellReuseIdentifier: "TerantInfoTabCell")
I use the first method, there will appear the issue,then I use the 2) method replace the 1) , so there is no problem here.
I had the exact same error and spent quiet an amount of time debugging it. What #jmduke said is really the key: where does the error occur?
With my particular error, looking at operaterLabel.text == "" led me on the right path. I accessed the operaterLabel.text while the view was not yet fully initialized. In my particular case I set a variable from a different view during a segue and then acted upon that variable being set and updating a label inside the view. However the view was not completely initialized.
Thus my solution was to update the label inside the viewDidLoad() function.
I searched and searched trying to figure out how to solve my similar problem. As others mentioned, I was accessing UI elements before they were initialized. But figuring out why, was the difficult part. Spoiler --> I was using ProfileVC.swift and profileVC.xib
Even though I had all of my connections right in IB, from the parentVC I was calling
let newVC = ProfileVC()
profile.modalPresentationStyle = .custom
present(profile, animated: true, completion:nil)
Since I had different names (caplital 'P' in my swift file and lowercase 'p' in my xib), calling ProfileVC() didn't work as it didn't know to go to the xib I had made. Instead I had to use:
let newVC = ProfileVC.init(nibName: "profileVC", bundle: Bundle.main)
or just rename the xib to have a captial P and I could use my original code
Obviously this is hard to see in stackoverflow as you need to see what you are calling in the parent VC, the names of the files and IB. So hopefully this may be one solution to someone's problem out there even if it doesn't solve Arshia's problem.
That means your storyboard doesn't have a link to your IBOUTLET, please verify
I had this error and my problem was caused by adding a member (let's call it newProperty) to my model class, then trying to run a project that loaded data with NSCoder.decodeObjectForKey(newPropertyKey). During previous testing, I had saved objects without newProperty, so when the app tried to call decodeObjectForKey(newPropertyKey) on my old data, Xcode responded with this error message.
This error usually occurs because we try to change UILabel text after the view is loaded. Remember that UILabels once loaded in the view cannot be changed in any way they can only be set within viewdidload() function. You can check this by putting your text assigning code in the viewDidLoad() function which will set UILabels when loading the view, It will work.
But now if your application is built in such a way that it is setting UILabels after the view is loaded then the only solution is that you will need to create UILabels dynamically/Programatically where ever you want in the code and assign what ever you want because they will be created/instantiated with that text/label.
As #aircraft said you can register your cell this way :
let cellNib = UINib(nibName: "\(CellClass.self)", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "\(CellClass.self)")
this solved the problem with me.

Can't UnWrap Optional - None Swift

I assure you that i have checked all the answers prior posting this question on Unwrapping an object, but this thing simply does not seem to work for me. I am simply trying to pass on a text value from my cell tapped to the Label on the next screen.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if(segue.identifier == "detailViewSegue")
{
var DVC:DetailedViewController = segue.destinationViewController as DetailedViewController
let path:NSIndexPath = self.tableView.indexPathForSelectedRow()
var segueRecipeName:String = recipeMgr.RecipeName[path.row] as String
DVC.detailedRecipeLabel.text = segueRecipeName
}
}
The problem occurs at this line -
DVC.detailedRecipeLabel.text = segueRecipeName //Can't UnWrap Optional - None
I know I'm supposed to check the nil value of segueRecipeName before assigning. I do a print check on the console and it clearly is not null. The error occurs only when I'm assigning the value to the 2nd view controller class object. I'm sure this will help others learning Swift :)
DVC.detailedRecipeLabel is nil
Probably it's a IBOutlet that hasn't been loaded yet.
You should add a custom property to your DetailedViewController that will accept your text, save it and then you can assign it to the label in viewDidLoad.
Example:
class DetailedViewController ... {
...
var recipeName: NSString? = nil
...
override func viewDidLoad() -> () {
...
self.detailedRecipeLabel.text = self.recipeName
}
}
DVC.recipeName = segueRecipeName

Resources