Changing of text on button not permanent - swift4

I have four buttons in a single view, with texts "A", "B", "X", "Y" on them respectively. I expected to see the texts of btnA and btnB change respectively when I pressed on btnX and btnY respectively and then both of btnA and btnB turn green. Instead, when I pressed btnA, "A" changed to "1" and immediately changed back to "A" again. But btnB changed to "2" permanently as expected.
This problem may seem simple but I just can't get the expected result. I just started to learn Swift. Please help me. Thank you!
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btnA: UIButton!
#IBOutlet weak var btnB: UIButton!
#IBOutlet weak var btnX: UIButton!
#IBOutlet weak var btnY: UIButton!
#IBAction func btnXPressed(_ sender: UIButton) {
btnA.titleLabel?.text = "1"
check()
}
#IBAction func btnYPressed(_ sender: UIButton) {
btnB.titleLabel?.text = "2"
check()
}
func check() {
if ((btnA.titleLabel?.text)! == "1") && ((btnB.titleLabel?.text)! == "2") {
btnA.backgroundColor = UIColor.green
btnB.backgroundColor = UIColor.green
}
}
}

Related

printing percentage value into decimal swift

The Result I wantedi have three buttons under same IBAction showing different percentages %0, %10, %20.
and I have another button called calculate in another IBAction. so what I want is. when I choose %10 and press calculate I want to print out the 0.1 in the console. this is very beginner question but I m really stuck here
below is my code
import UIKit
class CalculatorViewController: UIViewController {
#IBOutlet weak var billTextField: UITextField!
#IBOutlet weak var zeroPctButton: UIButton!
#IBOutlet weak var tenPctButton: UIButton!
#IBOutlet weak var twentyPctButton: UIButton!
#IBOutlet weak var splitNumberLabel: UILabel!
#IBAction func tipChanged(_ sender: UIButton) {
zeroPctButton.isSelected = false
tenPctButton.isSelected = false
twentyPctButton.isSelected = false
sender.isSelected = true
}
#IBAction func stepperValueChanged(_ sender: Any) {
}
#IBAction func calculatePressed(_ sender: UIButton) {
}
}
The easiest way is to add the output on the percentage button tapped, e.g. in the #IBAction of the "10%" button:
print("0.1")
If you really need to output on the Calculate button tap, you can first determine which percantage button is selected:
if zeroPctButton.isSelected {
print("0.0")
} else if tenPctButton.isSelected {
// ...
If you don't want to hardcode the output, you need some data to base on. Since you don't show us any model code, we can only rely on the text on the buttons. So, the solution might look something like this (inside the Calculate button's #IBAction):
[zeroPctButton,
tenPctButton,
twentyPctButton]
.filter { $0.isSelected }
.forEach {
print("\(Double(($0.titleLabel.text ?? "").filter { ("0"..."9").contains($0) }) / 100.0)")
}
(It takes the text of the selected percentage buttons, filters out only digits from it, converts the resulting digit string to Double, and divides the result by 100.0.)

Troubles with starting value using UISlider

Started working on the application. There was the following problem, in Main.storyboard the current value is set for the slider (for the top one it is 1.5 out of 3, and for the bottom one it is 100 out of 200), therefore, in the screenshot, I should have points on the slider track in the middle. I started googling about it, I can't find anything. Xcode 12 problem maybe? If not, please help me write the correct search query. I will be very grateful.
Sorry for my bad English. :)
Here ViewController:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var heightLabel: UILabel!
#IBOutlet weak var weightLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func heightSliderChanged(_ sender: UISlider) {
print(sender.value)
heightLabel.text = String(format: "%.2f", sender.value) + "m"
}
#IBAction func weightSliderChanged(_ sender: UISlider) {
weightLabel.text = String(format: "%.0f", sender.value) + "Kg"
}
}
Property's for first slider:
Property's for second slider:
Yes, it's Xcode issues. You can find the issues list from this link. (https://fahimfarook.medium.com/xcode-12-and-ios-14-developer-bugs-and-issues-ada35920a104).
Create an outlet of both slider and set value through coding.
#IBOutlet weak var firstSlider: UISlider!
#IBOutlet weak var secondSlider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
firstSlider.minimumValue = 0
firstSlider.maximumValue = 3
firstSlider.value = 1.5
secondSlider.minimumValue = 0
secondSlider.maximumValue = 200
secondSlider.value = 100
}

How can I properly send values between classes in Swift?

I've been working on a text based adventure game using Swift. However, I can't seem to change the default values for specific classes.
Below is the code for the class that allows me to select my player class
import UIKit
class ClassSelectionController: UIViewController
{
//Default class values
var character = (0, 0, "", 0)
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//class button actions
#IBAction func fighterBtn(_ sender: Any)
{
character = (50, 60, "Steal Sword", 18)
performSegue(withIdentifier: "Character", sender: self)
}
#IBAction func wizerdBtn(_ sender: Any)
{
character = (25, 70, "Staff", 15)
performSegue(withIdentifier: "Character", sender: self)
}
#IBAction func thiefBtn(_ sender: Any)
{
character = (30, 60, "Dagger", 18)
performSegue(withIdentifier: "Character", sender: self)
}
#IBAction func archerBtn(_ sender: Any)
{
character = (50, 60, "Bow & Arrow", 16)
performSegue(withIdentifier: "Character", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: (Any)?)
{
//code for segue
var vc = segue.destination as! ViewController
vc.finalCharacter = self.character
}
}
And this is the class that receives the data for the player class and displays it.
import UIKit
class ViewController: UIViewController
{
var finalCharacter = (0, 0, "", 0)
//****************************************
//Setup for outlets go between these lines
//****************************************
#IBOutlet weak var healthLabel: UILabel!
#IBOutlet weak var damageLabel: UILabel!
#IBOutlet weak var weaponLabel: UILabel!
#IBOutlet weak var armorLabel: UILabel!
#IBOutlet weak var storyLabel: UILabel!
#IBOutlet weak var actionButton: UIButton!
#IBOutlet weak var northBtn: UIButton!
#IBOutlet weak var southBtn: UIButton!
#IBOutlet weak var eastBtn: UIButton!
#IBOutlet weak var westBtn: UIButton!
//****************************************
//Setup for outlets go between these lines
//****************************************
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
healthLabel.text = "Health: \(finalCharacter.0)"
damageLabel.text = "Damage: \(finalCharacter.1)"
weaponLabel.text = "Weapon: " + finalCharacter.2
armorLabel.text = "Armor : \(finalCharacter.3)"
}
//****************************************
//Setup for buttons go between these lines
//****************************************
#IBAction func actionButton(_ sender: Any)
{
}
#IBAction func northButton(_ sender: Any)
{
}
#IBAction func southButton(_ sender: Any)
{
}
#IBAction func eastButton(_ sender: Any)
{
}
#IBAction func westButton(_ sender: Any)
{
}
//****************************************
//Setup for buttons go between these lines
//****************************************
}
Even though my code does not currently show it I did put print values in the class buttons just so see if the values have changed when I select a class and I have seen that they do change when the button is pressed. I also poked around in ViewController and changed the finalCharacter values, just to see if that affected anything, which it didn't. So my educated guess is that the problem has to be in ClassSelectionController.
So the main problem is that I will click on the wizard player class, and I'd expect the class stats for the wizard to pop up (I.e. 25, 70, "Staff", 15), but I'll only get the default values that are in the ClassSelectionController (0, 0, "", 0).
What is happening here that you have multiple UIStoryboardSegue named "Character" linked with every button
so what happens is when you press the button the Segue is called before the Action button and in addition the UIStoryboardSegue is called again (if you place a debugger in the viewDidLoad you would see that it goes there two times).
Solution
Remove all the UIStoryboardSegue linked from the buttons
Make a new UIStoryboardSegue from the ClassSelectionController to the next ViewController name it 'Character'
You dont need to change anything from the code but should add a safe check
override func prepare(for segue: UIStoryboardSegue, sender: (Any)?)
{
if (segue.identifier == "Character") {
let vc = segue.destination as! ViewController
vc.finalCharacter = self.character
}
}

Error : Consecutive statements on a line must be separated by ';' What's wrong?

import UIKit
class ViewController: UIViewController {
//Place your instance variables here
let questions = Questionbank()
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet var progressBar: UIView!
#IBOutlet weak var progressLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let firstQuestion = questions.list[0]
questionLabel.text = firstQuestion.questionText
}
#IBAction func answerPressed(_ sender: AnyObject) {
}
func updateUI() {
}
func nextQuestion() {
}
func checkAnswer() {
}
func startOver() {
}
}
This is my code above. And following is the error come up.
This is the errors come up.
There seems to be problem with questionLabel.text line but
I can't figure it out. This is a part of ios tutorial I am currently
working on.
Thank you for help.
I just found out why.
Problem was questionLabel.text not being written using xcode auto complete feature.
First time I typed manually and got error.
Second time, I let Xcode autocomplete it and it worked.
Anyone know why this works this way?

Nesting buttons in Swift

How can a button press another button. I want to know how to press button2 and have button1 complete its task and relay that information to button2. I feel like this answer is super simple, and any help would be greatly appreciated.
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBAction func button1(sender: AnyObject) {
var textAgeArray = ["1", "2", "3"]
let randomTextAge = Int(arc4random_uniform(UInt32(textAgeArray.count)))
let displayAge = textAgeArray[randomTextAge]
textField1.text = displayAge
}
#IBAction func button2(sender: AnyObject) {
textField2.text = displayAge
}
You are using these buttons to update particular text field when a button is pressed, so put that task inside a function and then call that function from any button. If you want to track that then add a variable to check what is current text. What you are trying to do can be done through this way because you don't want to press button you want to do particular task.
As Mukesh suggested you can refactor your code, with a separate method of the repeated code.
Just thought I'd post an alternative solution. You can call the button1 method from inside of button2:
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
var displayAge: String?
#IBAction func button1(sender: AnyObject) {
var textAgeArray = ["1", "2", "3"]
let randomTextAge = Int(arc4random_uniform(UInt32(textAgeArray.count)))
displayAge = textAgeArray[randomTextAge]
textField1.text = displayAge
}
#IBAction func button2(sender: AnyObject) {
button1(sender)
textField2.text = displayAge
}
Note that you must take the displayAge variable out so that the button2 method can access it. This will make textField1 and textField2's text the same. I'm not sure if that's the desired result as I can't tell from your post. If you want these to be different random fields then I would suggest you refactor it to have the repeated method separate.
This will also set both of the text fields at the same time. If you don't want to refactor your code to only set one field at a time then you could start tagging your button's to see where the call is coming from:
#IBOutlet var button1: UIButton!
#IBAction func button1(sender: AnyObject) {
var textAgeArray = ["1", "2", "3"]
let randomTextAge = Int(arc4random_uniform(UInt32(textAgeArray.count)))
displayAge = textAgeArray[randomTextAge]
// if sender is this button, then update text, otherwise don't do anything
if sender.tag == 1 {
textField1.text = displayAge
}
}
By default tags are 0, but you can change them by set them like so: (You can put this in viewDidLoad)
button1.tag = 1
May as well add the solution by refactoring for completeness:
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBAction func button1(sender: AnyObject) {
let displayAge = randomTextAge()
textField1.text = displayAge
}
#IBAction func button2(sender: AnyObject) {
let displayAge = randomTextAge()
// Uncomment the line below if you want to update textField1 with the same value
// textField1.text = displayAge
textField2.text = displayAge
}
func randomTextAge() -> String {
var textAgeArray = ["1", "2", "3"]
let randomTextAge = Int(arc4random_uniform(UInt32(textAgeArray.count)))
let displayAge = textAgeArray[randomTextAge]
return displayAge
}