Written by
Amy
on
on
Swift 계산기 만들기 v0.5
연산 기호 중복 클릭 처리 기능 추가, 단항 연산 오류 수정
연산 처리를 담당하는 클래스 (모델)
import Foundation
class CalculatorModel {
// 연산 타입 정의 : 단일, 이항, 등호
// Associated Value 값에 클로저 대입
private enum OperatoinCase {
case unary((Double) -> Double)
case binary((Double,Double) -> Double)
case equal
}
// 연산 기호 : 연산 타입 딕셔너리 생성
private var operDic: [String:OperatoinCase] = [
"+": .binary({(num1, num2) -> Double in return num1 + num2}),
"-": .binary({(num1, num2) -> Double in return num1 - num2}),
"*": .binary({(num1, num2) -> Double in return num1 * num2}),
"/": .binary({(num1, num2) -> Double in return num1 / num2}),
"cos": .unary(cos),
"√": .unary(sqrt),
"±": .unary({(num1: Double) -> Double in return -num1}),
"=": .equal
]
// 연산을 기다리는 옵셔널 Double 변수 생성
var leftNumber: Double?
// 연산 기호 클릭 시 leftNum에 디스플레이 값 대입
func setNumber(displayNum: Double){
leftNumber = displayNum
}
// 바이너리 연산을 위한 스트럭트 WaitingBinary의 인스턴스
private var waitingBinary: WaitingBinary?
// 연산 클릭시 연산 수행
var operand: Double?
func perfomrOperation(mathSymbol: String) {
if let operationCase = operDic[mathSymbol] {
switch operationCase {
case .unary(let function):
if leftNumber != nil && operand == nil {
operand = function(leftNumber!)
}else if leftNumber != nil && operand != nil {
operand = function(operand!)
}
case .binary(let binaryFunc):
if leftNumber != nil && operand == nil {
operand = leftNumber!
waitingBinary = WaitingBinary(firstNum: operand!, waitingFunc: binaryFunc)
}else if leftNumber != nil && operand != nil {
operand! = waitingBinary!.doBinaryOp(with: leftNumber!)
waitingBinary = WaitingBinary(firstNum: operand!, waitingFunc: binaryFunc)
}else if operand != nil && leftNumber == nil {
waitingBinary = WaitingBinary(firstNum: operand!, waitingFunc: binaryFunc)
}
leftNumber = nil
case .equal:
getResult()
}
}
}
// Binary 연산을 저장하고 있을 Struct
private struct WaitingBinary {
let firstNum: Double
let waitingFunc: (Double,Double) -> Double
func doBinaryOp(with secondNum: Double) -> Double {
return waitingFunc(firstNum, secondNum)
}
}
// Binary 연산의 결과값 구하기 (Equal 연산)
var returnValue: Double? // ViewController에 넘겨줄 연산 완료 값
private func getResult() {
if waitingBinary != nil && leftNumber != nil {
returnValue = waitingBinary!.doBinaryOp(with: leftNumber!)
}
}
}
뷰 콘트롤러
class UpgradeCalculatorViewControler: UIViewController {
//MARK: - UI Property
@IBOutlet weak var displayLB: UILabel!
//MARK: - IBAction
//숫자 입력받기 OK
var isTyping: Bool = false
@IBAction func digit(_ sender: UIButton) {
let currentDigit = sender.currentTitle!
if isTyping {
let textCurrentlyInDisplay = displayLB!.text!
displayLB!.text = textCurrentlyInDisplay + currentDigit
}else {
displayLB!.text = currentDigit
isTyping = true
}
}
// 리셋
@IBAction func resetHandler(_ sender: UIButton) {
displayValue = 0.0
isTyping = false
calModel.setNumber(displayNum: displayValue)
calModel.operand = nil
}
// 전시된 값을 get 하거나 set하는 displayValue
var displayValue: Double {
get {
return Double(displayLB.text!)!
}
set {
displayLB.text! = String(newValue)
}
}
// operation
var calModel = CalculatorModel()
@IBAction func operation(_ sender: UIButton) {
if isTyping { // check
calModel.setNumber(displayNum: displayValue)
isTyping = false
}
guard let symbol = sender.currentTitle else { return }
calModel.perfomrOperation(mathSymbol: symbol)
if symbol == "=" {
displayValue = calModel.returnValue!
}else {
displayValue = calModel.operand!
}
}
}