電卓に履歴機能を追加したい
解決したいこと
あるお方の動画を見ながら電卓のコードを書いたのですが、ボタンを押したら計算した履歴が画面遷移して見れるようにしたいのですがやり方がわかりません。どなたか教えてください。
押すボタンはlogと書かれたボタンにしてください
移動先のファイル名はLogViewにしてくだい
ソースコード
import SwiftUI
enum CaluculateState {
case initial, addition, substraction, division, multiplication, sum
}
struct ContentView: View {
@State var selectedItem: String = "0"
@State var caluculatedNumber: Double = 0
@State var caluculateState: CaluculateState = .initial
private let caluculateItems: [[String]] = [
["AC", "list", "log", "count"],
["7", "8", "9", "÷"],
["4", "5", "6", "X"],
["1", "2", "3", "-"],
["0", ".", "=", "+"],
]
var body: some View {
ZStack {
Color.black
.ignoresSafeArea()
VStack {
Spacer()
HStack {
Spacer()
Text(selectedItem == "0" ? checkDecimal(number: caluculatedNumber) : selectedItem)
.font(.system(size: 100, weight: .light))
.foregroundColor(Color.white)
.padding()
.lineLimit(1)
.minimumScaleFactor(0.4)
}
VStack {
ForEach(caluculateItems, id: \.self) { items in
NumberView(selectedItem: $selectedItem,
caluculatedNumber: $caluculatedNumber,
caluculateState: $caluculateState,
items: items)
}
}
}
.padding(.bottom, 40)
}
}
private func checkDecimal(number: Double) -> String {
if number.truncatingRemainder(dividingBy: 1).isLess(than: .ulpOfOne) {
return String(Int(number))
} else {
return String(number)
}
}
}
struct NumberView: View {
@State var CmView = false
@State var LOGView = false
@State var LISTView = false
@Binding var selectedItem: String
@Binding var caluculatedNumber: Double
@Binding var caluculateState: CaluculateState
var items: [String]
private let buttonWidth: CGFloat = (UIScreen.main.bounds.width - 50) / 4
private let numbers: [String] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "."]
private let symbols: [String] = ["÷", "X", "-", "+", "="]
var body: some View {
HStack {
ForEach(items, id: \.self) { item in
Button {
handleButtonInfo(item: item)
} label: {
Text(item)
.font(.system(size: 30, weight: .regular))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
.foregroundColor(numbers.contains(item) || symbols.contains(item) ? .white : .black)
.background(handleButtonColor(item: item))
.sheet(isPresented: $LOGView) {
LogView()
}
.sheet(isPresented: $CmView) {
CMView()
}
.sheet(isPresented: $LISTView) {
ListView()
}
.cornerRadius(buttonWidth)
}
.frame(height: buttonWidth)
}
}
private func handleButtonColor(item: String) -> Color {
if numbers.contains(item) {
return Color(white: 0.2, opacity: 1)
} else if symbols.contains(item) {
return Color.orange
} else {
return Color(white: 0.8, opacity: 1)
}
}
private func handleButtonInfo(item: String) {
if numbers.contains(item) {
if item == "." && (selectedItem.contains(".") || selectedItem.contains("0")) {
return
}
if selectedItem.count >= 10 {
return
}
if selectedItem == "0" {
selectedItem = item
return
}
selectedItem += item
} else if item == "AC" {
selectedItem = "0"
caluculatedNumber = 0
caluculateState = .initial
}else if item == "log" {
LOGView = true
}else if item == "list" {
LISTView = true
}else if item == "count" {
CmView = true
}
guard let selectedNumber = Double(selectedItem) else { return }
if item == "÷" {
setCaluculate(state: .division, selectedNumber: selectedNumber)
} else if item == "X" {
setCaluculate(state: .multiplication, selectedNumber: selectedNumber)
} else if item == "-" {
setCaluculate(state: .substraction, selectedNumber: selectedNumber)
} else if item == "+" {
setCaluculate(state: .addition, selectedNumber: selectedNumber)
} else if item == "=" {
selectedItem = "0"
caluculate(selectedNumber: selectedNumber)
caluculateState = .sum
}
}
private func setCaluculate(state: CaluculateState, selectedNumber: Double) {
if selectedItem == "0" {
caluculateState = state
return
}
selectedItem = "0"
caluculateState = state
caluculate(selectedNumber: selectedNumber)
}
private func caluculate(selectedNumber: Double) {
if caluculatedNumber == 0 {
caluculatedNumber = selectedNumber
return
}
switch caluculateState {
case .addition:
caluculatedNumber = caluculatedNumber + selectedNumber
case .substraction:
caluculatedNumber = caluculatedNumber - selectedNumber
case .division:
caluculatedNumber = caluculatedNumber / selectedNumber
case .multiplication:
caluculatedNumber = caluculatedNumber * selectedNumber
default:
break
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
解決したコード↓
import SwiftUI
import CoreData
enum CaluculateState {
case initial, addition, substraction, division, multiplication, sum
}
struct ContentView: View {
@State var selectedItem: String = "0"
@State var caluculatedNumber: Double = 0
@State var caluculateState: CaluculateState = .initial
private let caluculateItems: [[String]] = [
["count", "list", "log", "AC"],
["7", "8", "9", "÷"],
["4", "5", "6", "X"],
["1", "2", "3", "-"],
["0", ".", "=", "+"],
]
var body: some View {
ZStack {
Color.black
.ignoresSafeArea()
VStack {
Spacer()
HStack {
Spacer()
Text(selectedItem == "0" ? checkDecimal(number: caluculatedNumber) : selectedItem)
.font(.system(size: 100, weight: .light))
.foregroundColor(Color.white)
.padding()
.lineLimit(1)
.minimumScaleFactor(0.4)
}
VStack {
ForEach(caluculateItems, id: \.self) { items in
NumberView(selectedItem: $selectedItem,
caluculatedNumber: $caluculatedNumber,
caluculateState: $caluculateState,
items: items)
}
}
}
.padding(.bottom, 40)
}
}
private func checkDecimal(number: Double) -> String {
if number.truncatingRemainder(dividingBy: 1).isLess(than: .ulpOfOne) {
return String(Int(number))
} else {
return String(number)
}
}
}
struct NumberView: View {
@State var CmView = false
@State var LOGView = false
@State var LISTView = false
@Binding var selectedItem: String
@Binding var caluculatedNumber: Double
@Binding var caluculateState: CaluculateState
@Environment(\.managedObjectContext) private var context
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \LogsData.answer, ascending: true)],animation: .default) var Data: FetchedResults<LogsData>
var items: [String]
private let buttonWidth: CGFloat = (UIScreen.main.bounds.width - 50) / 4
private let numbers: [String] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "."]
private let symbols: [String] = ["÷", "X", "-", "+", "="]
var body: some View {
HStack {
ForEach(items, id: \.self) { item in
Button {
handleButtonInfo(item: item)
} label: {
Text(item)
.font(.system(size: 30, weight: .regular))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
.foregroundColor(numbers.contains(item) || symbols.contains(item) ? .white : .black)
.background(handleButtonColor(item: item))
.sheet(isPresented: $LOGView) {
LogView()
}
.sheet(isPresented: $CmView) {
CMView()
}
.sheet(isPresented: $LISTView) {
ListView()
}
.cornerRadius(buttonWidth)
}
.frame(height: buttonWidth)
}
}
private func handleButtonColor(item: String) -> Color {
if numbers.contains(item) {
return Color(white: 0.2, opacity: 1)
} else if symbols.contains(item) {
return Color.orange
} else {
return Color(white: 0.8, opacity: 1)
}
}
private func handleButtonInfo(item: String) {
if numbers.contains(item) {
if item == "." && (selectedItem.contains(".") || selectedItem.contains("0")) {
return
}
if selectedItem.count >= 10 {
return
}
if selectedItem == "0" {
selectedItem = item
return
}
selectedItem += item
} else if item == "AC" {
selectedItem = "0"
caluculatedNumber = 0
caluculateState = .initial
}else if item == "log" {
LOGView = true
}else if item == "list" {
LISTView = true
}else if item == "count" {
CmView = true
}
guard let selectedNumber = Double(selectedItem) else { return }
if item == "÷" {
setCaluculate(state: .division, selectedNumber: selectedNumber)
} else if item == "X" {
setCaluculate(state: .multiplication, selectedNumber: selectedNumber)
} else if item == "-" {
setCaluculate(state: .substraction, selectedNumber: selectedNumber)
} else if item == "+" {
setCaluculate(state: .addition, selectedNumber: selectedNumber)
} else if item == "=" {
selectedItem = "0"
caluculate(selectedNumber: selectedNumber)
caluculateState = .sum
}
}
private func setCaluculate(state: CaluculateState, selectedNumber: Double) {
if selectedItem == "0" {
caluculateState = state
return
}
selectedItem = "0"
caluculateState = state
caluculate(selectedNumber: selectedNumber)
}
private func save() {
}
private func caluculate(selectedNumber: Double) {
let FN = caluculatedNumber
if caluculatedNumber == 0 {
caluculatedNumber = selectedNumber
return
}
switch caluculateState {
case .addition:
caluculatedNumber = caluculatedNumber + selectedNumber
let t = LogsData(context: context)
t.answer = String("\(FN)+\(selectedNumber)=\(caluculatedNumber)")
do {
try context.save()
} catch {
}
case .substraction:
caluculatedNumber = caluculatedNumber - selectedNumber
let t = LogsData(context: context)
t.answer = String("\(selectedItem)-\(setCaluculate)=\(caluculatedNumber)")
do {
try context.save()
} catch {
}
case .division:
caluculatedNumber = caluculatedNumber / selectedNumber
let t = LogsData(context: context)
t.answer = String("\(selectedItem)÷\(setCaluculate)=\(caluculatedNumber)")
do {
try context.save()
} catch {
}
case .multiplication:
caluculatedNumber = caluculatedNumber * selectedNumber
let t = LogsData(context: context)
t.answer = String("\(selectedItem)X\(setCaluculate)=\(caluculatedNumber)")
do {
try context.save()
} catch {
}
default:
break
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
参考になったサイト・動画
0