使用状态变量作为 SwiftUI 中函数的输入

mg_*_*erk 5 swift swiftui

我有两个文本字段,用于更改两个 @State 变量(即startingMileage 和endingMileage)的值,以及一个步进器,用于更改名为fuelAdded 的第三个@State 变量的值。我正在尝试使用用户的输入并进行计算来计算每加仑的英里数。在操场上,我的代码按预期工作。但是,它在 SwiftUI 项目中不起作用。

尝试在操场上运行代码如下:

func CalcMPG(start: String, end: String, fuel: Double) -> Int {
    let start = Int(start) ?? 1
    let end = Int(end) ?? 1
    let fuel = Int(fuel)
    let mpg = (end-start) / fuel
    return mpg
}


var endingMileage:String = "9250"
var startingMileage:String = "9000"
var fuelAdded:Double = 20

let milesPerGallon = CalcMPG(start: startingMileage, end: endingMileage, fuel: fuelAdded)
print("Fuel Efficiency: \(milesPerGallon) mpg")
Run Code Online (Sandbox Code Playgroud)

这按预期工作。

struct ContentView : View {

    @State var startingMileage: String = ""
    @State var endingMileage: String = ""
    @State var fuelAdded: Double = 10
    @State var carModel: String = ""
    @State var showMPGInfo = false
    @State var milesPerGallon: Int = 10

    func CalcMPG(start: String, end: String, fuel: Double) -> Int {
        let start = Int(start) ?? 1
        let end = Int(end) ?? 1
        let fuel = Int(fuel)
        let mpg = (end-start) / fuel
        return mpg
    }


    var body: some View {
        NavigationView {
            VStack{
                HStack {
                    Text("Car Model:")
                    Spacer()
                    TextField($carModel, placeholder: Text("Toyota Corolla"))
                        .textFieldStyle(.roundedBorder)
                }
                HStack {
                    Text("Starting ODO:")
                    Spacer()
                    TextField($startingMileage, placeholder: Text("8000"))
                    .textFieldStyle(.roundedBorder)
                    Text("miles")
                }

                HStack {
                    Text("Ending ODO:")
                    Spacer()
                    TextField($endingMileage, placeholder: Text("9000"))
                        .textFieldStyle(.roundedBorder)
                    Text("miles")
                }
                HStack {
                    Stepper(value: $fuelAdded, in: 0...20, step: 0.5) {
                        Text("Fuel Added: \(fuelAdded, specifier: "%0.1f") gallons")
                    }
                }
                Button(action: {
                    self.showMPGInfo.toggle() }){
                        Text("Show/Hide MPG")
                }
                    if showMPGInfo {
                        Spacer()
                        milesPerGallon = CalcMPG(start: startingMileage, end: endingMileage, fuel: fuelAdded)
                        Text("Fuel effiency: \(milesPerGallon) MPG")
                            .font(.largeTitle)
                    }
                }.padding()
                .navigationBarTitle(Text("Gas Mileage Calculator"))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当用户单击“显示/隐藏 MPG”时。我预计最终结果文本为“燃油效率:xx MPG”

但是,我收到以下错误:

ContentView.swift:34:19:无法推断复杂的闭包返回类型;添加显式类型以消除歧义

它对我来说没有任何意义...它突出显示了导航视图中的起始 VStack。

有什么想法吗?

Mar*_*n R 3

问题在于,对 的赋值milesPerGallon与用于构建视图层次结构参数的 \xe2\x80\x9c 函数构建器语法 \xe2\x80\x9d 配合得不好。@State var milesPerGallon如果我们用局部变量替换(也就是说,它不携带视图所依赖的状态,只携带中间值),它会变得更加明显:

\n\n
if showMPGInfo {\n    Spacer()\n    let milesPerGallon = CalcMPG(start: startingMileage,\n                                 end: endingMileage, fuel: fuelAdded)\n    Text("Fuel effiency: \\(milesPerGallon) MPG")\n        .font(.largeTitle)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在编译器错误是

\n\n
\n包含声明的闭包不能与函数生成器 \'ViewBuilder\' 一起使用\n
\n\n

有关函数构建器语法的更多信息,请参阅什么支持 SwiftUI 的 DSL?(其中还有文档的链接)。

\n\n

最简单的解决方案是避免使用局部变量并直接插入文本:

\n\n
if showMPGInfo {\n    Spacer()\n    Text("Fuel effiency: \\(CalcMPG(start: startingMileage, end: endingMileage, fuel: fuelAdded)) MPG")\n        .font(.largeTitle)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

其他解决方案是计算 \xe2\x80\x9c 中的文本字段立即评估闭包\xe2\x80\x9d:

\n\n
if showMPGInfo {\n    Spacer();\n    { () -> Text in\n        let milesPerGallon = CalcMPG(start: startingMileage,\n                                      end: endingMileage,\n                                      fuel: fuelAdded)\n        return Text("Fuel effiency: \\(milesPerGallon) MPG")\n    }()\n    .font(.largeTitle)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

或定义辅助功能

\n\n
func resultField(start: String, end: String, fuel: Double) -> Text {\n    let  milesPerGallon = CalcMPG(start: startingMileage, end: endingMileage, fuel: fuelAdded)\n    return Text("Fuel effiency: \\(milesPerGallon) MPG")\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

并将其用作

\n\n
if showMPGInfo {\n    Spacer()\n    resultField(start: startingMileage, end: endingMileage,\n                fuel: fuelAdded)\n        .font(.largeTitle)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

可能还有其他解决方法,但这就是我到目前为止想到的。

\n