見出し画像

SwiftUIで行こう! 電卓を作ろ!-機能を追加!-仕上げ。

続いて、コードを整理していき、機能を追加していきます。

参考サイトです。

https://www.youtube.com/watch?v=hBO81LgQcJM

switch 文をも変更していきます。

switch symbol

を配列で置き換えます。symbolを"enum"でOperationとしてその種類を指定した算術式を定義します。

private enum Operation{
    case constant(Double)
    case unaryOperation((Double) -> Double)
    case binaryOperation((Double,Double)->Double)
    case equals
   }

ここで、配列、辞書を作っていきます。

  private var operations:Dictionary = [
       "π" : Operation.constant(Double.pi),
       "√" : Operation.unaryOperation(sqrt),
       "X" : Operation.binaryOperation({$0 * $1}),
       "=": Operation.equals
   ]

次からは、実際に演算子を受け取って表示部分に表示させるコードを書いていきます。ここではswich文を使います。

switch operation {
}

として、配列である変数"operation"の値により振り分けます。switch文全体のコードです。

 mutating func performOperation(_ symbol:String){
       if let operation = operations[symbol]{
           switch operation {
           case .constant(let value):
               accumulator = value
            case .unaryOperation(let function):
               if accumulator != 0{
                   accumulator = function(accumulator!)
               }
               break
            case .binaryOperation(let function):
               if accumulator != nil {
                   pbo = PendingBinaryOperation(function: function, firstOperand: accumulator!)
                   accumulator = nil
               }
               
               case .equals:
               performPendingBinaryOperation()
  
           }
       }
   }

上2つの"case" の場合は、配列の中身は

"π" : Operation.constant(Double.pi),
"√" : Operation.unaryOperation(sqrt),

であり、

case .constant(let value):
  accumulator = value
case .unaryOperation(let function):
  if accumulator != 0{
  accumulator = function(accumulator!)
}
break

このマークが押されたら即演算となりますので単純です。

次のswitch文、下2つの"case"は2つの数字を使った計算をするためのコードです。

case .binaryOperation(let function):
  if accumulator != nil {
  pbo = PendingBinaryOperation(function: function, firstOperand:               accumulator!)
  accumulator = nil
  }

case .equals:
  performPendingBinaryOperation()

その仕組みはというと以下2つの関数と1つの変数からなっています。

以下、"case .equals:"ということで"="を押した時の命令です。

private mutating func performPendingBinaryOperation() {
       if pbo != nil && accumulator != nil {
           accumulator = pbo!.perform(with: accumulator!)
           pbo = nil
       }
   }
private var pbo: PendingBinaryOperation?
  private struct PendingBinaryOperation {
       let function: (Double, Double) -> Double
       let firstOperand: Double
       
       func perform(with secondOperand: Double) -> Double {
           return function(firstOperand, secondOperand)
       }
   }

変数pboはstruct PendingBinaryOperation{}を実体化したもの、今回は掛け算を実行するコードです。

enum Operationの

case binaryOperation((Double,Double)->Double)

var operations:Dictionary

"X" : Operation.binaryOperation({$0 * $1}),

に該当します。

PendingBinaryOperation{}のfunc perform()で実際に2つの値について計算しています。

func perform(with secondOperand: Double) -> Double {
return function(firstOperand, secondOperand)
}

function(firstOperand, secondOperand)がvar operations:Dictionaryの

"X" : Operation.binaryOperation({$0 * $1}),

{$0 * $1}で計算されています。

struct CalcBrain{}の全体のコードです。

private enum Operation{
       case constant(Double)
       case unaryOperation((Double) -> Double)
       case binaryOperation((Double,Double)->Double)
       case equals
   }
   
   private var operations:Dictionary = [
       "π" : Operation.constant(Double.pi),
       "√" : Operation.unaryOperation(sqrt),
       "X" : Operation.binaryOperation({$0 * $1}),
       "=": Operation.equals
   ]
   mutating func performOperation(_ symbol:String){
       if let operation = operations[symbol]{
           switch operation {
           case .constant(let value):
               accumulator = value
            case .unaryOperation(let function):
               if accumulator != 0{
                   accumulator = function(accumulator!)
               }
               break
            case .binaryOperation(let function):
               if accumulator != nil {
                   pbo = PendingBinaryOperation(function: function, firstOperand: accumulator!)
                   accumulator = nil
               }
               
               case .equals:
               performPendingBinaryOperation()
  
           }
       }
   }
   
   private mutating func performPendingBinaryOperation() {
       if pbo != nil && accumulator != nil {
           accumulator = pbo!.perform(with: accumulator!)
           pbo = nil
       }
   }
   
   private var pbo: PendingBinaryOperation?
   
   private struct PendingBinaryOperation {
       let function: (Double, Double) -> Double
       let firstOperand: Double
       
       func perform(with secondOperand: Double) -> Double {
           return function(firstOperand, secondOperand)
       }
   }

この記事が気に入ったらサポートをしてみませんか?