cs193p Swift - key value coding error - swift

I can't believe I'm having a problem with the very first lecture! We are building a calculator (it is not at all functional as a calculator at this point). Mine was working just fine until the performOperation function was added. Now I'm getting "this class is not key value coding compliant" error. The thing is that, as far as I can see, my code EXACTLY replicates the code that he is using in the class. I must be missing something but I've checked roughly 50 times to find a difference and I can't find one. Help? It is crashing every time.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTyping = false
#IBAction func touchDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTyping {
let textCurrentlyInDisplay = display.text!
display.text = textCurrentlyInDisplay + digit
} else {
display.text = digit
}
userIsInTheMiddleOfTyping = true
}
#IBAction func performOperation(sender: UIButton) {
userIsInTheMiddleOfTyping = false
if let mathematicalSymbol = sender.currentTitle {
if mathematicalSymbol == "π" {
display.text = String(M_PI)
}
}
}
}
EDIT: Code format

You can check your viewcontroller in storyboard, at the Module TextField in the right toolbar.
Do following steps if module textfield
is empty (there’s no placeholder):
Step 1. Focus Module TextField
Step 2. Edit randomly then clear
Step 3. Press Enter, if the result is as same as this picture, everything’s going okey.

Related

Control (UIDatePicker) doesn't trigger change event when it starts out hidden

I'm new to iOS development, but I'm having an issue with one of the views that I'm working on. I have a UIDatePicker that can either be hidden or visible depending on the state of a UISwitch. It seems that the associated #IBAction does not trigger when the view starts out hidden. It does work when the date picker starts out visible, so the IBAction is working.
Here's a simplified version of my code:
import UIKit
class StatusEditorViewController: UIViewController {
#IBOutlet var expiryPicker: UIDatePicker!
#IBOutlet var enableExpirySwitch: UISwitch!
var editingObject: StoredStatus?
private var pickerIsVisible = false
private var expiresIn: TimeInterval?
override func viewDidLoad() {
// Set a default value
expiryPicker.countDownDuration = TimeInterval(3600)
// If this view got passed an object to edit, use that for expiresIn
if let status = editingObject {
if let expires = status.expiresIn.value {
expiresIn = TimeInterval(expires)
}
}
// Hide the picker and turn off the "enable expiry" switch if we don't
// have a value yet. We'll show the picker once the switch has been pressed
pickerIsVisible = expiresIn != nil
enableExpirySwitch.isOn = expiresIn != nil
updatePicker()
}
func updatePicker() {
expiryPicker?.isHidden = !pickerIsVisible
}
#IBAction func expiryDidUpdate(_ sender: UIDatePicker) {
expiresIn = sender.countDownDuration
print(expiresIn!)
}
#IBAction func expirySwitchDidUpdate(_ sender: UISwitch) {
pickerIsVisible = sender.isOn
updatePicker()
// If the user just turned on the switch, we want to make sure we store the
// initial value already, in case the user navigated away
if (sender.isOn && expiresIn == nil) {
expiresIn = expiryPicker.countDownDuration
}
}
}
I'm not sure what's going wrong. I tried manually attaching a target (e.g. self.expiryPicker.addTarget(self, action: #selector(setExpiryValue), for: .allEditingEvents))
once the view becomes available, but that didn't work either.
I hope someone can tell me what I'm doing wrong. I'm guessing there's something fundamental that I'm doing wrong, but so far no search on Google or SO has led me to the answer.
Thanks in advance
f.w.i.w, I'm running XCode 11.7, with Swift 5, with a deployment target of iOS 13.7

Swift can't get text of label even though the same expression

im programming a calculator app as an exercise project.
I have already used the text of the label before via
calculatorLabel.text
Eventhough I use exactly the same expression in another function, I always get 0 instead of the actual text inside it. I seriously do not understand why that happens. I have already tried using debug mode and stuff but it doesn't work.
here ar the two functions (shortened):
#IBAction func operationButtonTapped(_ sender: UIButton) {
let operation = sender.currentTitle!
lastSender.backgroundColor = UIColor.systemBlue
lastSender = sender
sender.backgroundColor = UIColor.orange
//a switch would be here(deleted)
isTyping = false
let currentNumber = Double(calculatorLabel.text!)!
a = currentNumber
}
#IBAction func changeStateButtonTapped(_ sender: UIButton) {
let operation = sender.currentTitle!
let displayedNumber = Double(calculatorLabel.text!)!
var displayedText = self.calculatorLabel.text!
if operation == "+/-"{
if operation.prefix(1) == "-" {
displayedText.remove(at: displayedText.startIndex)
}
else{
displayedText = "-" + String(displayedNumber)
}
}
else if operation == "%"{
displayedText = String(displayedNumber/100)
}
calculatorLabel.text = displayedText
}
the top one gets the text while the bottom one doesn't...
thank you very much in advance for trying to help me!
I found the answer...
It seems the connection between it and the code was somehow messed up.
To all who have the same problem: right click the component in the storyboard and check the connections!

How to solve the error SIGABRT even if the outlets look correct?

I'm working on my first iOS app with Xcode and Swift. My app has multiple UIViewControllers (=VC). Everything works quite well, but there is an error which I couldn't work out on my own with the help of Google or StackOverflow.
My problem is:
I have a UIButton called 'Quit' in the VC 'CompleteTest' which I control dragged in the Main storyboard to the VC 'Main Menu' in order that it brings the user back to the 'Main Menu' when it is pressed.
But when I click this UIButton in the Simulator the error:
Thread 1 signal SIGABRT comes up.
This is not the first time I stumbled over this error and I saw multiple threads in stack overflow giving a solution to this problem. In the past by checking the outlets I could solve this error quite easily.
But in this case this solution doesn't work, because the outlets look fine (there are no exclamation-points showed).
What is even more strange is where the error is showed.
Normally the SIGABRT error is shown in the AppDelegate, if I'm not mistaken.
But in my case it is shown at the line 54 of the VC 'CompleteTest'-file. At this line I am transferring data to the next VC 'Final Complete test' with the override function 'prerpare'.
Unfortunately, I couldn't put images in this question, even tough
I prepared them. Anyway I hope my problem is still clear.
Furthermore, excuse me for my poor English as it is my second language.
How should I proceed? Thank you in advance for your help!
import UIKit
class CompleteTest: UIViewController {
// Components of Visualisation VC
#IBOutlet weak var ShotNumber: UILabel!
#IBOutlet weak var ProjectedScore: UILabel!
#IBOutlet weak var Distance: UILabel!
var sum: Double = 100.0 //sum represents overall Score of Test
#IBOutlet weak var Report: UIButton!
var help: Int = 0 // var 'help' is helping to change the number showed on the Scoring Buttons in VC
#IBOutlet weak var Left1: UIButton!
#IBOutlet weak var Right1: UIButton!
#IBOutlet weak var Center1: UIButton!
#IBOutlet weak var BadContact1: UIButton!
//Percentage components
var leftpct: Int = 0
var rightpct: Int = 0
var centerpct: Int = 0
var totalpct: Int = 0
var badcontactpct: Int = 0
// Transfer of data from ViewController 'CompleteTest' to ViewController 'FinalCompleteTest'
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let finalCompleteTest = segue.destination as! FinalCompleteTest
finalCompleteTest.score = String(sum)
finalCompleteTest.Leftpct = Int(leftpct)
finalCompleteTest.Rightpct = Int(rightpct)
finalCompleteTest.Centerpct = Int(centerpct)
finalCompleteTest.Totalpct = Int(totalpct)
finalCompleteTest.BadContactpct = Int(badcontactpct)
}
override func viewDidLoad() {
super.viewDidLoad()
Report.isHidden = true
}
//Scoring Buttons
#IBAction func BadContact(_ sender: Any) {
sum -= 1
BadContact1.setTitle("OK", for: .normal)
badcontactpct += 1
}
#IBAction func Left(_ sender: Any) {
sum -= 0.5
help += 1
Left1.setTitle(String(help), for: .normal)
if help == 1 {
leftpct += 1
totalpct += 1}
}
#IBAction func Right(_ sender: Any) {
sum -= 0.5
help += 1
Right1.setTitle(String(help), for: .normal)
if help == 1 {
rightpct += 1
totalpct += 1}
}
#IBAction func Center(_ sender: Any) {
Center1.setTitle("0", for: .normal)
centerpct += 1
totalpct += 1
}
Thanks for taking the time to write such a thorough question. If you want, you can upload your images to some other site (e.g. imgur) and then use the direct links here.
As matt mentions in the comments, that as! might be the reason you're seeing this crash. You can easily prove it if you replace your code to something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let finalCompleteTest = segue.destination as? FinalCompleteTest {
finalCompleteTest.score = String(sum)
finalCompleteTest.Leftpct = Int(leftpct)
finalCompleteTest.Rightpct = Int(rightpct)
finalCompleteTest.Centerpct = Int(centerpct)
finalCompleteTest.Totalpct = Int(totalpct)
finalCompleteTest.BadContactpct = Int(badcontactpct)
} else {
print("oh no, segue.destination is not a FinalCompleteTest")
}
}
If you can see that message in your console, probably you haven't connected something correctly on the storyboard.
If not, try to give us some more information.
If you don't understand the "dangers" of using ! in your code, please try to understand Optionals first and don't hesitate to ask if you need more help.
Good luck!

using switch statement inside a button

Please help and I'm sorry if this is covered somewhere else although i have looked elsewhere and whilst there are answers to my topic i cannot find one for my problem. so if anyone could help that would be great.
basically i am trying to do a switch statement inside a button so that when i click the button the statement activates in my label, but for some reason i cannot get it to work
here is my code below
when i hit run it always shows the "This is an even number between 0 and 10" regardless of even number, odd number or large number
Any help would be greatly appreciated
thank you very much
Right before the switch line you have to add three lines to assign the value of the input text field to the variable number.
guard let inputText = numberInput.text, let input = Int(inputText) else {
numberOutput.text = "Please enter a number!"
return }
number = input
This code works fine in playground, always prints expected output.
var number = 6
switch number {
case 0,2,4,6,8,10:
print("even")
case 1,3,5,7,9:
print("odd")
default:
print("higher")
}
where are you changing the number variable? Are you doing it on one of the callback methods for textfield delegate?
you are not changing the value of your var number. Looks like it is always 6 based from your code
You can simply do this:
import UIKit
class EmptyViewController: UIViewController
{
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textField: UITextField!
#IBAction func buttonHit(_ sender: UIButton)
{
if let text = textField.text, let number = Int(text)
{
switch number {
case 0,2,4,6,8,10:
label.text = "Even"
case 1,3,5,7,9:
label.text = "Odd"
default:
label.text = "Higher"
}
}
else
{
label.text = "Please enter a valid number"
}
}
}

Declare a variable in ViewDidLoad and use elsewhere (Swift)

First Swift project, and I'm confused as to how scope works. I'm trying to choose a random integer in ViewDidLoad and then allow the user to guess the number, but I can't work out how to access the variable answer created in ViewDidLoad in my button action.
class ViewController: UIViewController {
#IBOutlet var guess: UITextField!
#IBOutlet var result: UILabel!
#IBAction func guessButton(sender: AnyObject) {
var userGuess = guess.text.toInt()
if userGuess != nil {
if userGuess == answer {
result.text = "You got it!"
} else if userGuess > answer {
result.text = "Too high! Guess again!"
} else {
result.text = "Too low! Guess again!"
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
var answer = arc4random_uniform(100) + 1
}
}
Three scopes:
File top level
Object type declaration top level (like your guess)
Local (inside function curly braces) (like your userGuess)
You can only see up (higher surrounding scope).
So, code in guessButton method cannot see variable declared in viewDidLoad method. But they can both see variable declared at file top level or variable declared at object type declaration top level. Which one do you think is most appropriate here?