测试已测试 | ✗ |
语言语言 | SwiftSwift |
许可 | MIT |
发布最后发布 | 2017年6月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✗ |
由 Maxim Khatskevich 维护。
将任何对象转换成离散系统,并声明其状态。
建议使用 CocoaPods 安装
pod 'XCEState', '~> 2.6'
此库允许通过定义一组不同的状态并将这些状态立即或通过转换应用来将任何对象转换为 离散系统。
此库的一个典型用例是在您的应用状态发生变化时重新配置 UIView
和其子类的实例。
给定对象的每个状态都由两个闭包表示。这些闭包中的每一个都接收对象的一个实例作为输入参数,并应在内部对象成员上进行突变。所有这样的突变共同定义了对象的一个独特状态。
第一个闭包 - onSet
- 是必需的,并在对象进入状态时声明突变。第二个闭包 - onUpdate
- 是可选的,并在对象进入状态并再次应用相同状态时声明突变。
假设我们有一个类,它代表一个视图,其中用户可以输入他们的搜索关键字,并有一个按钮在按下时开始搜索过程
class SearchView: UIView
{
let keyword = UITextField()
let start = UIButton()
}
要将此类声明为离散系统,声明它遵循 Stateful
协议
extension SearchView: Stateful
{
// optionally lets declare a type alias
// to shorten states declaration:
typealias St = State<SearchView>
}
除了提供允许声明并将状态应用于稍后声明的特殊辅助成员外,Stateful
协议不要求实现任何事情。
为了描述给定类的状态,在此类内部定义一个类级别函数(其名称将被解释为状态名称),该函数返回该类的 State
。
例如,我们可以为我们的 SearchView
类定义一个名为 awaiting
的状态。在这个状态下,keyword
文本字段和 start
按钮都处于可用状态,可以接受用户输入。注意,我们可以为该函数定义尽可能多的输入参数,这为我们提供了将任何类型的外部值传递到状态配置闭包的机会。请看以下示例,我们如何传递 keyword
字段的默认值。
extension SearchView
{
static
func awaiting(with keyword: String) -> St
{
return state{
$0.keyword.text = keyword
$0.keyword.isEnabled = true
$0.start.isEnabled = true
}
}
}
用户输入搜索关键词并点击 start
按钮后,我们可能想锁定这些控件,直到搜索完成。为此,我们可能想在搜索视图中应用一个名为 locked
的状态,其声明如下
extension SearchView
{
static
func locked() -> St
{
return state{
$0.keyword.isEnabled = false
$0.start.isEnabled = false
}
}
}
稍后,我们可以按照以下方式将声明给类的任何状态应用于此类的一个实例
let transition: Transition<SearchView>.Body = ... // define transition
let view = SearchView()
view.state.apply{ $0.awaiting(with: "something") }.instantly()
view.state.apply{ $0.awaiting(with: "something") }.instantly() // no effect
view.state.apply{ $0.locked() }.viaTransition() // with default transition
view.state.apply{ $0.awaiting(with: "after search") }.viaTransition(transition)
开发者如何实现状态转换完全取决于自己的选择。在处理基于 UIView
的类时,使用动画应用更改是常见的做法,而 Transition
别名提供了完全控制转换的能力。
我们还可以定义当应用带有转换的状态时默认应使用的转换,但不需要明确提供特定的转换。
class SearchView: UIView
{
//...
static
var defaultTransition: Transition<SearchView>.Body = {
(view, mutations, completion) in
view.alpha = 0.0
//===
mutations() // this is closure from the state
//===
UIView.animate(
withDuration: 1.0,
animations: { v.alpha = 1.0 },
completion: completion
)
}
//...
}
上面的示例展示了默认转换,它首先隐藏整个视图,然后应用新状态中的变更,最后使用动画显示整个视图,使其再次可见。或者,如果需要的话,我们可以将 mutations()
调用放在 UIView.animate(…)
调用的 animations
闭包内,以在淡入动画期间实际动画化变更。
为了使结果代码尽可能简洁和易于理解,同时维护编译时的类型安全,该库依赖于 Swift 的高级语言特性,如泛型和简写闭包参数名称,因此它 **不** 与 Objective-C 兼容。