【问题标题】:SwiftUI: How to combine a Double with a String and do a math calculation?SwiftUI:如何将 Double 与 String 组合并进行数学计算?
【发布时间】:2020-08-04 13:20:06
【问题描述】:

我对 Swift / SwiftUI 和一般编码仍然是全新的。 我之前问过这个问题,但它被关闭了,因为它显然是重复的,但是(!)这并不能解释 SwiftUI,我无法让这个东西在 SwiftUI 中工作,因为即使我使用建议的 NSExpression,我也不能使用结果,因为它不是视图,我不知道如何将其转换为视图(请参阅问题底部的更新)。

我正在尝试使用一组来自 DataModel 的预定义转换来制作一个简单的转换器。到目前为止,我可以填充 ContentView 并移动到 DetailView 中,在那里我创建了一个滑块,该滑块在移动滑块时自动更新 TextView 并且通过 DataModel 填充整个屏幕(我希望我以正确的方式解释这一点)。

现在我的问题是,每次转换显然都使用不同的计算。例如“/ 1000”或“* 50”。我已将这些部分作为字符串存储在 DataModel 中。现在我想做的是在我的计算中使用这些字符串,但我不知道如何包含它们。显然,我无法将这些转换为双精度数来进行计算。这是代码和DataModel:

数据模型:

struct Converter: Identifiable {
    var id = UUID()
    var title: String
    var range = 0.0...0.0
    var calc: String
    var sliderValue: Double

    var color: [Color]
    var description: String
}

如您所见,“calc”是字符串类型。我也在使用我用 0.0...0.0 定义的“范围”,因为我不知道如何初始化它(由于范围封闭(?),我总是遇到错误,所以这就是我想出来的使错误静音。

以下是一些数据的示例:

let converterData: [Converter] = [
    Converter(
        title: "Conversion1",
        range: 0.0...200,
        calc: "/ 1000",
        sliderValue: 0.0,
        color: [Color.blue, Color.red],
        description: "This is conversion 1"
     ),
...
...

如您所见,我已将范围更改为“0.0...200”,因为滑块不应超过 200。我已将计算部分“/1000”输入到 calc 中。这是我想添加到 DetailView 计算中的内容(见下文)。我现在没有使用其余的数据,因为我仍然坚持这个计算。

代码:

@State var sliderValue: Double = 0.0
var conversion: Converter

var body: some View {
    VStack(alignment: .leading) {
        VStack(alignment: .leading) {
            Text("value1".uppercased())
                .font(.largeTitle)
                .fontWeight(.bold)
            Text("\(sliderValue, specifier: "%.2f")")
                .font(.system(size: 60, weight: .bold))
            Text("to value2".uppercased())
                .font(.largeTitle)
                .fontWeight(.bold)
        
            self.calculatedView(for: sliderValue)
        }
    
        Slider(value: $sliderValue, in: conversion.range, step: 0.5)
            .padding(8)
            .overlay(
                Capsule()
                    .stroke(Color.purple, style: StrokeStyle(lineWidth: 5))
            )
    }
    .padding()
}

如您所见,我使用“conversion.range”来指定滑块的确切范围。这是计算:

private func calculatedView(for value: Double) -> some View {
    Text("\(value / 1000, specifier: "%.2f")")
        .font(.system(size: 60, weight: .bold))
    }
}

更新:

所以我所做的是尝试在计算视图中使用 NSExpression:

private func calculatedView(for value: Double) -> some View {
    
    let calculation = String(value) + conversion.calc
    let expn = NSExpression(format:calculation)
    let result = expn.expressionValue(with: nil, context: nil)
    
    Text(result)
        .font(.system(size: 60, weight: .bold))
}

我什至不确定这是否是使用 NSExpression 的方式。我正在尝试从滑块的值创建一个字符串并添加conversion.calc。它应该看起来像这样:125.5 / 1000(仅作为示例)。我不确定这首先是否正确。 现在我尝试使用 NSExpression 并将结果存储在变量 result 中,并且该变量应显示为 TextView。我收到两条错误消息:

  1. 函数声明了一个不透明的返回类型,但它的主体中没有返回语句来推断基础类型

对于文本(结果): 2. 初始化器调用没有完全匹配

问题

现在我只是添加值并将“/ 1000”硬编码。我想更改的是使用converter.calc(即“/ 1000”)。但显然当我添加这个时整个计算被破坏了,但我不知道如何重新格式化整个事情以便它工作.在我刚刚创建一个 switch 语句(或其他东西)之前,每个转换都有一个新的计算,这会炸毁整个代码。

我真的希望有人能指出我正确的方向,因为我很高兴我终于明白了如何使用一个简单的 DataModel。

感谢您的阅读和任何提示。致以最诚挚的问候!

【问题讨论】:

    标签: string type-conversion swiftui string-interpolation nsexpression


    【解决方案1】:

    而是让 Converter 中的 calc 属性持有一个闭包。这样,您可以在初始化 Converter 时传入任何类型的转换函数(通过传入转换闭包)。在 Double 中执行所有计算(作为数字),然后转换为 String 进行显示。

    Here is a link to Closures at Swift.org

    尝试使用字符串和数字进行数学运算将是一团糟。

    EDIT使用闭包的简单示例

    除了 calc 变量外,其他都一样

    struct Converter {
        var calc: ((Double) -> Double)
    }
    

    用法

    let closure: ((Double) -> Double) = { num in
            return num / 1000
    }
    
    let converter = Converter(calc: closure)
    
    print("Conversion result: \(converter.calc(500))")
    

    您可以将任何类型的计算方法传递给转换器,或者您可以在结构本身中对方法进行硬处理,然后调用 calc,它将自动获取结构中的任何变量。

    但是对于您的问题,而不是 CalculatedView 函数:

    VStack(alignment: .leading) {
            Text("value1".uppercased())
                .font(.largeTitle)
                .fontWeight(.bold)
            Text("\(sliderValue, specifier: "%.2f")")
                .font(.system(size: 60, weight: .bold))
            Text("to value2".uppercased())
                .font(.largeTitle)
                .fontWeight(.bold)
        
            Text("\(conversion.calc(sliderValue))")
                .font(.system(size: 60, weight: .bold))
        }
    

    【讨论】:

    • 我昨天晚上试过这个,但我无法让它工作。你对如何用闭包来完成这个有什么建议吗?非常感谢。提醒你我还是新手。
    猜你喜欢
    • 2017-12-29
    • 1970-01-01
    • 2019-01-31
    • 2018-08-26
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 2022-01-17
    相关资源
    最近更新 更多