swift - 如何解决由于强制展开导致的致命意外 nil 错误
问题描述
我刚刚开始学习 swift 的基础知识,并且正在使用 swiftui 制作一个计算器来掌握它。但是,在尝试强制解包变量时,我不断收到错误消息,即发现 nil 值。我知道使用强制展开不是安全的做法,所以我尝试用 if let 语句替换它,但那些只会让我的计算结果变为 0,即它永远不会进入 if let 语句。我的代码逻辑在图片中,任何帮助将不胜感激。
import SwiftUI
struct ContentView: View {
@State private var firstnumber = 0
@State private var secondnumber = 0
@State private var operand = ""
@State private var calctext = "0"
@State private var isTyping = false
var body: some View {
ZStack { Color.black
.edgesIgnoringSafeArea(.all)
VStack(){
TextField("0", text: $calctext)
.padding(EdgeInsets(top: 150, leading: 20, bottom: 20, trailing: 20))
.border(Color.gray, width: 2)
.multilineTextAlignment(.trailing)
.foregroundColor(Color.white)
.font(.largeTitle)
HStack{
createbutton("AC")
.buttonStyle(numberdesign1())
Spacer()
createbutton("+/-")
.buttonStyle(numberdesign1())
Spacer()
createbutton(" % ")
.buttonStyle(numberdesign1())
Spacer()
Button(action: {
self.operandclick("÷")
}) {
Text(" ÷ ")
}
.buttonStyle(buttondesign())
.cornerRadius(15.0)
}.padding()
HStack{
createbutton(" 9 ")
.buttonStyle(numberdesign())
Spacer()
createbutton(" 8 ")
.buttonStyle(numberdesign())
Spacer()
createbutton(" 7 ")
.buttonStyle(numberdesign())
Spacer()
Button(action: {
self.operandclick("×")
}) {
Text(" × ")
}
.buttonStyle(buttondesign())
.cornerRadius(15.0)
}.padding()
HStack{
createbutton(" 6 ")
.buttonStyle(numberdesign())
Spacer()
createbutton(" 5 ")
.buttonStyle(numberdesign())
Spacer()
createbutton(" 4 ")
.buttonStyle(numberdesign())
Spacer()
Button(action: {
self.operandclick("-")
}) {
Text(" - ")
}
.buttonStyle(buttondesign())
.cornerRadius(15.0)
}.padding()
HStack{
createbutton(" 3 ")
.buttonStyle(numberdesign())
Spacer()
createbutton(" 2 ")
.buttonStyle(numberdesign())
Spacer()
createbutton(" 1 ")
.buttonStyle(numberdesign())
Spacer()
Button(action: {
self.operandclick("+")
}) {
Text(" + ")
}
.buttonStyle(buttondesign())
.cornerRadius(15.0)
}.padding()
HStack{
Button(action: {
self.digitTapped("0")
}) {
Text(" 0 ")
}
.foregroundColor(Color.white)
.padding(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
.background(Color.gray)
.border(Color.gray, width: 1)
.cornerRadius(40.0)
Spacer()
createbutton(" . ")
.buttonStyle(numberdesign())
Spacer()
Button(action: {
self.calculate()
}) {
Text(" = ")
}
.buttonStyle(buttondesign())
.cornerRadius(15.0)
}.padding()
}
.aspectRatio(contentMode: .fill)
}
}
private func createbutton(_ number: String) -> Button<Text> {
return Button(action: {
self.digitTapped(number)
}) {
(Text(number))
}
}
private func digitTapped(_ number: String) -> Void {
if isTyping {
calctext += number
} else {
calctext = number
isTyping = true
}
}
private func operandclick(_ operand: String) {
isTyping = false
// if Int(calctext) != nil {
firstnumber = Int(calctext)!
// }
self.operand = operand
calctext = operand
}
private func calculate() {
isTyping = false
var result = 0
// if Int(calctext) != nil {
secondnumber = Int(calctext)!
// }
if operand == "+" {
result = firstnumber + secondnumber
print (result, firstnumber, secondnumber)
} else if operand == "-" {
result = firstnumber - secondnumber
} else if operand == "÷" {
result = firstnumber / secondnumber
} else if operand == "×" {
result = firstnumber * secondnumber
}
calctext = "\(result)"
}
}
struct buttondesign: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundColor(Color.white)
.padding()
.background(LinearGradient(gradient: Gradient(colors: [Color("DarkGreen"),Color("LightGreen")]), startPoint: .leading, endPoint: .trailing))
.clipShape(Circle())
}
}
struct numberdesign: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundColor(Color.white)
.padding(.all)
.background(Color.gray)
.border(Color.gray, width: 1)
.clipShape(Circle().scale(1))
}
}
struct numberdesign1: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundColor(Color.black)
.padding(.all)
.background(Color("LightGray"))
.border(Color.gray, width: 1)
.clipShape(Circle())
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
解决方案
除非您确定它们不包含任何 nil 值,否则不应强制解包选项。
我建议您使用nil coalescing
运算符为字符串的整数转换提供默认值
let firstNumber = Int(calcText) ?? 0
推荐阅读
- javascript - 每次文本更改时如何设置过渡
- sql - SQL CASE 和 JOIN 查询
- r - 绘制三变量折线图
- css - 脉冲时如何将文本保持在页面中间
- haskell - `foldr` 和 `foldl` 的定义中使用了哪些类型的递归?
- android - 在 Android 上用 OpenGL 画一个圆
- react-native - 我在哪里放置带有 expo 的 admob 的应用程序 ID?
- ios - setValue(value, forKey) 以某种方式改变了 Realm 中的整个数组
- java - 如何在没有 spring 框架的情况下读取配置文件 (*.yaml *.properties)
- machine-learning - 如何使用 torchvision.datasets.Imagefolder 将数据拆分为训练集和测试集?