继续我的previous question,观察UIViewRepresentable
的几个状态变化的最佳方法是什么?以前,我只需要观察一个属性userWon
的更改。然而,由于应用程序中引入了新功能,我现在需要观察新的变化。假设这些可能会增加更多,那么最好的方法是添加更多的State
属性并将它们绑定到UIViewRepresentable
吗?在这一点上,添加越来越多的绑定和onChange
修饰符来观察变化感觉有些笨拙。示例代码如下:
struct GameView: View {
@State private var userWon: Bool = false
@State private var propA: Bool = false
@State private var propB: Int = 0
@State private var propC: Int = 0
...
...
...
@State private var propZ: Int = 0
@StateObject private var gameService = GameService()
var body: some View {
ZStack {
VStack {
GameViewRepresentable(userWon: $userWon,
propA: $propA,
propB: $propB,
propC: $propC,
...
propZ: $propZ) // <- Add more bindings??
.onChange(of: userWon) { newValue in
if newValue {
gameService.updateUserScore()
}
}
.onChange(of: propA) { newValue in
gameService.doSomethingA()
}
.onChange(of: propB) { newValue in
gameService.doSomethingB()
}
.onChange(of: propZ) { newValue in
gameService.doSomethingZ()
}
}
.clipped()
}
}
}
struct GameViewRepresentable: UIViewRepresentable {
typealias UIViewType = GameView
@Binding var userWon: Bool
func makeUIView(context: Context) -> GameView {
let gameView = GameView()
gameView.delegate = context.coordinator
return gameView
}
func updateUIView(_ uiView: GameView, context: Context) {
}
func makeCoordinator() -> GameViewCoordinator {
GameViewCoordinator(self)
}
class GameViewCoordinator: GameViewDelegate {
var parent: GameViewRepresentable
init(_ parent: GameViewRepresentable) {
self.parent = parent
}
func userWon() {
self.parent.userWon = true
}
}
}
我能想到的替代方法是:
1.在gameService
中创建一个包含上述要观察的属性的信封对象/模型,并将其作为绑定传递给UIViewRepresentable
。
1.让gameService
观察这个被包围的物体,可能是使用Combine
?但我不知道如何做到这一点,或者它是否会在所有的工作。任何帮助是赞赏如何有效地做到这一点。
1条答案
按热度按时间dfuffjeb1#
您可以将所有
@State var
移动到您的GameService
中,作为@Published var
。然后,您可以通过
@ObservedObject
将其传递给GameViewRepresentable
,以避免写出游戏视图所需的所有状态。由于这是一个
UIViewRepresentable
,我认为您可能会通过其属性的setter来更新game
(而不是说,从ObservedObject
的投影值生成一个Binding
)。在这种情况下,您可以使用didSet
来检测更改:否则,可以使用
onReceive
检测更改: