I am still totally new to Swift / SwiftUI and coding in general. I asked this question before but it was closed because it was apparently a duplicate, but (!) this does not account for SwiftUI and I cannot get this thing to work in SwiftUI, because even if I use the suggested NSExpression, I cannot use the result, because it is not a View and I have no idea on how to convert it to a View (see the update at bottom of the question).
I am trying to make a simple converter with a set of predefined conversion from a DataModel. So far I can populate the ContentView and move into a DetailView where I have created a slider which automatically updates a TextView whenever the slider is moved and the whole screen is populated through the DataModel (I hope I explain this the right way).
Now my problem is that every single conversion uses a different calculation obviously. For instance "/ 1000" or "* 50". I have stored these parts as Strings in the DataModel. Now what I'd like to do is to use these Strings in my calculation, but I have no idea how I can include them. Obviously I cannot convert these to Doubles to make a calculation. Here is the code and 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
}
As you can see "calc" is of type String. I am also using "range" which I defined with 0.0...0.0 because I didn't know how I could initialize it otherwise (I always got an error because of a closed range (?) so this is what I cam up with to silence the error.
Here is an example of some data:
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"
),
...
...
As you can see I have changed the range to "0.0...200" because the slider shouldn't go beyond 200. I have entered the part of the calculation "/ 1000" into calc. This is the thing I'd like to add to the calculation in the DetailView (see below). I am not using the rest of the data right now, because I am still stuck with this calculation.
Code:
@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()
}
As you can see I use "conversion.range" to specify the exact range for the slider. Here is the calculation:
private func calculatedView(for value: Double) -> some View {
Text("\(value / 1000, specifier: "%.2f")")
.font(.system(size: 60, weight: .bold))
}
}
Update:
So what I did was to try to use NSExpression in calculatedView:
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))
}
I am not even sure if this is the way to use NSExpression. I am trying to create a string from the value of the slider and add conversion.calc. It should look something like this: 125.5 / 1000 (just as an example). I am not sure if this is right in the first place. Now I try to use NSExpression and store the result in the variable result and this variable should be shown as a TextView. I get two error messages:
- Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type
And for Text(result): 2. No exact matches in call to initializer
Question
Right now I just add the value and hard-code the "/ 1000" in. What I'd like to change is instead use converter.calc (which is "/ 1000). But obviously when I just add this the whole calculation is broken, but I have no idea how the re-format the whole thing so that it works. Before I would have just created a switch statement (or something else) with a new calculation for each conversion, which would blow up the whole code.
I really hope someone can point me into the right direction, because I am so happy that I have finally understood how to use a simple DataModel.
Thanks for reading and for any tip. With best regards!