尝试实现状态机:
struct Transition {
var targetState: any ContextState
var effect: Effect? = nil
typealias Effect = ( Context ) -> ()
}
/// Events may trigger transitions between the states.
/// Each method takes an instance of the 'Context' type as parameter
/// to be able to call methods on the 'Context' to effect actions as required
protocol Events {
mutating func gotoState1(_: Context) -> Transition?
mutating func gotoStateě(_: Context) -> Transition?
}
/// Protocol extension to provide DEFAULT implementations of all the Events protocol methods
extension Events {
mutating func gotoState1(_: Context) -> Transition? { return nil }
mutating func gotoState2(_: Context) -> Transition? { return nil }
}
/// Activities related to the states themselves.
/// These methods will allow each concrete state type to define 'entry' and 'exit' activities
/// for the state it represents
protocol Activities {
func enter( _ : Context )
func exit( _ : Context )
}
/// With DEFAULT empty implementation of both the methods in place, concrete state types will
/// need to implement these methods only for states that actually have 'entry' and/or 'exit'
/// activities respectively
extension Activities {
func enter( _ : Context ) {}
func exit( _ : Context ) {}
}
typealias ContextState = Events & Activities
具体状态实现为:
struct State1: ContextState {
func enter( _ : GoProRemote ) {
// TODO: Perform the action to be taken once the state is entered
}
/// Go to State2
mutating func gotoState2(_: Context) -> Transition? {
return Transition(targetState: State2())
}
}
struct State2: ContextState {
func enter( _ : GoProRemote ) {
// TODO: Perform the action to be taken once the state is entered
}
/// Go to State1
mutating func gotoState1(_: Context) -> Transition? {
return Transition(targetState: State1())
}
}
最后是控制器:
struct Context {
@State var state: ContextState = State1()
/// Perform transition to the new state
private func perform( transition : Transition? ) {
guard let transition = transition else { return }
state.exit( self )
transition.effect?( self )
state = transition.targetState
state.enter( self )
}
}
在 SwiftUI 中,有一个包含 TabView 的视图,它是特定状态的图形表示。其中的每个选项卡都是针对一种状态设计的。
struct SMView: View {
var context: Context
var body: some View {
TabView(selection: $context.state) {
Text("State 1").tag(State1())
Text("State 2").tag(State2())
}
.onChange(of: $context.state, {
print("Going to \($context.state) state")
})
}
}
这就是问题所在。上面的代码不起作用,因为它在状态变量的可哈希不一致性等中生成错误......
有人知道如何使用状态结构为 TabView 中的选项卡建立索引吗?
@State var context = Context()
同时从 Context 结构体中删除
@State
结构体内部的函数需要标记为变异,例如
mutating func perform(...
供动画参考,它是
withAnimation {
context.selection =
}