SwiftUI onTapGesture不适用于Mac app中的ObservedObject [英] SwiftUI onTapGesture does not work with ObservedObject in Mac app
问题描述
我想基于另一个视图(LeftView)中轻击手势的操作来更新视图(RightView).下面是我的示例代码来完成此操作:
I would like to update a view (RightView) based on actions from a tap gesture in another view (LeftView). Below is my example code to accomplish this:
AppState.swift
import Foundation
class AppState: ObservableObject {
@Published var tapCount: Int = 0
func incrementTapCount() {
self.tapCount += 1
print("tap count \(self.tapCount)")
}
}
LeftView.swift
import SwiftUI
struct LeftView: View {
@ObservedObject var appState = AppState()
var body: some View {
VStack {
Text("Left View")
}
.frame(width: 100, height: 200)
.onTapGesture {
print("tapped left view")
self.appState.incrementTapCount()
}
}
}
RightView.swift
import SwiftUI
struct RightView: View {
@ObservedObject var appState = AppState()
var body: some View {
VStack {
Text("Right View")
Text("Tap Count: \(self.appState.tapCount)")
}.frame(width: 200, height: 200)
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
LeftView()
RightView()
}.frame(width: 300, height: 200)
}
}
不幸的是,RightView文本不会随着点击数更新.但是,如果我在ObservableObject类中使用计时器来更新拍子计数,则RightView会正确更新.
Unfortunately, the RightView text does not update with the tap count. However, if I use a timer in the ObservableObject class to update the tap count, then the RightView updates correctly.
import Foundation
class AppState: ObservableObject {
@Published var tapCount: Int = 0
init() {
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
self.tapCount += 1
}
}
func incrementTapCount() {
self.tapCount += 1
print("tap count \(self.tapCount)")
}
}
为什么LeftView中的轻击手势不会更新RightView文本?
Why does the tap gesture in LeftView not update the RightView text?
推荐答案
LeftView
和 RightView
都分别初始化了自己的单独的 AppState
对象,所以他们不会观察到相同的状态.
LeftView
and RightView
are each initializing their own separate AppState
objects, so they aren't observing the same state.
在两个视图中,都将 @ObservedObject
保留为未初始化的属性:
In both of your views, leave the @ObservedObject
as an uninitialized property:
LeftView.swift&RightView.swift
@ObservedObject var appState: AppState
在SwiftUI视图中具有未初始化的属性时,您需要在每次使用该视图时为其提供一个值.
When you have an uninitialized property like this in a SwiftUI view, you need to provide a value for it any time you want to use the view.
PreviewProvider
使用视图的实例,因此Xcode可以在画布上向您显示该视图,并且只需要您为提供一个 placeholder 值.appState
.该值并不是很重要(除了Xcode画布,它没有在其他任何地方使用),因此您只需要提供正确类型的值即可:
The PreviewProvider
uses an instance of your view so Xcode can show it to you on the canvas, and it only needs you to supply a placeholder value for appState
. The value isn't really important (it isn't used anywhere but the Xcode canvas) so you just need to provide something of the correct type:
#if DEBUG
struct LeftView_Previews: PreviewProvider {
static var previews: some View {
LeftView(appState: AppState())
}
}
#endif
最后,在 ContentView
中,您需要将对单个 shared AppState
的引用传递到 LeftView
和 RightView
,这样它们就可以观察相同的对象:
Finally in ContentView
you'll want to pass a reference to a single shared AppState
down to LeftView
and RightView
so they can each observe the same object:
ContentView.swift
import SwiftUI
struct ContentView: View {
var sharedAppState = AppState()
var body: some View {
HStack {
LeftView(appState: sharedAppState)
RightView(appState: sharedAppState)
}.frame(width: 300, height: 200)
}
}
现在两个视图都在观察 AppState
的相同实例,当它们的属性更改时,它们都将更新.
Now that both views are observing the same instance of AppState
, they'll both update when its properties change.
您还可以使用 @EnvironmentObject
在应用程序中所有所有视图之间共享状态,但是由于这里我们只关注两个视图,因此 @ObservedObject
是一个务实的选择.
You can also use @EnvironmentObject
to share state between all the views in your app, but since we're only concerned with two views here @ObservedObject
is a pragmatic choice.
这篇关于SwiftUI onTapGesture不适用于Mac app中的ObservedObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!