【问题标题】:Using state variables as inputs to a func in SwiftUI在 SwiftUI 中使用状态变量作为函数的输入
【发布时间】:2019-06-16 05:35:50
【问题描述】:

我有两个文本字段可以更改两个@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")

这按预期工作。

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

当用户点击“显示/隐藏 MPG”时。我希望最终生成的文本是“燃料效率:xx MPG”

但是,我收到以下错误:

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

它对我来说没有任何意义...它突出显示 NavigationView 中的起始 VStack。

有什么想法吗?

【问题讨论】:

  • 好的,这一定与milesPerGallon = CalcMPG(...) 的声明有关,因为只要我把它拿出来并把 (CalcMPG(...)) 放入我想要返回的文本中它可以按需要工作。有人知道我在这里做错了什么吗?在这种情况下使用 @State 变量是不是不对?

标签: swift swiftui


【解决方案1】:

问题在于milesPerGallon 的赋值不能很好地与用于构建视图层次结构参数的“函数构建器语法”一起使用。如果我们将@State var milesPerGallon 替换为局部变量(即is,它不携带视图所依赖的状态,只有一个中间值),就会变得更加明显:

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

现在编译错误是

包含声明的闭包不能与函数生成器“ViewBuilder”一起使用

有关函数构建器语法的更多信息,请参阅What enables SwiftUI's DSL?(其中还包含指向文档的链接)。

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

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

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

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

或者定义一个辅助函数

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

并将其用作

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多