在 SwiftUI 中使用状态变量作为 func 的输入 [英] Using state variables as inputs to a func in SwiftUI

查看:47
本文介绍了在 SwiftUI 中使用状态变量作为 func 的输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

func CalcMPG(start: String, end: String,fuel: Double) ->整数{让开始 = Int(start) ??1让结束 = Int(end) ??1让燃料= Int(燃料)让 mpg = (end-start)/燃料返回 mpg}var endMileage:String = "9250"变量开始里程:字符串=9000"添加 var 燃料:双 = 20让milesPerGallon = CalcMPG(开始:开始里程,结束:结束里程,燃料:燃料添加)打印(燃油效率:\(英里每加仑)英里")

这按预期工作.

struct ContentView : View {@State varstartingMileage: String = ""@State varendingMileage: String = ""@State varfuelAdded:双= 10@State var carModel: String = ""@State var showMPGInfo = false@State varmilesPerGallon:Int = 10func CalcMPG(开始:字符串,结束:字符串,燃料:双)->整数{让开始 = Int(start) ??1让结束 = Int(end) ??1让燃料= Int(燃料)让 mpg = (end-start)/燃料返回 mpg}var主体:一些视图{导航视图{虚拟堆栈{堆栈{Text("车型:")垫片()TextField($carModel, placeholder: Text("Toyota Corolla")).textFieldStyle(.roundedBorder)}堆栈{Text("开始ODO:")垫片()文本字段($startingMileage,占位符:文本(8000")).textFieldStyle(.roundedBorder)文本(英里")}堆栈{Text("结束ODO:")垫片()文本字段($endingMileage,占位符:文本(9000")).textFieldStyle(.roundedBorder)文本(英里")}堆栈{Stepper(value: $fuelAdded, in: 0...20, step: 0.5) {文本(燃料添加:\(燃料添加,说明符:%0.1f")加仑)}}按钮(动作:{self.showMPGInfo.toggle() }){Text("显示/隐藏 MPG")}如果显示MPGInfo {垫片()英里每加仑 = CalcMPG(开始:开始里程,结束:结束里程,燃料:燃料添加)Text("燃油效率:\(milesPerGallon) MPG").font(.largeTitle)}}.填充().navigationBarTitle(Text("Gas Mileage Calculator"))}}}

当用户点击显示/隐藏 MPG"时.我希望最终得到的文本是燃油效率:xx MPG"

但是,我收到以下错误:

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

它在我看来没有任何意义...它突出显示了 NavigationView 中的起始 VStack.

有什么想法吗?

解决方案

问题是对 milesPerGallon 的赋值不能很好地与用于构建参数的函数构建器语法"配合使用查看层次结构.如果我们将 @State varmilesPerGallon 替换为一个局部变量(也就是 is, 它不携带视图所依赖的状态,只是一个中间变量),这会变得更加明显值):

if showMPGInfo {垫片()让milesPerGallon = CalcMPG(start:startingMileage,结束:结束里程,燃料:燃料添加)Text("燃油效率:\(milesPerGallon) MPG").font(.largeTitle)}

现在编译错误是

<前>包含声明的闭包不能与函数构建器ViewBuilder"一起使用

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

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

if showMPGInfo {垫片()文本(燃油效率:\(CalcMPG(开始:开始里程,结束:结束里程,燃料:燃料添加))MPG").font(.largeTitle)}

其他解决方案是在立即评估的闭包"中计算文本字段:

if showMPGInfo {间隔();{ () ->文本输入让milesPerGallon = CalcMPG(start:startingMileage,结束:结束里程,燃料:燃料添加)return Text("燃油效率:\(milesPerGallon) MPG")}().font(.largeTitle)}

或者定义一个辅助函数

func resultField(start: String, end: String,fuel: Double) ->文本 {让milesPerGallon = CalcMPG(开始:开始里程,结束:结束里程,燃料:燃料添加)return Text("燃油效率:\(milesPerGallon) MPG")}

并将其用作

if showMPGInfo {垫片()结果字段(开始:开始里程,结束:结束里程,燃料:燃料添加).font(.largeTitle)}

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

I have two text fields that change the value of two @State variables, namely startingMileage and endingMileage, and a stepper that changes the value of a third @State variable named fuelAdded. I'm trying to use the user's inputs and do a calculation to calculate miles per gallon. In playground, my code works as expected. It does not work in a SwiftUI project, however.

Tried running the code in playground as below:

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")

This works as expected.

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"))
        }
    }
}

When the user clicks on "Show/Hide MPG". I expect the end resulting text to be "Fuel Efficiency: xx MPG"

However, I get the following errors:

ContentView.swift:34:19: Unable to infer complex closure return type; add explicit type to disambiguate

It doesn't appear anywhere sensical to me... It highlights the starting VStack in the NavigationView.

Any thoughts?

解决方案

The problem is that the assignment to milesPerGallon does not work well with the "function builder syntax" used to build the arguments of the view hierarchy. It becomes a bit more obvious if we replace @State var milesPerGallon by a local variable (which is is, it does not carry state on which the view depends, only a intermediate value):

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

Now the compiler error is

Closure containing a declaration cannot be used with function builder 'ViewBuilder'

For more information about the function builder syntax see What enables SwiftUI's DSL? (which has also links to the documentation).

The simplest solution would be to avoid a local variable and interpolate the text directly:

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

Other solutions are to calculate the text field in an "immediately evaluated closure":

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

or to define an auxiliary function

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

and use it as

if showMPGInfo {
    Spacer()
    resultField(start: startingMileage, end: endingMileage,
                fuel: fuelAdded)
        .font(.largeTitle)
}

There may be other workarounds, but that is what I came up with so far.

这篇关于在 SwiftUI 中使用状态变量作为 func 的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆