村花的swift学习笔记2

import Foundation model需要一个东西来储存里面所有的数据,里面的数据有很多种类型,要分开储存才可以在controller问model要数据的时候才可以不会凌乱,这时候,就需要用到enum(枚举)用来分开这些凌乱的数据了。 [code lang="swift"] enum Op: CustomStringConvertible{ case Operand(Double) case UnaryOperand(String, Double -> Double) case BinaryOperand(String,(Double,Double) -> Double) var description:String{ get{ switch self{ case .Operand(let operand): return "\(operand)" case .UnaryOperand(let symbol, _): return symbol case .BinaryOperand(let symbol, _): return symbol } } } } [/code] 1.enum是基本类型,可以像class一样有实例,有函数,但是实例只能是计算类实例。 2.一般var数据类型里面都会有get方法和set方法,但是description是只读属性,所以只有get方法,没有set方法。 3.description的作用就是使op转化为一个string返回,由这个属性里的get方法实现。 4.使用自己作为switch的参数,目的是重复使用下面那个evaluate方法里的switch部分代码。 有了这个description属性还不够,还需要实现这个属性,所以要enum op后面implement一个printable,但是在swift2.0中,printable改成了CustomStringConvertale。这个不是继承,不是继承,不是继承,而是protocol,意思是要这个枚举自己实现这个protocol,而恰好这个protocol里面有个description属性可以返回一个string。 涌进来的数据分好之后,就需要一个用于储存数据的栈~ var opStack = [Op]() 有了栈就可以把数据压进栈了: [php]func pushOperand(operand:Double) -> Double?{ opStack.append(Op.Operand(operand)) return evaluate() } [/php] 当一个个数据传进来的时候,需要判断和了解一下在最新一个数据进来之前有没有别的数据,因为有可能进行的是一个长长的运算比方说3*(4+1),所以新建一个字典类型的实例变量来存储已知的运算,每次执行performOperation时会到knowsOps里去查找,当找到之后就把结果传入opStack里 字典类型有两种写法: 第一种: var knownOps = Dictionary() 第二种: var knownOps = [String:Op]() 处理好数据的分类和储存,就要开始动脑子计算了,controller和veiw可不管计算的,model就相当于这个设计里的脑子。因为计算的时候需要用到递归,所以我就弄个递归方法: [php]func evaluate(ops: [Op]) -> (results: Double?, remainingOps: [Op]){ if !ops.isEmpty{ var remainingOps = ops let op = remainingOps.removeLast(); switch op { case .Operand(let operand): return (operand, remainingOps) case .UnaryOperand(_,let operation): //开始递归 let operandEvaluation = evaluate(remainingOps) //if把let operand从optional double变成了double if let operand = operandEvaluation.results{ return(operation(operand),operandEvaluation.remainingOps) } case .BinaryOperand(_,let operation): //二次递归 let op1Evaluation = evaluate(remainingOps) if let operand1 = op1Evaluation.results{ let op2Evaluation = evaluate(op1Evaluation.remainingOps) if let operand2 = op2Evaluation.results{ return(operation(operand1,operand2),op2Evaluation.remainingOps) } } } } return (nil,ops) } //递归 func evaluate() -> Double?{ let (result, _) = evaluate(opStack) return result } [/php] 1.第一个递归的返回值很奇怪,没错,返回了一个像结构体一样的东西,在swift里叫tuple,tuple是一种mini数据结构,可以使函数返回多个值,语法简单,就是一对括号里面添加参数,参数之间用逗号隔开,参数名可写可不写。 2.因为递归的时候,想要一个不断变化的变量来储存仍未进行运算的数据,但是ops是不可变的,不可以通过直接改变ops来实现这个想法,所以这里有个老师提供的小 tips:ops是不可变的,但是现在需要一个可变的变量来储存ops,所以用一个var来对ops进行copy,就可以使用removeLast()了,任何变量前面默认都是let,可以创建一个var类型的copy来供本地使用。 3.这里用switch来关联变量取出枚举,这是一个没有default的switch,因为这个swift已经把所有可能的情况都列出来了,不需要default。 4.Operand前的小点是Op.Operand()的省略,swift会自己推测匹配,括号里的operand是个与枚举op里各种情况的关联。 5.处理unaryoperand时,因为不需要知道里面那个string,也就是不需要知道计算符号,只关心计算的函数,所以用下划线来忽略string。swift里“_”=忽略,这样就不用再往后使用这个结构的时候声明其他乱七八糟的变量。 6.如果let后面声明的是一个optional数据类型的变量,可以在let前面加个if就去掉optional了。 7.另一种调用可返回一个tuple值的函数的方法就是直接令一个tuple等于函数返回值,tuple里的参数名不一定要和所调用的函数返回的tuple里的参数名相同,如第二个evaluate函数所示。 上面递归算好了的结果,现在就需要一个东西把结果返回给controller,完成这一次与controller之间的“通话”了: 当CalculatorBrain里面有一定数量的运算的时候,这里就只需要输入运算符号 [php]func performOperation(symbol: String) -> Double?{ if let operation = knownOps[symbol]{ opStack.append(operation) } //将每次运算结果返回 return evaluate() } } [/php] 写到这里,这个计算机的model差不多就完成了,因为有了model,所以上节课写的veiwcontroller就需要改变一下,用通过controller与model“通话”的方法替代veiwcontroller的计算操作部分,分工明确一点。 controller和model通过brain来通话连结: [php]var brain = CalculatorBrain() @IBAction func operate(sender: UIButton) { if userIsInTheMiddleOfTypingANumber{ enter() } if let operation = sender.currentTitle{ if let result = brain.performOperation(operation){ displayValue = result }else{ displayValue = 0 } } } @IBAction func enter() { userIsInTheMiddleOfTypingANumber = false //每次把operand压进栈,都会通过brain里的evaluate()把运算结果赋值给displayValue if let result = brain.pushOperand(displayValue){ displayValue = result }else{ displayValue = 0 } } [/php] 1.else里可以试着返回一个错误信息,或者把displayValue清空;如果displayValue是一个optional,这里就可以返回一个错误信息,或者把displayValue清空,总之比直接设为0好啦。 今天就写到这里啦,等我下次文思泉涌的晚上,我再说说我目前对mvc的理解啦,文章里写的有什么不对的不妥的,欢迎斧正哟~ 昨天去发廊焗油,洗头的大姐姐说:“小妹妹,你年纪轻轻的脖子怎么那么劳损啊”,我默默的回了一句并且内心在流泪:“大姐,我是学软加工程的?”,而且最近口腔溃疡两次,让超级无敌馋的我吃东西的时候充分体验到什么叫“痛并快乐着”了?……

转载于:https://my.oschina.net/pigvillage/blog/698170

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值