Swiftui 计算器 连续计算
Swiftui Calculator Continuous calculation
我想在我的应用程序中练习真正的ios计算器并且可以连续计算
当我点击添加按钮时,我想可以 calculated.But 现在当我点击添加时我的值无法真正自动计算 button.I 不知道这个问题。
我应该如何更改我的代码?
这是我的 ContentView.swift:
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 value = "0"
@State var runningNumber = 0
@State var currentOperation: Operation = .none
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(value)
.bold()
.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: {
self.didTap(button: item)
}, label: {
Text(item.rawValue)
.font(.system(size: 32))
.frame(
width: self.buttonWidth(item: item),
height: self.buttonHeight()
)
.background(item.buttonColor)
.foregroundColor(.white)
.cornerRadius(self.buttonWidth(item: item)/2)
})
}
}
.padding(.bottom, 3)
}
}
}
}
func didTap(button: CalcButton) {
switch button {
case .add, .subtract, .mutliply, .divide, .equal:
if button == .add {
self.currentOperation = .add
self.runningNumber = Int(self.value) ?? 0
self.value = "\(runningNumber + Int(self.value) ?? 0)"
}
else if button == .subtract {
self.currentOperation = .subtract
self.runningNumber = Int(self.value) ?? 0
}
else if button == .mutliply {
self.currentOperation = .multiply
self.runningNumber = Int(self.value) ?? 0
}
else if button == .divide {
self.currentOperation = .divide
self.runningNumber = Int(self.value) ?? 0
}
else if button == .equal {
let runningValue = self.runningNumber
let currentValue = Int(self.value) ?? 0
switch self.currentOperation {
case .add: self.value = "\(runningValue + currentValue)"
case .subtract: self.value = "\(runningValue - currentValue)"
case .multiply: self.value = "\(runningValue * currentValue)"
case .divide: self.value = "\(runningValue / currentValue)"
case .none:
break
}
}
if button != .equal {
self.value = "0"
}
case .clear:
self.value = "0"
case .decimal, .negative, .percent:
break
default:
let number = button.rawValue
if self.value == "0" {
value = number
}
else {
self.value = "\(self.value)\(number)"
}
}
}
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()
}
}
这比预期的要棘手。当您按下一个运算符(+、-、* 等)时,常规计算器也会显示部分结果 – 不仅在“=”上。
所以每次点击运算符,你都必须计算partialResult。
我不得不引入一个新的变量 AwaitingNewNumberInput
来处理这种情况,您看到的是部分结果,但是当按下一个数字时,您开始输入一个新的数字。
对不起,但为了更清楚(至少对我自己而言),我还重命名了变量。我将所有计算变量都保留为 Int 以减少从 String 的转换。
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
}
}
我想在我的应用程序中练习真正的ios计算器并且可以连续计算
当我点击添加按钮时,我想可以 calculated.But 现在当我点击添加时我的值无法真正自动计算 button.I 不知道这个问题。
我应该如何更改我的代码?
这是我的 ContentView.swift:
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 value = "0"
@State var runningNumber = 0
@State var currentOperation: Operation = .none
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(value)
.bold()
.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: {
self.didTap(button: item)
}, label: {
Text(item.rawValue)
.font(.system(size: 32))
.frame(
width: self.buttonWidth(item: item),
height: self.buttonHeight()
)
.background(item.buttonColor)
.foregroundColor(.white)
.cornerRadius(self.buttonWidth(item: item)/2)
})
}
}
.padding(.bottom, 3)
}
}
}
}
func didTap(button: CalcButton) {
switch button {
case .add, .subtract, .mutliply, .divide, .equal:
if button == .add {
self.currentOperation = .add
self.runningNumber = Int(self.value) ?? 0
self.value = "\(runningNumber + Int(self.value) ?? 0)"
}
else if button == .subtract {
self.currentOperation = .subtract
self.runningNumber = Int(self.value) ?? 0
}
else if button == .mutliply {
self.currentOperation = .multiply
self.runningNumber = Int(self.value) ?? 0
}
else if button == .divide {
self.currentOperation = .divide
self.runningNumber = Int(self.value) ?? 0
}
else if button == .equal {
let runningValue = self.runningNumber
let currentValue = Int(self.value) ?? 0
switch self.currentOperation {
case .add: self.value = "\(runningValue + currentValue)"
case .subtract: self.value = "\(runningValue - currentValue)"
case .multiply: self.value = "\(runningValue * currentValue)"
case .divide: self.value = "\(runningValue / currentValue)"
case .none:
break
}
}
if button != .equal {
self.value = "0"
}
case .clear:
self.value = "0"
case .decimal, .negative, .percent:
break
default:
let number = button.rawValue
if self.value == "0" {
value = number
}
else {
self.value = "\(self.value)\(number)"
}
}
}
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()
}
}
这比预期的要棘手。当您按下一个运算符(+、-、* 等)时,常规计算器也会显示部分结果 – 不仅在“=”上。 所以每次点击运算符,你都必须计算partialResult。
我不得不引入一个新的变量 AwaitingNewNumberInput
来处理这种情况,您看到的是部分结果,但是当按下一个数字时,您开始输入一个新的数字。
对不起,但为了更清楚(至少对我自己而言),我还重命名了变量。我将所有计算变量都保留为 Int 以减少从 String 的转换。
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
}
}