Reputation: 1172
I'm trying to understand how to transform value from model to view. For example, I have a model:
struct BloodPressure {
var systolic: Int = 0
var diastolic: Int = 0
}
And I have a view:
struct MeasurementsTabView: View {
@State private var bloodPressure = BloodPressure()
var body: some View {
VStack {
TextField("Systolic", text: $bloodPressure.systolic)
TextField("Diastolic", text: $bloodPressure.diastolic)
}
}
}
There is an error, because text
parameter should be a string, but bloodPressure.systolic
is Int
.
I found a solution, but I think that isn't elegant:
var body: some View {
let systolicBinding = Binding <String> (
get: { String(self.bloodPressure.systolic) },
set: {
if let int = Int($0) {
self.bloodPressure.systolic = int
}
})
let diastolicBinding = Binding <String> (
get: { String(self.bloodPressure.diastolic) },
set: {
if let int = Int($0) {
self.bloodPressure.diastolic = int
}
})
return VStack {
TextField("Systolic", text: systolicBinding)
TextField("Diastolic", text: diastolicBinding)
}
}
How you solve similar issues?
Upvotes: 1
Views: 453
Reputation: 257563
In this case I recommend to introduce ViewModel layer, so BloodPressure remains pure model.
Below is simplified demo of concept (eg. formatting/validation of text fields is out of scope, etc.)
import SwiftUI
import Combine
struct BloodPressure {
var systolic: Int = 0
var diastolic: Int = 0
}
class BloodPressureViewModel: ObservableObject {
var model: BloodPressure
init(_ model: BloodPressure) {
self.systolic = String(model.systolic)
self.diastolic = String(model.diastolic)
self.model = model
}
@Published var systolic: String = "" {
didSet {
self.model.systolic = Int(self.systolic) ?? 0
}
}
@Published var diastolic: String = "" {
didSet {
self.model.diastolic = Int(self.diastolic) ?? 0
}
}
}
struct MeasurementsTabView: View {
@ObservedObject var viewModel: BloodPressureViewModel
init(bloodPressure: BloodPressure) {
viewModel = BloodPressureViewModel(bloodPressure)
}
var body: some View {
VStack {
TextField("Systolic", text: $viewModel.systolic)
TextField("Diastolic", text: $viewModel.diastolic)
}
}
}
Upvotes: 2