【问题标题】:How to split calculator logic into its own class? (using Xcode/Swift 11.3.1)如何将计算器逻辑拆分为自己的类? (使用 Xcode/Swift 11.3.1)
【发布时间】:2020-03-01 08:52:41
【问题描述】:

我使用 Xcode 构建了一个简单的 iOS 计算器,它是一个视图控制器和一个类,我必须将计算器逻辑放入一个单独的类中,但我不是确定如何去做。我是在原始类内部还是外部创建一个新类?原始类有@IBAction func numberPressed@IBAction func operandPressed

如何将输入传递给我需要创建的新 Calculator 类?

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var lblDisplay: UILabel!

    var numberOnDisplay: Double = 0
    var previousNumber: Double = 0
    var operand = 0
    var isPerformingOperand = false


    override func viewDidLoad() {
        super.viewDidLoad()

        lblDisplay.text = ""
    }

    // Inputs whatever number is pressed 0-9
    @IBAction func numberPressed(_ sender: Any) {

        let tag = (sender as! UIButton).tag

        if isPerformingOperand == true {
            isPerformingOperand = false
            lblDisplay.text = String(tag)
            numberOnDisplay = Double(lblDisplay.text!)!

        } else {

                lblDisplay.text = lblDisplay.text! + String(tag)
                numberOnDisplay = Double(lblDisplay.text!)!
        }

    }

    // Performs the operands including decimal, clear and backspace
    @IBAction func operandPressed(_ sender: Any) {

        let tag = (sender as! UIButton).tag


        /* Operands:  = (99), . (10) X (12), ÷ (13), - (14), + (15) */

        if tag == 10 {
            if lblDisplay.text?.range(of: ".") == nil {
                lblDisplay.text! += "."
            }
        }

            if tag == 12 {
            isPerformingOperand = true
            previousNumber = Double(lblDisplay.text!)!
            lblDisplay.text = "*"
            operand = tag

        } else if tag == 13 {
            isPerformingOperand = true
            previousNumber = Double(lblDisplay.text!)!
            lblDisplay.text = "÷"
            operand = tag

        } else if tag == 14 {
            isPerformingOperand = true
            previousNumber = Double(lblDisplay.text!)!
            lblDisplay.text = "-"
            operand = tag

        } else if tag == 15 {
            isPerformingOperand = true
            previousNumber = Double(lblDisplay.text!)!
            lblDisplay.text = "+"
            operand = tag
        }
         else if tag == 16 {
                if lblDisplay.text != "" {
                    lblDisplay.text?.removeLast();
                }
        }

        /* clear button tab17 */
        else if tag == 17 {
            lblDisplay.text = ""
            previousNumber = 0
            numberOnDisplay = 0
            operand = 0
        }




        else if tag == 99 {
            /*   = / + -   */
            // operand tag

            if operand == 12 {
            lblDisplay.text = String(previousNumber * numberOnDisplay)

            } else if operand == 13 {
            lblDisplay.text = String(previousNumber / numberOnDisplay)

            } else if operand == 14 {
            lblDisplay.text = String(previousNumber - numberOnDisplay)

            } else if operand == 15 {
            lblDisplay.text = String(previousNumber + numberOnDisplay)
            }
        } 
    } 
}

【问题讨论】:

  • “我如何将输入传递给我需要创建的新‘计算器逻辑类’?”就像你在任何地方传递任何东西一样。调用方法。
  • 从删除标签开始。您不必只使用一种方法来处理所有按钮点击。你的操作数应该是enum
  • 你想在另一堂课上学什么?
  • @NajeeburRehman 我需要将计算器逻辑移动到一个单独的类中。我相信我需要将数学运算符(x、/、+、- 等)和 clear 移到单独的类中。这是一项作业,根据我最初的编码方式,我真的不知道如何最好地进行。
  • 参见斯坦福课程的this video。节目大约在 17 分钟后开始,但引导讨论很有用。

标签: ios swift xcode class calculator


【解决方案1】:

第 1 步:

定义业务逻辑类应该做什么和不应该做什么:

  • 由于这是纯逻辑,它应该与标签系统无关。您必须为其提供纯数学模型。
  • 它应该在计算完成时向您的视图控制器发送消息,或者应该清除屏幕。

第 2 步:

将您的模型定义为原始枚举:

enum Operand {
    case plus
    case minus
    case times
    case divisor
}

enum SpecialOperands {
    case dot
    case clear
    case whitespace
    case compute
}

第 3 步(在 CalculatorBusinessLogic.swift 文件中):

通过提供它必须满足的合同来定义业务类应该做什么:

protocol CalculatorBusinessLogic {
    var delegate: CalculatorBusinessLogicDelegate? { get set }

    func provideNumberInput(number: Int)
    func provideOperandInput(operand: Operand)
    func provideSpecialOperandInput(operand: SpecialOperands)
}

以及它应该将什么结果发送回您的视图控制器:

protocol CalculatorBusinessLogicDelegate: class {
    func onComputationDone(previousNumber: Int, currentNumber: Int, operand: Operand, result: Int)
    func clearScreen()
}

第 4 步:(在 Calculator.swift 文件中):

实现契约,将所有与逻辑相关的属性移到类中:

class Calculator: CalculatorBusinessLogic {

    weak var delegate: CalculatorBusinessLogicDelegate?

    var numberOnDisplay: Double = 0
    var previousNumber: Double?
    var currentNumber: Double?
    var currentOperand: Operand?
    var operand = 0
    var isPerformingOperand = false

    // TODO: handle inputs here, fire delegate when needed to notify View Controller
    func provideNumberInput(number: Int) {
        //...
    }
    func provideOperandInput(operand: Operand) {
        //...
    }
    func provideSpecialCharacterInput(operand: SpecialOperands) {

        //...
        if operand == .clear {
            delegate?.clearScreen()
        }

        if operand == .compute, let previousNumber = self.previousNumber, let currentOperand = self.currentOperand, let currentNumber = self.currentNumber {
            delegate?.onComputationDone(previousNumber: previousNumber, currentNumber: currentNumber, operand: currentOperand, result: /* compute result here */)
        }
        //...

    }

}

在此处使用Test Driven Development 可以帮助您处理复杂的错误情况(操作数错误、除以零...)

第 5 步:(在您的 ViewController.swift 文件中):

声明逻辑类:

var calculatorLogic: CalculatorBusinessLogic = Calculator()

在 viewDidLoad 中设置委托:

calculatorLogic.delegate = self

只要检测到相关输入,就会触发计算器逻辑函数。 实现委托以对计算结果做出反应:

extension ViewController: CalculatorBusinessLogicDelegate {
    func onComputationDone(previousNumber: Int, currentNumber: Int, operand: Operand, result: Int) {
        lblDisplay.text = "\(result)"
    }

    func clearScreen() {
        lblDisplay.text = ""
    }
}

您可以通过谷歌搜索端口适配器架构/清洁架构来阅读有关如何在 iOS 应用程序中分离类的更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多