SwiftUI 视图更新
Posted
技术标签:
【中文标题】SwiftUI 视图更新【英文标题】:SwiftUI View updating 【发布时间】:2021-08-09 10:43:46 【问题描述】:我有:
class Exercise: ObservableObject
@Published var currentSet: Int = 1
func start() somehow changing currentSet
class ExerciseProgram: ObservableObject
@Published var currentExercise: Exercise? = nil
func start() ...self.currentExercise = self.exercises[exerciseIndex + 1]...
struct Neck: View
@ObservedObject var program: ExerciseProgram = ExerciseProgram(exercises: neckExercises)
var body: some View
Text(\(self.program.currentExercise!.currentSet))
问题是我的View只有在ExerciseProgram的currentExercise改变时才更新,而currentExercise本身有currentSet属性,当它改变时我的view没有更新。原则上,我理解为什么我们完全按照它的工作方式工作的逻辑:我指定了当 currentExercise 更改时应该更新视图,但我没有说当 currentExercise 实体的属性发生更改时应该更新视图。所以我不明白该怎么做。而且我不能将运动更改为结构
【问题讨论】:
this SO answer处理嵌套的可观察对象,可能对您有用。 ***.com/questions/58406287/… 以下文章建议避免这种结构并重新审视大局。 rhonabwy.com/2021/02/13/nested-observable-objects-in-swiftui 【参考方案1】:您只需要在适当的级别观察对象即可。
每个@Published
仅在对象整体发生变化时触发刷新。
在您的示例中,如果您替换数组或添加/删除对象,数组将会改变。
import SwiftUI
struct ExerciseProgramView: View
//At this level you will see the entire program
@StateObject var program: ExerciseProgram = ExerciseProgram()
var body: some View
VStack
if program.currentExercise != nil
ExerciseView(exercise: program.currentExercise!)
else
Text("Ready?")
Spacer()
HStack
if program.currentExercise == nil
Button("start program", action:
program.start()
)
else
Button("stop", action:
program.stop()
)
Button("next", action:
program.next()
)
struct ExerciseView: View
//At this level you will see the changes for the exercise
@ObservedObject var exercise: Exercise
var body: some View
VStack
Text("\(exercise.name)")
Text("\(exercise.currentSet)")
if exercise.timer == nil
Button("start exercise", action:
exercise.start()
)
else
Button("stop exercise", action:
exercise.stop()
)
.onDisappear(perform:
exercise.stop()
)
struct ExerciseProgramView_Previews: PreviewProvider
static var previews: some View
ExerciseProgramView()
class Exercise: ObservableObject, Identifiable
let id: UUID = UUID()
let name: String
@Published var currentSet: Int = 1
var timer : Timer?
init(name: String)
self.name = name
func start()
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: timer in
self.currentSet += 1
if self.currentSet >= 10
timer.invalidate()
self.timer = nil
)
func stop()
timer?.invalidate()
timer = nil
class ExerciseProgram: ObservableObject
@Published var currentExercise: Exercise? = nil
@Published var exercises: [Exercise] = [Exercise(name: "neck"), Exercise(name: "arm"), Exercise(name: "leg"), Exercise(name: "abs")]
@Published var exerciseIndex: Int = 0
func start()
self.currentExercise = self.exercises[exerciseIndex]
func next()
if exerciseIndex < exercises.count
self.exerciseIndex += 1
else
self.exerciseIndex = 0
start()
func stop()
exerciseIndex = 0
currentExercise = nil
另外,请注意ObservableObject
s 是如何被初始化的。
@StateObject
用于必须在 View
中初始化对象时使用
@ObservedObject
用于将ObservableObject
传递给子View
,但该对象是在class
中创建的,特别是 class ExerciseProgram
。
https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app
【讨论】:
以上是关于SwiftUI 视图更新的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI,为啥部分视图没有刷新? @State 变量未更新