Swift5+Xcode11.6
おそるおそるSwift 2-4 デンタッキー(電卓)を作る ~電卓らしく計算させる機能を追加する~
Swift5+Xcode11.6 シリーズ2の4回目です。 今回のゴール 続きです。下の動画のように、一端の電卓として機能するように、計算させる機能を追加します。コードはContentView.swiftに書きました。 […]
今回のゴール
続きです。入力履歴機能を追加しました。コードはContentView.swiftに書きました。
後半は変更がないので省略しています。
import SwiftUI struct ContentView: View { @State var inputArray :[String] = [] //リスト表示用 @State var inputStr :String = "" let CalStr :[String] = ["+","-"] //計算記号一覧 func outputStr(tmpStr :String) { // var str1 :String = "" if tmpStr == "C" { self.inputStr = "" self.inputArray = [] } else if tmpStr == "=" { var tmpStr2 :String = "" //配列の文字をキャッシュ var tmpResult :Double = 0.0 //計算途中の数値をキャッシュ var symbol :String //四則計算の区別 self.inputArray.append(self.inputStr) self.inputStr = tmpStr for item in self.inputArray { let str = item let start1 = str.startIndex //配列要素の最初の文字を取得 symbol = String(str[start1]) if self.CalStr.contains(symbol) == false { tmpResult = atof(item) //atofは文字列をDoubleに変換する関数 print("I'm Here!") } else { tmpStr2 = String(str.suffix(item.count - 1)) print("tmpStr2\(tmpStr2)") switch symbol { case "+": tmpResult += atof(tmpStr2) case "-": tmpResult -= atof(tmpStr2) default: tmpResult = 9999999.0 } } } self.inputStr = String(tmpResult) } else if (self.CalStr.contains(tmpStr))&&(inputStr != "") { self.inputArray.append(self.inputStr) self.inputStr = tmpStr } else { self.inputStr += tmpStr } } func delete(at offsets: IndexSet) { if let first = offsets.first { self.inputArray.remove(at: first) } } var body: some View { VStack { List{ ForEach (self.inputArray, id: \.self) { index in Text(index) } .onDelete(perform: delete) } //配列データの一意性を保証するために、id: \.selfが必要。 VStack { Text("\(self.inputStr)") .font(.largeTitle) .fontWeight(.heavy) .foregroundColor(Color.red) .multilineTextAlignment(.trailing) .frame(width: 300.0)
とりあえず、計算結果表示用テキストフィールドの上に、リストを追加しています。いまさらですが、VBAやその他の言語のようにオブジェクトに名前をつけて、処理対象となるオブジェクトを指定する方法ではなく、オブジェクトそのものに処理内容を入れるSwiftUIはかなり個性的で、慣れが必要です。
ついでにForEach構文も慣れる必要があります。58~61行目は次のような記述も可能です。
List{ ForEach (0..<self.inputArray.count,id: \.self) { index in Text(self.inputArray[index]) }
いずれにせよ、id:\.selfは必須で無いとエラーになります。まあ、Xcodeが直してくれますが。
62行目の.onDeleteは、リストの項目を削除させるときの処理内容を指定するための予約語です。デンタッキーでは、func delete(50〜54行目)が実行されます。この部分はサイトで拾ってきたのでやや意味を理解しきれていないのですが、.onDeleteから対象となる場所(Indexset)を引数でもらい、それを配列番号に変換して削除しているのだろうと、今のところ理解しています。
ちなみに、Indexsetは”1 indexes”を返し、ユーザ定義関数first(=Indexset.first)は削除対象の行列番号を返します。
次回は
細かいイレギュラー入力への対応や加減以外の計算機能は実装していませんが、とりあえず自分なりの目標には到達したので一旦ここで開発を終了します。
興味がある方はシリーズ3もご覧ください!