Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode = 0x0) - ios

class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var userIsInTheMiddleOfTypingNumber: Bool = false
#IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if (userIsInTheMiddleOfTypingNumber) {
label.text = label.text! + digit
}
else {
label.text = digit
userIsInTheMiddleOfTypingNumber = true
}
}
}
I am currently creating a calculator app. For some reason, when I run the simulator and try to input some digits in, the siumulator freezes, and the error of bad_instruction appears on the line:
label.text = digit
How would I fix this situation?

Looks like you forgot to connect the label in the Storyboard with the outlet.

Looks like the currentTitle property is nil which results in a crash. You are force unwrapping the property without any nil check.
#IBAction func appendDigit(sender: UIButton) {
if let digit = sender.currentTitle {
if (userIsInTheMiddleOfTypingNumber) {
label.text = label.text! + digit
}
else {
label.text = digit
userIsInTheMiddleOfTypingNumber = true
}
}
}
OR
It could be the reason specified by #dasdom

Related

Detect when a button is pressed outside of the IBAction in Swift?

I'm a beginner programmer making my first real app, a calculator in Swift.
It's mostly working, but one issue I'm running into is how it displays numbers after pressing one of the operator buttons. Currently, whenever an operator button is pressed, I have it set the label at the top of the calculator to "0". But on actual calculators, this top display won't change until another number button is pressed.
If I don't reset the display to 0, then any number buttons that are pressed will add to the current text at the top, and mess up the equation that the calculator will have to do (i.e. 2+2 displays 22, and the solution it displays is 22+2=24)
I'm wondering if it's possible to detect when one of the number buttons is pressed (listed in my code as the intButtonPressed IBAction) outside of the intButtonPressed function? That way I can keep the top label the same until the user starts inputting more text, then I can set it to 0 to prevent the calculator from breaking.
Any other possible (better) solutions would be welcome as well
Here's my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var topLabel: UILabel!
var num1 = Double()
var solution = Double()
var op = String()
#IBAction func intButtonPressed(_ sender: UIButton) {
if topLabel.text == "0" {
topLabel.text = sender.currentTitle
}
else if topLabel.text == String(solution) {
num1 = Double(topLabel.text!)!
solution = 0.00
topLabel.text = sender.currentTitle
// Basically stops user from adding to solution?
// Also stores solution as num1 and clears solution field
}
else {
topLabel.text = topLabel.text! + sender.currentTitle!
// Keep typing
}
if (topLabel.text?.count)! > 12 {
topLabel.text = "Error"
}
else {
return
}
// if its greater than 12 characters, display "error"
}
#IBAction func clearButtonPressed(_ sender: UIButton) {
num1 = 0.00
solution = 0.00
topLabel.text = "0"
}
#IBAction func opButtonPressed(_ sender: UIButton) {
if sender.currentTitle == "=" {
equals()
}
else {
op = sender.currentTitle!
num1 = Double(topLabel.text!)!
topLabel.text = "0"
}
// Need it to display num1 until I press another button, then I need it to only display that text.
}
func equals() {
switch op {
case "+":
add()
case "-":
subtract()
case "×":
multiply()
case "÷":
divide()
default:
print(Error.self)
}
}
func add() {
solution = num1 + Double(topLabel.text!)!
topLabel.text = String(solution)
}
func subtract() {
solution = num1 - Double(topLabel.text!)!
topLabel.text = String(solution)
}
func multiply() {
print("topLabel = ", topLabel.text!)
solution = num1 * Double(topLabel.text!)!
print("solution = ", solution)
topLabel.text = String(solution)
}
func divide() {
solution = num1 / Double(topLabel.text!)!
//answer()
}
}
Update for anyone who finds this in the future: I've solved the issue, and realized that I wasn't very clear with what I wanted it to do. I solved the problem simply by adding a condition to the if/else statement in the inButtonPressed function that detects if the topLabel is 0. By rewriting that to detect if the topLabel is 0 OR the same as num1, and then changing the else statement in the opButtonPressed function to set topLabel to String(num1), the program does exactly what I want. Here's the rewritten code:
#IBAction func intButtonPressed(_ sender: UIButton) {
if topLabel.text == "0" || topLabel.text == "0.0" || topLabel.text == String(num1){
dotPressed = false
// Resets dotPressed whenever the top is 0 or num1 and an int button is pressed
topLabel.text = sender.currentTitle
}
else if topLabel.text == String(solution) {
num1 = Double(topLabel.text!)!
solution = 0.00
topLabel.text = sender.currentTitle
// Basically stops user from adding to solution?
// Also stores solution as num1 and clears solution field
}
else {
topLabel.text = topLabel.text! + sender.currentTitle!
}
}
#IBAction func opButtonPressed(_ sender: UIButton) {
if sender.currentTitle == "=" {
equals()
}
else {
op = sender.currentTitle!
num1 = Double(topLabel.text!)!
topLabel.text = String(num1)
}
// Successfully displays num1 until I press another button, then only displays that text.
I also added a separate function to handle decimals, and I had to update the code in there as well to keep that working.

How to add two numbers in Swift only when both of the text fields are filled in

I'm trying to add two numbers in Swift 5, and I want to add some error checks. I don't want to make it possible for a user to click on the plus button if both of the text fields are not filled in. I tried with the if state below but it did not work.
the whole function:
#IBAction func sum(_ sender: Any) {
let one = input1.text
let oneInt = Int(one!)
let two = input2.text
let twoInt = Int(two!)
let total = oneInt! + twoInt!
label.text = "\(total)"
if(input2.text == nil){
addBtn.isEnabled = false
}
if(input1.text == nil){
addBtn.isEnabled = false
}
}
Try to use guard like this. If your input field does not contain any value that field return blank string and when you try to get integer value from that string it will return nil and your add button will be disable.
#IBAction func sum(_ sender: Any) {
guard let text1 = input1.text, let intValue1 = Int(text1) else {
addBtn.isEnabled = false
return
}
guard let text2 = input2.text, let intValue2 = Int(text2) else {
addBtn.isEnabled = false
return
}
label.text = "\(intValue1 + intValue2)"
}
A nice and simple way is to addTarget to your textFiels. This will enable you to handle the events on the text field. In this scenario we'll use .editingChanged and use a single selector to achieve our goal:
What we'll do : We will listen for when someone types something in the textfield. Whenever a text changed was made, we'll check to see if all the textfields was populated and then if it was we enable the sum button.
A small controller sample :: Make sure to read the comments to understand the code faster
import UIKit
class ViewController: UIViewController {
#IBOutlet var textfield1: UITextField!
#IBOutlet var textfield2: UITextField!
#IBOutlet var sumButton: UIButton!
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
sumButton.isEnabled = false /// Disable the button first thing
[textfield1, textfield2].forEach {
$0.addTarget(self, action: #selector(editingChanged(_:)), for: .editingChanged) /// add targets to handle the events (in your case it listens for the 'editingChanged' event )
}
}
#objc func editingChanged(_ textField: UITextField) {
/// Here we just loop through all our textfields
for each in [textfield1, textfield2] {
if let text = each?.text { /// Just make sure the textfields text is not nil
if text.count < 1 {
// If the textfiels text has no value in, then we keep the button disabled and return
sumButton.isEnabled = false
return
}
} else {
/// Else if the text field's text is nill, then return and keep the button disabled
sumButton.isEnabled = false
return
}
}
sumButton.isEnabled = true /// If the code reaches this point, it means the textfields passed all out checks and the button can be enabled
}
#IBAction func sum(_ sender: Any) {
let one = textfield1.text!
let two = textfield2.text!
guard let oneInt = Int(one), let twoInt = Int(two) else {
print("Whatever was in that text fields, couldn't be converted to an Int")
label.text = "Be sure to add numbers."
return
}
let total = oneInt + twoInt
label.text = "\(total)"
}
}
textfields are not nil but empty strings. so make your comparison like :
if input1.text == "" {
// do your check here
}
Seems like you want to start with addBtn.isEnabled = false then update it whenever the user enters two valid integers into the text fields, i.e. Int(input1.text ?? "") != nil && Int(input2.text ?? "") != nil. You can do this by adding a target to your textfields (input1 and input2) for .editingChanged events. For example, if you're doing this in a UIViewController, you can do this in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
addBtn.isEnabled = false
input1.addTarget(self, action: #selector(textFieldDidEdit(_:)), for: .editingChanged)
input2.addTarget(self, action: #selector(textFieldDidEdit(_:)), for: .editingChanged)
}
Where textFieldDidEdit(_:) action looks like:
#objc func textFieldDidEdit(_ sender: UITextField) {
addBtn.isEnabled = Int(input1.text ?? "") != nil && Int(input2.text ?? "") != nil
}
Finally your sum function becomes:
#IBAction func sum(_ sender: UIButton) {
guard let oneInt = Int(input1.text ?? ""), let twoInt = Int(input2.text ?? "") else {
return
}
let total = oneInt + twoInt
label.text = "\(total)"
}
As all of the number validation has moved to the textFieldDidEdit(_:) function.

Xcode finds nil in optional value and crashes Swift

I've been looking on this site for an answer to my question but no matter what I do my compiler still gives me the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
I don't know what is causing this seeing as I wrapped up all my code in an if statement to ensure that if the value submitted is nil it would print a message.
Here is the code:
#IBOutlet var textField: UITextField!
#IBOutlet var label4: UILabel!
#IBAction func buttonTapped(_ sender: Any) {
if textField.text != nil {
let textFieldInt: Int? = Int(textField.text!)
let convert = textFieldInt! * 7
label4.text = String(convert)
}
else {
label4.text = "Please enter a number!"
}
}
I've searched through similar questions and have understood a small amount about what is causing this error but I have yet to find a solution.
Could someone please help me?
I am using Xcode8 with the latest version of Swift.
You are force unwrapping using !. You need to do if let or guard let to unwrap because textFieldInt that you force wrapped may be nil.
You should use this code
if let textFieldText = textField.text {
if let textFieldInt = Int(textFieldText ){
let convert = textFieldInt * 7
label4.text = "\(convert)"
} else{
print("textFieldInt is nil")
}
}else{
print("text field's text is nil, not too likely")
}
The crash occurs due to textFieldInt is nil
the problem is that textField.text is not number-like String.
let textFieldInt: Int? = Int(textField.text!)
That's why textFieldInt is nil here:
let convert = textFieldInt! * 7
to solve this issue I would suggest to use this:
if let val = textField.text, let intVal = Int(val) {
let convert = intVal * 7
label4.text = String(convert)
} else {
label4.text = "Please enter a number!"
}
You declared textFieldInt as an optional Int? Thus, it's possible for it to be nil. The following will assure it's an Int
guard let textFieldInt = textField.text as? Int else {
//handle fail case
return
}
Try this:
#IBOutlet var textField: UITextField!
#IBOutlet var label4: UILabel!
#IBAction func buttonTapped(_ sender: Any) {
if textField.text != nil {
if let textFieldInt: Int? = Int(textField.text!){
let convert = textFieldInt! * 7
label4.text = String(convert)
}
}
else {
label4.text = "Please enter a number!"
}
}

Could not find an overload for “init” that accepts the supplied arguments - Stanford course work

I am trying to learn swift now and following the standard online and first lecture's work is to build a calculator. I followed exactly the same code but it failed to compile. code as follow:
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 mathmaticalSymbol = sender.currentTitle{
if mathmaticalSymbol == "π" {
display.text = String(M_PI)
}
}
}
}
error message showed up on the line of display.text = String(M_PI).
it said "Could not find an overload for “init” that accepts the supplied arguments".
should be an easy question but I am new to Swift and couldn't figure it out.

Swift 2 Converting from String To Number

I'm following the Stanford Videos for iOS development and I am using Xcode 7 with Swift 2.
I wrote the code from the video line by line, however I keep getting an error.
import UIKit
class ViewController: UIViewController
{
#IBOutlet weak var display: UILabel!
var userIsTyping = false
#IBAction func AppendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsTyping {
display.text = display.text! + digit
} else {
display.text = digit
userIsTyping = true
}
}
var operandStack = Array<Double>()
#IBAction func enter() {
userIsTyping = false
operandStack.append(displayValue)
}
var displayValue: Double {
get{
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set (newValue){
display.text = "\(newValue)"
userIsTyping = false
}
}
}
At the line where I return
NumberFormatter().numberFromString(display.text!)!.doubleValue
I get an error of
Thread 1: EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP,subcode=0x0)
A conversion can fail. The result can be nil. The "!" means "compiler, I am 100 percent sure that the result can never be nil, so if it is ever nil then please crash". Guess what, sometimes it is nil.
Use "if let".
PS. I think it is very, very unhealthy to take user interface elements (like the title of a button) and to assume they have certain values.
You are much better off substituting that return statement with a much simpler:
return Double(display.text!)!
let Number = (NSNumberFormatter().numberFromString(xtxt.text!)as! Double)
return Number

Resources