SwiftUI — Combine 實踐 雙向綁定和時間機器

學習完蘋果的教程
我們知道了通過@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猜扮,看一下效果

TimeTrave.gif

最后放上代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末躏惋,一起剝皮案震驚了整個濱河市闰围,隨后出現(xiàn)的幾起案子莫矗,更是在濱河造成了極大的恐慌椿浓,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒸眠,死亡現(xiàn)場離奇詭異圆凰,居然都是意外死亡远舅,警方通過查閱死者的電腦和手機带污,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門僵控,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鱼冀,你說我怎么就攤上這事报破。” “怎么了千绪?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵充易,是天一觀的道長。 經(jīng)常有香客問我荸型,道長盹靴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮稿静,結(jié)果婚禮上梭冠,老公的妹妹穿的比我還像新娘。我一直安慰自己自赔,他們只是感情好妈嘹,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布柳琢。 她就那樣靜靜地躺著绍妨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪柬脸。 梳的紋絲不亂的頭發(fā)上他去,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音倒堕,去河邊找鬼灾测。 笑死,一個胖子當著我的面吹牛垦巴,可吹牛的內(nèi)容都是我干的媳搪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼骤宣,長吁一口氣:“原來是場噩夢啊……” “哼秦爆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起憔披,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤等限,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后芬膝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體望门,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年锰霜,在試婚紗的時候發(fā)現(xiàn)自己被綠了筹误。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡癣缅,死狀恐怖纫事,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情所灸,我是刑警寧澤丽惶,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站爬立,受9級特大地震影響钾唬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一抡秆、第九天 我趴在偏房一處隱蔽的房頂上張望奕巍。 院中可真熱鬧,春花似錦儒士、人聲如沸的止。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诅福。三九已至,卻和暖如春拖叙,著一層夾襖步出監(jiān)牢的瞬間氓润,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工薯鳍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咖气,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓挖滤,卻偏偏與公主長得像崩溪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子斩松,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容