问题描述
我正在尝试创建一个简单的小费计算器,但是一旦用户在应用程序中添加了信息而不是计算小费,我就会遇到问题,该函数正在返回,好像某处有问题一样。
我试图做到这一点,当用户在文本字段中输入一个数字并选择一个百分比时,总提示会显示在下方。
我该如何解决这个问题? 我添加了一个打印语句来打印“返回”这个词,并且它一直在打印这个词,所以我认为问题出在calculateTip 函数中:
这是我的 ContentView 类的代码:
struct ContentView: View {
//MARK: - PROPERTIES
@Observedobject public var tipVM = Tipviewmodel()
//MARK: - FUNCTIONS
private func endEditing() {
hideKeyboard()
}
//MARK: - BODY
var body: some View {
Background {
NavigationView {
ZStack {
vstack {
HStack(spacing: 10) {
Text("Tip Calculator")
.font(.system(.largeTitle,design: .rounded))
.fontWeight(.heavy)
.padding(.leading,4)
.foregroundColor(.blue)
Spacer()
Button(action: {
// tipVM.clearFields()
},label: {
Text("Clear")
.font(.system(size: 16,weight: .semibold,design: .rounded))
.padding(.horizontal,10)
.frame(minWidth: 70,minHeight: 24)
.background(
Capsule().stroke(linewidth: 2)
)
.foregroundColor(.blue)
}) //: BUTTON
} //: HSTACK
.padding()
Spacer(minLength: 80)
TextField("Enter Amount: ",text: $tipVM.amount)
.padding()
.background(Color.secondary)
.foregroundColor(.white)
.font(.system(.title3,design: .rounded))
Picker(selection: $tipVM.tipPercentage,label: Text("Picker"),content: {
ForEach(0 ..< tipVM.tipChoices.count) { index in
Text("\(self.tipVM.tipChoices[index])%").tag(index)
.font(.system(.body,design: .rounded)).padding()
}.padding()
.background(subtitleColor)
.foregroundColor(.white)
}).onTapGesture(perform: {
tipVM.calculateTip()
})
.pickerStyle(SegmentedPickerStyle())
Text(tipVM.tip == nil ? "£0" : "\(tipVM.tip!)")
.font(.system(.largeTitle,design: .rounded))
.fontWeight(.bold)
.foregroundColor(.blue)
.padding()
} //: vstaCK
} //: ZSTACK
.navigationBarHidden(true)
} //: NAVIGATION VIEW
.navigationViewStyle(StackNavigationViewStyle())
}.onTapGesture {
self.endEditing()
}
.ignoresSafeArea(.keyboard,edges: .all)
} //: BACKGROUND
}
import Foundation
import SwiftUI
import Combine
class Tipviewmodel: ObservableObject {
var amount: String = ""
var tipPercentage: Int = 0
var tip: Double?
let tipChoices = [10,15,20,25,30]
let didChange = PassthroughSubject<Tipviewmodel,Never>()
func calculateTip() {
guard let amount = Double(amount) else {
print("returning")
return
}
self.tip = amount * (Double(tipPercentage)/100)
self.didChange.send(self)
}
}
如果有任何帮助,我将不胜感激。
解决方法
通常的方法是用 @Published
标记属性,其更改将被监控。不需要额外的 Combine
主题。
并声明 tip
为非可选
import Foundation
import SwiftUI
// import Combine
class TipViewModel: ObservableObject {
var amount: String = ""
var tipPercentage: Int = 0
@Published var tip = 0.0
let tipChoices = [10,15,20,25,30]
func calculateTip() {
guard let numAmount = Double(amount) else {
print("returning")
return
}
self.tip = numAmount * (Double(tipPercentage)/100)
}
}
其次,如果当前视图结构创建(也称为拥有)可观察对象,则始终使用 @StateObject
而不是 @ObservedObject
。后者用于在视图层次结构中的更高级别初始化并刚刚通过的对象。
struct ContentView: View {
//MARK: - PROPERTIES
@StatedObject private var tipVM = TipViewModel()
...
Text("£\(tipVM.tip)")