使用变化的变量更新视图
updating a view with changing variables
我有这个程序和 SwiftUI。该程序用于根据 3 个用户输入使用机器学习计算就寝时间。我有一个 Text("") 向用户显示他们更新的就寝时间。
我希望程序自动更新就寝时间并将其显示在我的 Text("") 上。我尝试了很多方法,none 似乎有效。到目前为止我尝试了什么
- onAppear - 仅在程序首次运行时更新一次就寝时间
- onTapGesture - 仅在点击选择器时更新就寝时间(滚动选择器不起作用),并且它以某种方式阻碍更新步进器(点击 +/- 不会改变时间)
- 使用 didSet 和 class 符合 observableObject,class 中的 @Pulished 变量和视图结构中的 @ObservedObject。效果不佳,但我仅在 class 具有默认值
时尝试过
- 在结构中使用 didSet - 它没有更新就寝时间
有谁知道是否有更简单的方法来更新就寝时间,无论用户滚动选择器还是每当变量发生变化时?
UI looks for detail
struct ContentView: View {
static var defaultWakeUpTime : Date {
var defaultTime = DateComponents()
defaultTime.hour = 7
defaultTime.minute = 0
return Calendar.current.date(from: defaultTime) ?? Date()
}
@State private var wakeUp = defaultWakeUpTime
@State private var sleepAmount = 8.0
@State private var coffeeAmount = 0 {
didSet {
calculateSleepTime()
}
}
@State private var showTime : String = " "
func calculateSleepTime() {**CONTENT**}
var body: some View {
NavigationView {
VStack {
Spacer(minLength: 20)
Text("Your optimum sleep time is \(showTime)")
Spacer(minLength: 10)
Section {
Text("When do you want to wake up?")
.font(.headline)
DatePicker("Please choose a time", selection: $wakeUp, displayedComponents: .hourAndMinute)
.labelsHidden()
.datePickerStyle(WheelDatePickerStyle())
}
Spacer()
Form {
Text("How many hours would you like to sleep?")
.font(.headline)
Stepper(value: $sleepAmount, in: 4...12, step: 0.25) {
Text("\(sleepAmount, specifier: "%g" ) hours")
}
}
Spacer()
Section {
Text("How many cups of coffee do you drink?")
.font(.headline)
Picker("Coffee Selector", selection: $coffeeAmount) {
ForEach (1..<21) {
Text("\([=10=]) " + "Cup")
}
}
.labelsHidden()
}
}
.navigationBarTitle(Text("BetterSleep"))
.onAppear(perform: calculateSleepTime)
}
}
}
我会使用 viewModel 并使用订阅来跟踪值和计算睡眠时间。
将顶部的 ContentView 更改为此
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
现在在任何变量之前加上 viewModel.
创建一个新的 .swift 文件我只是将其命名为 ViewModel,但您不必这样做。
import Combine
final class ViewModel: ObservableObject {
@Published private(set) var bedTime: String = ""
@Published var wakeUp: Date = Date()
@Published var sleepAmount: Double = 8.0
@Published var coffeeAmount = 0
private var cancellables = Set<AnyCancellable>()
init() {
$wakeUp
.receive(on: RunLoop.main)
.sink { [weak self] _ in
self?.calculateSleepTime()
}.store(in: &cancellables)
$sleepAmount
.receive(on: RunLoop.main)
.sink { [weak self] _ in
self?.calculateSleepTime()
}.store(in: &cancellables)
$coffeeAmount
.receive(on: RunLoop.main)
.sink { [weak self] _ in
self?.calculateSleepTime()
}.store(in: &cancellables)
}
private func calculateSleepTime() {
// Your Logic
self.bedTime =
}
}
现在只要其中一个值发生变化,建议就寝时间就会更新。记得在 coffeeAmount 中加一,因为它从 0 开始。
我有这个程序和 SwiftUI。该程序用于根据 3 个用户输入使用机器学习计算就寝时间。我有一个 Text("") 向用户显示他们更新的就寝时间。
我希望程序自动更新就寝时间并将其显示在我的 Text("") 上。我尝试了很多方法,none 似乎有效。到目前为止我尝试了什么
- onAppear - 仅在程序首次运行时更新一次就寝时间
- onTapGesture - 仅在点击选择器时更新就寝时间(滚动选择器不起作用),并且它以某种方式阻碍更新步进器(点击 +/- 不会改变时间)
- 使用 didSet 和 class 符合 observableObject,class 中的 @Pulished 变量和视图结构中的 @ObservedObject。效果不佳,但我仅在 class 具有默认值 时尝试过
- 在结构中使用 didSet - 它没有更新就寝时间
有谁知道是否有更简单的方法来更新就寝时间,无论用户滚动选择器还是每当变量发生变化时?
UI looks for detail
struct ContentView: View {
static var defaultWakeUpTime : Date {
var defaultTime = DateComponents()
defaultTime.hour = 7
defaultTime.minute = 0
return Calendar.current.date(from: defaultTime) ?? Date()
}
@State private var wakeUp = defaultWakeUpTime
@State private var sleepAmount = 8.0
@State private var coffeeAmount = 0 {
didSet {
calculateSleepTime()
}
}
@State private var showTime : String = " "
func calculateSleepTime() {**CONTENT**}
var body: some View {
NavigationView {
VStack {
Spacer(minLength: 20)
Text("Your optimum sleep time is \(showTime)")
Spacer(minLength: 10)
Section {
Text("When do you want to wake up?")
.font(.headline)
DatePicker("Please choose a time", selection: $wakeUp, displayedComponents: .hourAndMinute)
.labelsHidden()
.datePickerStyle(WheelDatePickerStyle())
}
Spacer()
Form {
Text("How many hours would you like to sleep?")
.font(.headline)
Stepper(value: $sleepAmount, in: 4...12, step: 0.25) {
Text("\(sleepAmount, specifier: "%g" ) hours")
}
}
Spacer()
Section {
Text("How many cups of coffee do you drink?")
.font(.headline)
Picker("Coffee Selector", selection: $coffeeAmount) {
ForEach (1..<21) {
Text("\([=10=]) " + "Cup")
}
}
.labelsHidden()
}
}
.navigationBarTitle(Text("BetterSleep"))
.onAppear(perform: calculateSleepTime)
}
}
}
我会使用 viewModel 并使用订阅来跟踪值和计算睡眠时间。
将顶部的 ContentView 更改为此
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
现在在任何变量之前加上 viewModel.
创建一个新的 .swift 文件我只是将其命名为 ViewModel,但您不必这样做。
import Combine
final class ViewModel: ObservableObject {
@Published private(set) var bedTime: String = ""
@Published var wakeUp: Date = Date()
@Published var sleepAmount: Double = 8.0
@Published var coffeeAmount = 0
private var cancellables = Set<AnyCancellable>()
init() {
$wakeUp
.receive(on: RunLoop.main)
.sink { [weak self] _ in
self?.calculateSleepTime()
}.store(in: &cancellables)
$sleepAmount
.receive(on: RunLoop.main)
.sink { [weak self] _ in
self?.calculateSleepTime()
}.store(in: &cancellables)
$coffeeAmount
.receive(on: RunLoop.main)
.sink { [weak self] _ in
self?.calculateSleepTime()
}.store(in: &cancellables)
}
private func calculateSleepTime() {
// Your Logic
self.bedTime =
}
}
现在只要其中一个值发生变化,建议就寝时间就会更新。记得在 coffeeAmount 中加一,因为它从 0 开始。