RxSwift 样例六 Calculator

APIWrappers是简单介绍API使用的,就不会讲了,可以说看一遍就好了,这种东西,熟能生巧别无他法。

Calculator 相信是每个初学者都做过的项目。回想当初一坨不忍直视的代码,相信你看到RxSwift的样例会觉得,还有这样简洁的计算器!实在惭愧,入行几年我自认为写不出这样的分级,每天工作都被业务代码填充。几乎没有多少时间自己琢磨精妙的代码,时常会感觉到了瓶颈,希望能借这一系列博客学到大牛编码的思想。与君共勉。

Calculator.swift 里面定义了大量的enum来判断当前的状态。符号,命令,状态。

一句一句读就好理解了,
let system = Observable.system(
CalculatorState.initial,
accumulator: CalculatorState.reduce,
scheduler: MainScheduler.instance,
feedback: { _ in commands }
)
// .debug("calculator state")
.shareReplayLatestWhileConnected()

这里有一个公用方法来绑定了MainScheduler.instance。

 allClearButton.rx.tap.map { _ in .clear }

像这样点击allClearButton就会触发CalculatorState变化,

        case .clear:
            return CalculatorState.initial

结果就是重新实例化一个CalculatorState。自然默认就是0.
理解这一个按钮点击的变化事件,其他的按钮都是一样的。

   func mapScreen(transform: (String) -> String) -> CalculatorState {
        switch self {
        case let .oneOperand(operand, screen):
            return .oneOperand(operand: operand, screen: transform(screen))
        case let .oneOperandAndOperator(operand, operat, screen):
            return .oneOperandAndOperator(operand: operand, operator: operat, screen: transform(screen))
        }
    }

显示屏幕也做的很巧妙。分为需要显示符号和不需要显示符号两个case。有一个问题我一直没搞清的是CalculatorState.reduce是在什么时候改变的呢,我以为是在写符号的时候,因为点击运算符号也就意味着需要显示符号会为true,但代码看来并不是。

答案在这个方法里面static func reduce(state: CalculatorState, _ x: CalculatorCommand) -> CalculatorState
但是外面并没有传值进入这个方法,那么states又是怎么来的呢。大家思考一分钟。

其实有这个想法的都进入了一个误区,states根本不是外来的,而是自身的。CalculatorState 本身就是一个enum,当然有俩个states了。在第二个延展里面,清楚的记录了

 case .operation(let o):
            switch state {
            case let .oneOperand(_, screen):
                return .oneOperandAndOperator(operand: Double(screen) ?? 0.0, operator: o, screen: "0")
            case let .oneOperandAndOperator(operand, o, screen):
                return .oneOperandAndOperator(operand: o.perform(operand, Double(screen) ?? 0.0), operator: o, screen: "0")
            }
        case .equal:
            switch state {
            case let .oneOperandAndOperator(lhs, o, screen):
                let result = o.perform(lhs, Double(screen) ?? 0.0)
                return .oneOperand(operand: result, screen: String(result))

如果是点击符号,初始的oneOperand状态,会变成oneOperandAndOperator,而点击等于好,oneOperandAndOperator会变成oneOperand。哈,就像BOOL一样,只会有一个值出现。goodNews,除此之外,应该没有什么难点了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值