SwiftUI onTapGesture 不适用于 Mac 应用程序中的 ObservedObject
SwiftUI onTapGesture does not work with ObservedObject in Mac app
我想根据来自另一个视图 (LeftView) 中点击手势的操作来更新视图 (RightView)。下面是我完成此操作的示例代码:
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 class 中使用计时器来更新点击计数,则 RightView 会正确更新。
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 文本?
LeftView
和 RightView
各自初始化各自的 AppState
对象,因此它们观察的状态不同。
在您的两个视图中,将 @ObservedObject
保留为未初始化的 属性:
LeftView.swift & RightView.swift
@ObservedObject var appState: AppState
当您在 SwiftUI 视图中有一个未初始化的 属性 时,您需要在任何时候想要使用该视图时为其提供一个值。
PreviewProvider
使用您的视图实例,因此 Xcode 可以在 canvas 上向您显示它,它只需要您提供一个 占位符 appState
的值。该值并不是很重要(除了 Xcode canvas 之外没有在任何地方使用它)所以您只需要提供正确类型的东西:
#if DEBUG
struct LeftView_Previews: PreviewProvider {
static var previews: some View {
LeftView(appState: AppState())
}
}
#endif
最后,在 ContentView
中,您需要将对单个 shared AppState
的引用传递到 LeftView
和 RightView
这样他们每个人都可以观察到同一个物体:
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
的同一个实例,它们都会在其属性更改时更新。
您还可以使用 @EnvironmentObject
在应用中的 所有 视图之间共享状态,但由于我们在这里只关注两个视图 @ObservedObject
是务实的选择。
我想根据来自另一个视图 (LeftView) 中点击手势的操作来更新视图 (RightView)。下面是我完成此操作的示例代码:
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 class 中使用计时器来更新点击计数,则 RightView 会正确更新。
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 文本?
LeftView
和 RightView
各自初始化各自的 AppState
对象,因此它们观察的状态不同。
在您的两个视图中,将 @ObservedObject
保留为未初始化的 属性:
LeftView.swift & RightView.swift
@ObservedObject var appState: AppState
当您在 SwiftUI 视图中有一个未初始化的 属性 时,您需要在任何时候想要使用该视图时为其提供一个值。
PreviewProvider
使用您的视图实例,因此 Xcode 可以在 canvas 上向您显示它,它只需要您提供一个 占位符 appState
的值。该值并不是很重要(除了 Xcode canvas 之外没有在任何地方使用它)所以您只需要提供正确类型的东西:
#if DEBUG
struct LeftView_Previews: PreviewProvider {
static var previews: some View {
LeftView(appState: AppState())
}
}
#endif
最后,在 ContentView
中,您需要将对单个 shared AppState
的引用传递到 LeftView
和 RightView
这样他们每个人都可以观察到同一个物体:
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
的同一个实例,它们都会在其属性更改时更新。
您还可以使用 @EnvironmentObject
在应用中的 所有 视图之间共享状态,但由于我们在这里只关注两个视图 @ObservedObject
是务实的选择。