斯坦福iOS9公开课总结(二):what is MVC

MVC

关于MVC我们先来看一张图
MVC
相信很多人对这张图不陌生。那么我们一起来回顾一下MVC吧!

什么是MVC?

* Model:数据类,视图所需要的数据。
* View:视图类,构建UI界面。
* Controller: 控制类,用来控制View和Model之间的交流。

Model、View和Controller之间的关系

Controller与View

Controller可以控制View中显示的内容。View中不包含任何数据,当需要数据的时候需要通过Controller获取。

1.  目标动作机制(target-action)
      可以通过`outlet`与`View`相连,例如:`storyBoard`中的`UILabel`。
2.  委托机制(delegate)
3.  数据源机制(dataSource)

Controller与Model

Controller可以控制Model, 他能够调用Model中的方法

1.  广播机制(Notification)
2.  KVO机制 (Key-Value Observing)

View和Model

ViewModel之间没有直接交互,他们之间的交互全部需要通过Controller

CalculatorDemo

效果图

Calculator1.gif

View

程序界面使用storyBoard搭建。

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import UIKit
class ViewController: UIViewController {
    @IBOutlet private weak var display: UILabel!
    private var userInTheMiddleOfTyping = false
    @IBAction private func targetDigit(_ sender: UIButton) {
        //let digit = sender.currentTitle! //容易是程序崩溃。Optional类型
        if let digit = sender.currentTitle {
            if userInTheMiddleOfTyping {
                let textCurrentlyInDisplay = display.text! //textCurrentlyInDispla是String类型
                display.text = textCurrentlyInDisplay + digit
            } else {
                display.text = digit
            }
            userInTheMiddleOfTyping = true
        }
    }
    private var displayValue: Double {
        get {
            return Double(display.text!)!
        }
        set {
            display.text = String(newValue)
        }
    }
    
    //调用Model
    private var brain = CalculatorBrain()
    
    @IBAction private func performOperation(_ sender: UIButton) {
        //使用Model
        if userInTheMiddleOfTyping {
//向model传值
            brain.setOperand(operand: displayValue)
            userInTheMiddleOfTyping = false
        }
        if let mathematicalSymbol = sender.currentTitle {
//传递操作符
            brain.performOperation(symbol: mathematicalSymbol)
        }
//获取计算结果
        displayValue = brain.result
    }
}

Model

Model暴露出来的接口:

1
2
3
4
5
6
7
8
internal class CalculatorBrain {

    internal func setOperand(operand: Double)

    internal func performOperation(symbol: String)

    internal var result: Double { get }
}

Model 完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class CalculatorBrain {
    
    //内部存储器,用于保存计算结果
    private var accumulator = 0.0
    
    //public 公共的方法, 接收外部传入的值
    func setOperand(operand: Double) {
        accumulator = operand
    }
    // 一元运算符本身有相同的地方,二元运算符也是
    func performOperation(symbol: String) {
        if let opertion = operations[symbol] {
            switch opertion {
            case .Constant(let value):
                accumulator = value
            case .UnaryOperation(let function):
                accumulator = function(accumulator)
            case .BinaryOperation(let function):
                executePendingBinaryOperation()
                pending = PendingBinaryOperationInfo(binaryFunction: function, firstOperand: accumulator)
            case .Equals:
                executePendingBinaryOperation()
            }
        }
    }
    //返回计算结果
    var result: Double {
        get {
            return accumulator
        }
    }
    //操作符字典
    private var operations: Dictionary<String, Operation> = [
        "π" : Operation.Constant(M_PI), //M_PI
        "e" : Operation.Constant(M_E), //M_E
        "√" : Operation.UnaryOperation(sqrt),
        "cos" : Operation.UnaryOperation(cos),
        "*" : Operation.BinaryOperation({$0 * $1}),
        "+" : Operation.BinaryOperation({$0 + $1}),
        "-" : Operation.BinaryOperation({$0 - $1}),
        "÷" : Operation.BinaryOperation({$0 / $1}),
        "=" : Operation.Equals
        
    ]
    
    //枚举操作类型
    private enum Operation {
        case Constant(Double)
        case UnaryOperation((Double) -> Double) // 关联函数类型
        case BinaryOperation((Double, Double) -> Double)
        case Equals
    }
    //用于处理等于号
    private func executePendingBinaryOperation() {
        if pending != nil {
            accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator)
            pending = nil
        }
    }
    // 使用结构体存储数据
    private var pending: PendingBinaryOperationInfo?
    private struct PendingBinaryOperationInfo {
        var binaryFunction: (Double, Double) -> Double
        var firstOperand: Double
    }

}

总结

本文是视频课程的第二课,主要讲解了MVC,内容比较基础。另外,视频大量的时间用来写讲解CalculatorDemo,大家有时间可以看视频,讲解的很清晰,相信一定会有收获。