學習完蘋果的教程
我們知道了通過@State 就可以實現(xiàn) 數(shù)據(jù)和UI的綁定
修改APP就可以直接修改數(shù)據(jù)的State 例如
@State private var showDetail = true
Button(action: {
self.showDetail.toggle()
}
if showDetail {
HikeDetail(hike: hike).transition(.moveAndFade)
}
當點擊Button的時候會修改數(shù)據(jù)册烈,同時SwiftUI會reload頁面
做過大型一點的APP的同學都會知道 當你們公司出現(xiàn)數(shù)據(jù)部門的時候
APP端就會要求打點 對用戶當前所做的操作做記錄 那么用戶的所有操作都會定義一個State 我們就可以創(chuàng)建一個protocol 來完成這件事
//
public protocol StateMachine {
// 定義你APP內(nèi)可能發(fā)生的事情例如:添加一個item 修改item Title
associatedtype Event
//儲存事件信息
mutating func update(with event: Event)
}
//事件類型
enum Event {
//開始創(chuàng)建item 點擊 +
case startCreatingItem
//取消創(chuàng)建item 點擊 后面蒙版
case cancelCreatingItem
//修改 添加 title
case changePartialItemName(String)
//點擊add
case addItem
//點擊Toggle 開關(guān)
case setItemDone(identifier: UUID, isDone: Bool)
}
用戶操作后你就要記錄下來 那么通過上面你就可以知道我們可以創(chuàng)建一個記錄操作的類 在用戶操作的時候自動記錄
數(shù)據(jù)部門還會有需求劳景,把用戶的操作鏈式表現(xiàn),那么就可以用數(shù)組裝下他
創(chuàng)建一個全局的Store,并增加一個方法記錄TodoState
@EnvironmentObject var store: Store
// 添加事件
private var subsequentStates: [TodoState] = []
func dispatch(event: TodoState.Event) {
var newState = state
newState.update(with: event)
subsequentStates.append(newState)
}
說到這里呢费坊,最后把數(shù)據(jù)上報,就已經(jīng)完成了數(shù)據(jù)部門的要求。
我們已經(jīng)完成了View對State的綁定余素,學過前端的同學就知道奔穿,前端一般都會實現(xiàn)雙向綁定镜沽,單向綁定非常簡單,就是 用戶修改View贱田,也更新了State的數(shù)據(jù)缅茉。有單向綁定,就有雙向綁定男摧。如果用戶更新了State時蔬墩,View就會自動更新,這種情況就是雙向綁定耗拓。
把UI根據(jù)當前的State綁定
var body: some View {
ZStack{
NavigationView{
List(store.state.todoItems){item in
TodoListItem(item: item)
}.navigationBarTitle(Text("TimeTrave"))
.navigationBarItems(trailing: Button(action: {
self.store.dispatch(event: .startCreatingItem)
}, label: {
Image(systemName: "plus.circle")
}))
}
if store.state.isCreatingItem {
ModalDimmingView()
VStack{
Spacer()
AddItemView()
.background(Color.white)
.cornerRadius(12.0)
.shadow(radius: 16.0)
.padding()
Spacer()
}
.transition(.move(edge: .bottom))
}
}
那么UI綁定已經(jīng)綁定State拇颅,那怎么實現(xiàn)State發(fā)生變化View就能變化了,那我們就可以讓Store成為一個ObservableObject乔询,綁定方法也修改蔬蕊,當前State需要改變時,發(fā)布change哥谷,當currentState發(fā)生變化的時候就可以讓View發(fā)生變化了
//觀察對象
public final class Store: ObservableObject {
//初始State
private let initialState: TodoState
//儲存TodoState
private var subsequentStates: [TodoState] = []
//Publisher 發(fā)布者 發(fā)布狀態(tài)改變
public let objectWillChange = PassthroughSubject<Void, Never>()
//當前state需要改變時 發(fā)布change
var currentStateIndex: Int = 0 {
didSet {
withAnimation {
objectWillChange.send(())
}
}
}
func dispatch(event: TodoState.Event) {
var newState = state
newState.update(with: event)
subsequentStates.append(newState)
currentStateIndex = stateCount - 1
}
最后既然我們都實現(xiàn)了雙向綁定那么就可以手動修改currentState看一下岸夯,用一個Slider綁定currentStateIndex
let indexBinding = Binding(
get: {
return Double(self.store.currentStateIndex)
}, set: {
self.store.currentStateIndex = Int($0)
})
Slider(value: indexBinding, in: 0...Double(store.stateCount - 1)
當你拖動Slider的時候,是不是就有種時間機器的感覺们妥,可以回到任意的State猜扮,看一下效果
最后放上代碼地址