美文网首页SwiftUI
SwiftUI — Combine 实践 双向绑定和时间机器

SwiftUI — Combine 实践 双向绑定和时间机器

作者: 丿唯一的唯一丿 | 来源:发表于2020-03-08 17:55 被阅读0次

    学习完苹果的教程
    我们知道了通过@State 就可以实现 数据和UI的绑定
    修改APP就可以直接修改数据的State 例如

    @State private var showDetail = true
    Button(action: {
     self.showDetail.toggle()
    }
     if showDetail {
      HikeDetail(hike: hike).transition(.moveAndFade)
     }
    

    当点击Button的时候会修改数据,同时SwiftUI会reload页面
    做过大型一点的APP的同学都会知道 当你们公司出现数据部门的时候
    APP端就会要求打点 对用户当前所做的操作做记录 那么用户的所有操作都会定义一个State 我们就可以创建一个protocol 来完成这件事

    //
    public protocol StateMachine {
    
        // 定义你APP内可能发生的事情例如:添加一个item 修改item Title
        associatedtype Event
    
        //储存事件信息
        mutating func update(with event: Event)
    }
    
         //事件类型
        enum Event {
                //开始创建item 点击 +
                 case startCreatingItem
                //取消创建item 点击 后面蒙版
                 case cancelCreatingItem
                //修改 添加 title
                 case changePartialItemName(String)
                //点击add
                 case addItem
                //点击Toggle 开关
                 case setItemDone(identifier: UUID, isDone: Bool)
        }
    

    用户操作后你就要记录下来 那么通过上面你就可以知道我们可以创建一个记录操作的类 在用户操作的时候自动记录
    数据部门还会有需求,把用户的操作链式表现,那么就可以用数组装下他
    创建一个全局的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)
           }
    

    说到这里呢,最后把数据上报,就已经完成了数据部门的要求。
    我们已经完成了View对State的绑定,学过前端的同学就知道,前端一般都会实现双向绑定,单向绑定非常简单,就是 用户修改View,也更新了State的数据。有单向绑定,就有双向绑定。如果用户更新了State时,View就会自动更新,这种情况就是双向绑定。

    把UI根据当前的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绑定已经绑定State,那怎么实现State发生变化View就能变化了,那我们就可以让Store成为一个ObservableObject,绑定方法也修改,当前State需要改变时,发布change,当currentState发生变化的时候就可以让View发生变化了

    //观察对象
    public final class Store: ObservableObject {
        //初始State
        private let initialState: TodoState
        //储存TodoState
        private var subsequentStates: [TodoState] = []
        //Publisher 发布者 发布状态改变
        public let objectWillChange = PassthroughSubject<Void, Never>()
    
      //当前state需要改变时 发布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
           }
    

    最后既然我们都实现了双向绑定那么就可以手动修改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
    最后放上代码地址

    相关文章

      网友评论

        本文标题:SwiftUI — Combine 实践 双向绑定和时间机器

        本文链接:https://www.haomeiwen.com/subject/uabthhtx.html