当 Class 发生变化时,如何在 Class B 上执行函数?
How do I execute a function on ClassB when something changes in ClassA?
我有一个用 SwiftUI 编写的游戏,有两个 classes,一个 Game class 来管理游戏,还有一个 ScoreStore class 来管理一系列高分。当前,当用户按下按钮(显示在 ContentView 结构中)开始新游戏时,游戏的分数会被存储(通过 ScoreStore 上的函数)。我想在游戏达到某个状态(这里认为是某个分数)时保存分数。
Game 和 ScoreStore 都是 ObservableObjects,并且具有 @Published 属性作为 @EnvironmentObjects 提供给 ContentView。在 Game 中,score 不是 @Published 因为它是计算的 属性.
class Game: ObservableObject, Codable {
var deck: [Card] = []
@Published var piles: [[Card]] = [[],[],[],[]]
var score: Int {
let fullDeckCount = 52
var cardsOnThePiles = 0
for pile in piles {
cardsOnThePiles += pile.count
}
return fullDeckCount - deck.count - cardsOnThePiles
}
class ScoresStore: Codable, ObservableObject, Identifiable {
@Published var highScores: [Score] = []
func addScore(newScore: Int, date: Date = Date()) {
// Do things to add the score to the array
}
struct ContentView: View {
@EnvironmentObject var game: Game
@EnvironmentObject var scores: ScoresStore
func saveScore() {
scores.addScore(newScore: game.score)
}
var body: some View {
Button(action: { saveScore }) {
Text("New Game?")
}
}
我查看了其答案通过 @State 属性 绑定的问题,但在这种情况下,属性 我正在“观察”的是游戏(而不是 ContentView)。
提前致谢!
您需要一个 PassThroughSubject
来允许您的视图在 @Published
值更改时被触发以执行某些操作。然后,在您看来,您使用 .onReceive
来触发您的函数。
import SwiftUI
import Combine
struct ContentView: View {
@EnvironmentObject var game: Game
@EnvironmentObject var scores: ScoresStore
func saveScore() {
scores.addScore(newScore: game.score)
}
var body: some View {
Button(action: { saveScore }) {
Text("New Game?")
}
.onReceive(game.objectDidChange, perform: { _ in
//Do something here
})
.onReceive(scores.objectDidChange, perform: { _ in
//Do something here
})
}
}
final class Game: NSObject, ObservableObject, Codable {
let objectDidChange = PassthroughSubject<Void, Never>()
var deck: [Card] = []
@Published var piles: [[Card]] = [[],[],[],[]] {
didSet {
self.objectDidChange.send()
}
}
var score: Int {...}
}
final class ScoresStore: NSObject, Codable, ObservableObject, Identifiable {
let objectDidChange = PassthroughSubject<Void, Never>()
@Published var highScores: [Score] = [] {
didSet {
self.objectDidChange.send()
}
}
func addScore(newScore: Int, date: Date = Date()) {
// Do things to add the score to the array
}
}
每次Game.piles
或ScoreStore.highScores
更新,您都会收到通知到您视图中的.onReceive
,以便您进行处理。我怀疑您也想以这种方式跟踪游戏得分,并触发该更改。然后您可以测试您想要的任何内容并执行您想要的任何操作。您还会注意到我是在 didSet
上做的。您还会将其视为 objectWillSet
放入变量的 willSet
中。两者都有效,但 willSet
在实际更新之前发送触发器,而 didSet
在实际更新之后发送。这可能没有什么不同,但我过去曾有过这个问题。最后,我在顶部导入了 Combine
,但我在一个文件中完成了这些。无论您在哪里定义 passThroughSubject
,您都需要导入 Combine
。视图实际上并不需要导入它。祝你好运。
我有一个用 SwiftUI 编写的游戏,有两个 classes,一个 Game class 来管理游戏,还有一个 ScoreStore class 来管理一系列高分。当前,当用户按下按钮(显示在 ContentView 结构中)开始新游戏时,游戏的分数会被存储(通过 ScoreStore 上的函数)。我想在游戏达到某个状态(这里认为是某个分数)时保存分数。
Game 和 ScoreStore 都是 ObservableObjects,并且具有 @Published 属性作为 @EnvironmentObjects 提供给 ContentView。在 Game 中,score 不是 @Published 因为它是计算的 属性.
class Game: ObservableObject, Codable {
var deck: [Card] = []
@Published var piles: [[Card]] = [[],[],[],[]]
var score: Int {
let fullDeckCount = 52
var cardsOnThePiles = 0
for pile in piles {
cardsOnThePiles += pile.count
}
return fullDeckCount - deck.count - cardsOnThePiles
}
class ScoresStore: Codable, ObservableObject, Identifiable {
@Published var highScores: [Score] = []
func addScore(newScore: Int, date: Date = Date()) {
// Do things to add the score to the array
}
struct ContentView: View {
@EnvironmentObject var game: Game
@EnvironmentObject var scores: ScoresStore
func saveScore() {
scores.addScore(newScore: game.score)
}
var body: some View {
Button(action: { saveScore }) {
Text("New Game?")
}
}
我查看了其答案通过 @State 属性 绑定的问题,但在这种情况下,属性 我正在“观察”的是游戏(而不是 ContentView)。
提前致谢!
您需要一个 PassThroughSubject
来允许您的视图在 @Published
值更改时被触发以执行某些操作。然后,在您看来,您使用 .onReceive
来触发您的函数。
import SwiftUI
import Combine
struct ContentView: View {
@EnvironmentObject var game: Game
@EnvironmentObject var scores: ScoresStore
func saveScore() {
scores.addScore(newScore: game.score)
}
var body: some View {
Button(action: { saveScore }) {
Text("New Game?")
}
.onReceive(game.objectDidChange, perform: { _ in
//Do something here
})
.onReceive(scores.objectDidChange, perform: { _ in
//Do something here
})
}
}
final class Game: NSObject, ObservableObject, Codable {
let objectDidChange = PassthroughSubject<Void, Never>()
var deck: [Card] = []
@Published var piles: [[Card]] = [[],[],[],[]] {
didSet {
self.objectDidChange.send()
}
}
var score: Int {...}
}
final class ScoresStore: NSObject, Codable, ObservableObject, Identifiable {
let objectDidChange = PassthroughSubject<Void, Never>()
@Published var highScores: [Score] = [] {
didSet {
self.objectDidChange.send()
}
}
func addScore(newScore: Int, date: Date = Date()) {
// Do things to add the score to the array
}
}
每次Game.piles
或ScoreStore.highScores
更新,您都会收到通知到您视图中的.onReceive
,以便您进行处理。我怀疑您也想以这种方式跟踪游戏得分,并触发该更改。然后您可以测试您想要的任何内容并执行您想要的任何操作。您还会注意到我是在 didSet
上做的。您还会将其视为 objectWillSet
放入变量的 willSet
中。两者都有效,但 willSet
在实际更新之前发送触发器,而 didSet
在实际更新之后发送。这可能没有什么不同,但我过去曾有过这个问题。最后,我在顶部导入了 Combine
,但我在一个文件中完成了这些。无论您在哪里定义 passThroughSubject
,您都需要导入 Combine
。视图实际上并不需要导入它。祝你好运。