I have this code, but I want to improve it to enable changing operations without immediate calculation. For instance, if I input a number and mistakenly press ‘+’ followed by ‘-‘, it should perform subtraction instead of addition.
How can i fix this issue?
here’s the code:
import SwiftUI
enum CalcButton: String {
case one = "1"
case two = "2"
case three = "3"
case four = "4"
case five = "5"
case six = "6"
case seven = "7"
case eight = "8"
case nine = "9"
case zero = "0"
case add = "+"
case subtract = "-"
case divide = "÷"
case mutliply = "x"
case equal = "="
case clear = "AC"
case decimal = "."
case percent = "%"
case negative = "-/+"
var buttonColor: Color {
switch self {
case .add, .subtract, .mutliply, .divide, .equal:
return .orange
case .clear, .negative, .percent:
return Color(.lightGray)
default:
return Color(UIColor(red: 55/255.0, green: 55/255.0, blue: 55/255.0, alpha: 1))
}
}
}
enum Operation {
case add, subtract, multiply, divide, none
}
struct ContentView: View {
@State var displayNumber = 0 // change to Int
@State var lastResult = 0
@State var currentOperation: Operation = .none
@State var awaitingNewNumberInput = true // to switch from result display to input
let buttons: [[CalcButton]] = [
[.clear, .negative, .percent, .divide],
[.seven, .eight, .nine, .mutliply],
[.four, .five, .six, .subtract],
[.one, .two, .three, .add],
[.zero, .decimal, .equal],
]
var body: some View {
ZStack {
Color.black.edgesIgnoringSafeArea(.all)
VStack {
Spacer()
// Text display
HStack {
Spacer()
Text("(displayNumber)") // show value as string
.font(.system(size: 100))
.foregroundColor(.white)
}
.padding()
// Our buttons
ForEach(buttons, id: .self) { row in
HStack(spacing: 12) {
ForEach(row, id: .self) { item in
Button(action: {
didTap(button: item)
}, label: {
Text(item.rawValue)
.font(.system(size: 32))
.frame(
width: buttonWidth(item: item),
height: buttonHeight()
)
.background(item.buttonColor)
.foregroundColor(.white)
.cornerRadius(buttonWidth(item: item)/2)
})
}
}
.padding(.bottom, 3)
}
}
}
}
func didTap(button: CalcButton) {
switch button {
case .add:
setCurrentResult()
currentOperation = .add
awaitingNewNumberInput = true
case .subtract:
setCurrentResult()
currentOperation = .subtract
awaitingNewNumberInput = true
case .mutliply:
setCurrentResult()
currentOperation = .multiply
awaitingNewNumberInput = true
case .divide:
setCurrentResult()
currentOperation = .divide
awaitingNewNumberInput = true
case .equal:
setCurrentResult()
currentOperation = .none
awaitingNewNumberInput = true
case .clear:
// set ALL to 0
displayNumber = 0
lastResult = 0
currentOperation = .none
awaitingNewNumberInput = true
case .decimal, .negative, .percent:
break
default:
// number input
let number = Int(button.rawValue) ?? 0 // string to Int
if awaitingNewNumberInput {
awaitingNewNumberInput = false
displayNumber = number
} else {
displayNumber = displayNumber * 10 + number
}
}
}
// check if an older operation is active, calculate partial result
func setCurrentResult() {
switch currentOperation {
case .add:
displayNumber += lastResult
case .subtract:
displayNumber = lastResult - displayNumber
case .multiply:
displayNumber *= lastResult
case .divide:
displayNumber = lastResult / displayNumber
case .none:
break
}
lastResult = displayNumber
currentOperation = .none
}
func buttonWidth(item: CalcButton) -> CGFloat {
if item == .zero {
return ((UIScreen.main.bounds.width - (4*12)) / 4) * 2
}
return (UIScreen.main.bounds.width - (5*12)) / 4
}
func buttonHeight() -> CGFloat {
return (UIScreen.main.bounds.width - (5*12)) / 4
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I expect the program won’t add or subtract numbers right away when I press different operation buttons.
New contributor
Yasmin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.