Swift 当ClassA中发生变化时,如何在ClassB上执行函数?
我有一个用SwiftUI编写的游戏,有两个类,一个用于管理游戏的游戏类,一个用于管理一系列高分的ScoreStore类。当前,当用户按下按钮(显示在ContentView结构中)开始新游戏时,会存储游戏分数(通过ScoreStore上的函数)。我希望在游戏达到某个状态时保存分数(这里被认为是某个分数) Game和ScoreStore都是ObservieoObject,并具有可作为@EnvironmentObjects提供给ContentView的@Published属性。在游戏中,分数不会@Published,因为它是一个计算属性Swift 当ClassA中发生变化时,如何在ClassB上执行函数?,swift,swiftui,combine,Swift,Swiftui,Combine,我有一个用SwiftUI编写的游戏,有两个类,一个用于管理游戏的游戏类,一个用于管理一系列高分的ScoreStore类。当前,当用户按下按钮(显示在ContentView结构中)开始新游戏时,会存储游戏分数(通过ScoreStore上的函数)。我希望在游戏达到某个状态时保存分数(这里被认为是某个分数) Game和ScoreStore都是ObservieoObject,并具有可作为@EnvironmentObjects提供给ContentView的@Published属性。在游戏中,分数不会@Pu
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
}
我看过一些问题,它们的答案通过@State属性引用绑定,但在本例中,我“观察”的属性是在游戏中(而不是ContentView)
提前谢谢 您需要一个
PassThroughSubject
,以便在@发布的
值更改时触发视图执行某些操作。然后,在视图中,使用.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
}
}
导入快捷界面
进口联合收割机
结构ContentView:View{
@环境对象变量游戏:游戏
@环境对象变量分数:ScoresStore
func saveScore(){
scores.addScore(新闻核心:game.score)
}
var body:一些观点{
按钮(操作:{saveScore}){
文本(“新游戏?”)
}
.onReceive(game.objectDidChange,perform:{uu}in
//在这里做点什么
})
.onReceive(scores.objectDidChange,perform:{uu}in
//在这里做点什么
})
}
}
最后一类游戏:NSObject,ObservieObject,Codable{
让objectDidChange=PassthroughSubject()
变量组:[卡]=[]
@已发布的变量堆:[[Card]]=[]、[]、[]、[]、[]、[]{
迪塞特{
self.objectDidChange.send()
}
}
变量分数:Int{…}
}
最终类分数存储:NSObject、可编码、可观察对象、可识别{
让objectDidChange=PassthroughSubject()
@已发布变量高分:[分数]=[]{
迪塞特{
self.objectDidChange.send()
}
}
func addScore(newScore:Int,date:date=date()){
//采取措施将分数添加到数组中
}
}
每次Game.piles
或ScoreStore.highScores
更新时,您都会收到视图中.onReceive
的通知,这样您就可以处理它了。我想你也会希望通过这种方式来跟踪比赛的得分,并触发这种变化。然后,您可以测试您想要的任何内容,并执行您想要的任何操作。您还将注意到,我是在一个didSet
上这样做的。您还可以将其视为放置在变量上的willSet
中的objectWillSet
。两者都可以工作,但是将在实际更新之前发送触发器,而didSet
在实际更新之后发送触发器。这可能不会有什么不同,但我在过去就有过这个问题。最后,我在顶部导入了Combine
,但我在一个文件中完成了这些操作。无论您在何处定义passThroughSubject
,都需要导入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?")
}
}
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
}
}