見出し画像

SwiftUIで行こう! 電卓を作ろ!-演算しましょ。

https://note.com/dngri/n/n00eb7baa824d

 の続きです。数字が打てるようになったのでいよいよ演算していきます。

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

を参考に作っていきます。

struct UnarySymbols:View

について演算ができるように計算ができるように関数funcを作っていきます。

let symbols = ["π","√","±","="]

と宣言しているので、この記号がなんであるかによって動作を変えます。

    func performOperation(_ symbol:String){
       switch symbol {
       case "π":
           self.display = String(Double.pi)
       default:
           break
       }
   }

そしてButtonのactionの関数を入れます。

Button(mathSymbol,action:{
       self.performOperation(mathSymbol)
 })

これで、実行して"π"をいれると表示部に"π"と表示されます。

次に表示部に関係する部分のコードを整理します。ContentView.swiftファイルのstruct ContentView: View{} の上に書いていきます。

class CalcViewModel:ObservableObject{
   @Published var display = "0"
   @Published var middleTyping = false
}

表示するデータ、打ち始めを決めていくデータを格納する変数を持ちます。ここでこのclassは階層を超えて使うことになるclassということで、

プロトコルは

ObservableObject

変数には

@Published

をつけます。そしてもう一つ作業があります。

class SceneDelegate{}

にコードを追加していきます。

   var window: UIWindow?
   var calculatorViewModel = CalcViewModel()
   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
       
       let contentView = ContentView().environmentObject(CalcViewModel())
       
       if let windowScene = scene as? UIWindowScene {
           let window = UIWindow(windowScene: windowScene)
           window.rootViewController = UIHostingController(rootView: contentView)
           self.window = window
           window.makeKeyAndVisible()
       }
   }

大事なところは、先ほど作ったクラスをenvironmentObjectとして登録します。

let contentView = ContentView().environmentObject(CalcViewModel())

これが終われば、

displayと middleTypingを最初に書いたものと入れ替えていきます。

それぞれの構造体structに

@EnvironmentObject var calcVM: CalcViewModel

を追加し、displaymiddleTypingとしていたと calcVM.displaycalcVM.middleTypingとしていきます。

ここで気をつけないといけないのが、ContentView: View{}で読み込む構造体structを

            HStack{
               UnarySymbols()
               Digits()

にしておかないとエラーがでます。

演算子をもう一つ追加しましょう

func performOperation{}

に"case"を追加します。ルートです。

case "√":
     let operand = Double(calcVM.display)!
     calcVM.display = String(String(sqrt(operand)))
     self.calcVM.middleTyping = false

そして

calcVM.display = String(String(sqrt(operand)))

の部分をスッキリさせましょう。Computed Propertieを使います。変数に自動的に何か処理をさせることができます。

https://note.com/dngri/n/n5718cee6df68?magazine_key=m39ffd3b6c431

class CalcViewModel{}の中で使います。

var displayValue:Double{
     get{
        return Double(display)!
     }
     set{
        display = String(newValue)
     }
 }

今あるデータ(get)を文字列から数字にする。もうひとつ、受け取ったデータ(数字)を文字列にします。

組み込みます。

 func performOperation(_ symbol:String){
       switch symbol {
       case "π":
           calcVM.displayValue = Double.pi
           self.calcVM.middleTyping = false
       case "√":
           calcVM.displayValue = sqrt(calcVM.displayValue)
           self.calcVM.middleTyping = false
       default:
           break
       }
   }

case "π"の場合、文字列から数字へ変換して"self.display"に入れています。

self.display = String(Double.pi)

から

calcVM.displayValue = Double.pi

としています。これは、"calcVM.displayValue"自体がデータを受け取った場合に数字にする機能があるため、"String()"の必要がなくなったということです。

calcVM.displayValue = sqrt(calcVM.displayValue)

の場合は文字列のデータを受け取り

変数display に入った時点で →  displayValueで数字に変換。

それを平方根(sqrt)

sqrt(calcVM.displayValue)

してさらに文字列にしています。

コードもスッキリしてみやすくなりました。

画像1

実行するとこんな感じで演算子"π""√"、が使えるようになりました。

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