如何基于超过 1 个状态创建动态计算
How to create a dynamic calculation based off more than 1 State
我是 Swift 的新手(一般来说是编码)。我正在开发一个应用程序,该应用程序将根据对两个状态的跟踪输出计算结果。这两个状态是 brewModel 和 waterAmount。我能够成功创建一个函数,该函数将 return 基于两种状态进行一次计算。但是,现在我正在尝试创建一个选择器,它将在两个测量值(克和汤匙)之间切换计算。这是我遇到问题的地方。
我尝试用不同的方式编写一系列条件语句,例如 if 和 else if 以及 switch cases,但它不起作用。当我构建模拟器时,Xcode 只会思考很长时间,直到我停止它。有时我会在手动停止后收到错误消息,有时却不会。今天我收到“命令编译Swift来源失败,退出代码非零。”
有人有什么建议吗?
此外,如果我的代码混乱,我深表歉意,我有一堆我正在玩的东西被注释掉了。 func computeGrinds 确实有效,但仅用于一次计算。谢谢!
import SwiftUI
struct Water: View {
// @EnvironmentObject var favorites: Favorites
@State var animationInProgress = true
@State var brewModel: BrewModel
@State var waterAmount: Int = 1
@State var grindsSelection = "tbsp"
var grindOptions = ["tbsp", "grams"]
// var resultGrindCalc: Double {
//
// var value = Double(0)
// }
// switch grindsSelection {
// case "tbsp" || brewModel.frenchPress:
// value = Double(waterAmount) * 2.5
//
// }
//
// func computeGrinds () -> Double {
// switch brewModel {
// case .frenchPress, .chemex:
// return (2.5 * Double(waterAmount))
// case .drip :
// return Double(2 * Double(waterAmount))
// case .mokaPot:
// return Double(1 * Double(waterAmount))
// case .aeroPress:
// return Double(1.6 * Double(waterAmount))
// // default:
// // return(1 * Double(waterAmount))
// }
// }
var body: some View {
VStack (spacing: 5) {
Spacer()
HStack {
// Text("").padding(20)
Text("How many cups do you want to brew?")
Picker("", selection: $waterAmount) {
ForEach(1...15, id: \.self){
Text("\([=10=])")
}
}
// Spacer()
}.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color("Custom Color"), lineWidth: 8)
)
// gif/image conditionals
if (brewModel == .frenchPress) {
LottieView(name: "frenchpress", loopMode: .loop)
} else if brewModel == .chemex {
LottieView(name: "pourover", loopMode: .loop)
} else if brewModel == .aeroPress {
LottieView(name: "aeropress", loopMode: .loop)
} else if brewModel == .mokaPot {
LottieView(name: "mokapot", loopMode: .loop)
} else if brewModel == .drip {
Image("Drip")
.resizable()
.scaledToFit()
}
// I would have more conditionals but testing with just these two for now
var testingCalcCond = Double
if (brewModel == .frenchPress)||(grindsSelection=="tbsp") {
testingCalcCond = (2.5 * Double(waterAmount))
} else if (brewModel == .frenchPress)||(grindsSelection=="grams") {
testingCalcCond = (16 * Double(waterAmount))
}
let formatted = String(format: "%.2f", testingCalcCond)
// let formatted = String(format: "%.2f", computeGrinds())
HStack {
Text("**\(formatted)**")
Picker("Select Grinds Units: ", selection: $grindsSelection, content: {
ForEach(grindOptions, id: \.self) {
Text([=10=])
}
}).onChange(of: grindsSelection) { _ in computeGrinds() }
Text("of coffee grinds needed")
}
.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color("Custom Color"), lineWidth: 8)
)
}
Spacer()
}
}
struct Water_Previews: PreviewProvider {
static var previews: some View {
Water(brewModel: .drip)
}
}
}
*我正在使用 Xcode 13.2.1
*我正在使用 swiftUI
您需要考虑两个方面:
1.如何根据输入更新结果值。
您的结果值基于两个输入:brewModel 和 waterAmount。两者都是@State 变量并由选择器更改。
我将您的 computeGrinds func 更改为计算 属性,因为当两个基值之一发生变化时将自动调用它。然后就不再需要 .onchange 了,你可以只使用 var 值——它总是最新的。
2。从汤匙重新计算为克。
这更像是一个数学问题:据我了解,对于 .frenchPress,您需要每杯 2.5 汤匙或 16 克。所以 1 汤匙 = 16 / 2.5 = 6.4 克。一旦你知道你只需要通过一次 switch case,然后使用 unitValue 重新计算。我也整合了它 ;)
这是我的简化代码:
enum BrewModel {
case frenchPress
case chemex
case drip
case mokaPot
case aeroPress
}
struct ContentView: View {
@State var animationInProgress = true
@State var brewModel: BrewModel = .frenchPress
@State var waterAmount: Int = 1
@State var grindsSelection = "tbsp"
let grindOptions = ["tbsp", "grams"]
// computed var instead of func, does the same
var computeGrinds: Double {
// transforms tbsp = 1 to grams (= 6.4 ?)
var unitValue: Double = 1.0
if grindsSelection == "grams" {
unitValue = 6.4
}
switch brewModel {
case .frenchPress, .chemex:
return (2.5 * unitValue * Double(waterAmount))
case .drip :
return Double(2 * unitValue * Double(waterAmount))
case .mokaPot:
return Double(1 * unitValue * Double(waterAmount))
case .aeroPress:
return Double(1.6 * unitValue * Double(waterAmount))
}
}
var body: some View {
VStack (spacing: 5) {
HStack {
Text("How many cups do you want to brew?")
Picker("", selection: $waterAmount) {
ForEach(1...15, id: \.self){
Text("\([=10=])")
}
}
}
.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color.brown, lineWidth: 8)
)
.padding(.bottom)
let formatted = String(format: "%.2f", computeGrinds)
HStack {
Text("**\(formatted)**")
Picker("Select Grinds Units: ", selection: $grindsSelection, content: {
ForEach(grindOptions, id: \.self) {
Text([=10=])
}
})
Text("of coffee grinds needed")
}
.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color.brown, lineWidth: 8)
)
}
}
}
我是 Swift 的新手(一般来说是编码)。我正在开发一个应用程序,该应用程序将根据对两个状态的跟踪输出计算结果。这两个状态是 brewModel 和 waterAmount。我能够成功创建一个函数,该函数将 return 基于两种状态进行一次计算。但是,现在我正在尝试创建一个选择器,它将在两个测量值(克和汤匙)之间切换计算。这是我遇到问题的地方。
我尝试用不同的方式编写一系列条件语句,例如 if 和 else if 以及 switch cases,但它不起作用。当我构建模拟器时,Xcode 只会思考很长时间,直到我停止它。有时我会在手动停止后收到错误消息,有时却不会。今天我收到“命令编译Swift来源失败,退出代码非零。”
有人有什么建议吗?
此外,如果我的代码混乱,我深表歉意,我有一堆我正在玩的东西被注释掉了。 func computeGrinds 确实有效,但仅用于一次计算。谢谢!
import SwiftUI
struct Water: View {
// @EnvironmentObject var favorites: Favorites
@State var animationInProgress = true
@State var brewModel: BrewModel
@State var waterAmount: Int = 1
@State var grindsSelection = "tbsp"
var grindOptions = ["tbsp", "grams"]
// var resultGrindCalc: Double {
//
// var value = Double(0)
// }
// switch grindsSelection {
// case "tbsp" || brewModel.frenchPress:
// value = Double(waterAmount) * 2.5
//
// }
//
// func computeGrinds () -> Double {
// switch brewModel {
// case .frenchPress, .chemex:
// return (2.5 * Double(waterAmount))
// case .drip :
// return Double(2 * Double(waterAmount))
// case .mokaPot:
// return Double(1 * Double(waterAmount))
// case .aeroPress:
// return Double(1.6 * Double(waterAmount))
// // default:
// // return(1 * Double(waterAmount))
// }
// }
var body: some View {
VStack (spacing: 5) {
Spacer()
HStack {
// Text("").padding(20)
Text("How many cups do you want to brew?")
Picker("", selection: $waterAmount) {
ForEach(1...15, id: \.self){
Text("\([=10=])")
}
}
// Spacer()
}.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color("Custom Color"), lineWidth: 8)
)
// gif/image conditionals
if (brewModel == .frenchPress) {
LottieView(name: "frenchpress", loopMode: .loop)
} else if brewModel == .chemex {
LottieView(name: "pourover", loopMode: .loop)
} else if brewModel == .aeroPress {
LottieView(name: "aeropress", loopMode: .loop)
} else if brewModel == .mokaPot {
LottieView(name: "mokapot", loopMode: .loop)
} else if brewModel == .drip {
Image("Drip")
.resizable()
.scaledToFit()
}
// I would have more conditionals but testing with just these two for now
var testingCalcCond = Double
if (brewModel == .frenchPress)||(grindsSelection=="tbsp") {
testingCalcCond = (2.5 * Double(waterAmount))
} else if (brewModel == .frenchPress)||(grindsSelection=="grams") {
testingCalcCond = (16 * Double(waterAmount))
}
let formatted = String(format: "%.2f", testingCalcCond)
// let formatted = String(format: "%.2f", computeGrinds())
HStack {
Text("**\(formatted)**")
Picker("Select Grinds Units: ", selection: $grindsSelection, content: {
ForEach(grindOptions, id: \.self) {
Text([=10=])
}
}).onChange(of: grindsSelection) { _ in computeGrinds() }
Text("of coffee grinds needed")
}
.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color("Custom Color"), lineWidth: 8)
)
}
Spacer()
}
}
struct Water_Previews: PreviewProvider {
static var previews: some View {
Water(brewModel: .drip)
}
}
}
*我正在使用 Xcode 13.2.1 *我正在使用 swiftUI
您需要考虑两个方面:
1.如何根据输入更新结果值。
您的结果值基于两个输入:brewModel 和 waterAmount。两者都是@State 变量并由选择器更改。
我将您的 computeGrinds func 更改为计算 属性,因为当两个基值之一发生变化时将自动调用它。然后就不再需要 .onchange 了,你可以只使用 var 值——它总是最新的。
2。从汤匙重新计算为克。
这更像是一个数学问题:据我了解,对于 .frenchPress,您需要每杯 2.5 汤匙或 16 克。所以 1 汤匙 = 16 / 2.5 = 6.4 克。一旦你知道你只需要通过一次 switch case,然后使用 unitValue 重新计算。我也整合了它 ;)
这是我的简化代码:
enum BrewModel {
case frenchPress
case chemex
case drip
case mokaPot
case aeroPress
}
struct ContentView: View {
@State var animationInProgress = true
@State var brewModel: BrewModel = .frenchPress
@State var waterAmount: Int = 1
@State var grindsSelection = "tbsp"
let grindOptions = ["tbsp", "grams"]
// computed var instead of func, does the same
var computeGrinds: Double {
// transforms tbsp = 1 to grams (= 6.4 ?)
var unitValue: Double = 1.0
if grindsSelection == "grams" {
unitValue = 6.4
}
switch brewModel {
case .frenchPress, .chemex:
return (2.5 * unitValue * Double(waterAmount))
case .drip :
return Double(2 * unitValue * Double(waterAmount))
case .mokaPot:
return Double(1 * unitValue * Double(waterAmount))
case .aeroPress:
return Double(1.6 * unitValue * Double(waterAmount))
}
}
var body: some View {
VStack (spacing: 5) {
HStack {
Text("How many cups do you want to brew?")
Picker("", selection: $waterAmount) {
ForEach(1...15, id: \.self){
Text("\([=10=])")
}
}
}
.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color.brown, lineWidth: 8)
)
.padding(.bottom)
let formatted = String(format: "%.2f", computeGrinds)
HStack {
Text("**\(formatted)**")
Picker("Select Grinds Units: ", selection: $grindsSelection, content: {
ForEach(grindOptions, id: \.self) {
Text([=10=])
}
})
Text("of coffee grinds needed")
}
.padding()
.overlay (
RoundedRectangle(cornerRadius: 16)
.stroke(Color.brown, lineWidth: 8)
)
}
}
}