본문 바로가기

📱 Mobile/iOS

[iOS - SwiftUI] 계산기 만들기

SwiftUI로 계산기 만들기

 

 

Button 사이즈를 잡아주는 함수를 만든다. 

buttonWidth 같은 경우에는 0 버튼일 경우에는 다른 버튼들과는 다르게 넓은 width를 줘야하기 때문에 따로 조건을 넣어준다. 

 

/// Button Width
func buttonWidth(item: CalculatorButton) -> CGFloat {
    // 0일 경우에만 넓은 width를 준다!
    if item == .zero {
        return ((UIScreen.main.bounds.width - (4 * 12)) / 4) * 2
    }
    return (UIScreen.main.bounds.width - (5 * 12)) / 4
}

/// Button Height
func buttonHeight() -> CGFloat {
    return (UIScreen.main.bounds.width - (5 * 12)) / 4
}

 

 

 

Button을 enum 형태로 숫자, 연산자로 나눈다. 

숫자나 연산자마다 색상도 다르게 적용한다. 

 

enum CalculatorButton: String {
    // 숫자
    case one = "1"
    case two = "2"
    case three = "3"
    case four = "4"
    case five = "5"
    case six = "6"
    case seven = "7"
    case eight = "8"
    case nine = "9"
    case zero = "0"
    
    // 연산자
    case subtract = "\u{2212}"
    case add = "\u{002B}"
    case divide = "\u{00F7}"
    case multiply = "\u{00D7}"
    case equal = "="
    case clear = "AC"
    case decimal = "."
    case percent = "%"
    case negative = "\u{002B}/-"
    
    var buttonColor: Color {
        switch self {
        case .add, .subtract, .divide, .multiply, .equal:
            return Color(red: 244 / 255, green: 196 / 255, blue: 230 / 255)
        case .clear, .negative, .percent:
            return Color(red: 196 / 255, green: 244 / 255, blue: 239 / 255)
        default:
            return Color(red: 215 / 255, green: 196 / 255, blue: 244 / 255)
        }
    }
    
    var foregroundColor: Color {
        switch self {
        case .clear, .negative, .percent:
            return Color(.black)
        default:
            return Color(.white)
        }
    }
}

enum Operation {
    case add, subtract, divide, multiply, none
}

 

 

 

전체 계산기 화면의 버튼들의 UI를 잡아주는 코드이다. 

@State 변수를 사용하여 현재 화면에 보여지는 값(displayNumber), 실행숫자(runningNumber), 연산자(currentOperator), 그리고 화면 초기화 여부(shouldClearDisplay)를 관리한다. 

 

struct MainView: View {
    
    @State private var displayNumber = "0"
    @State private var runningNumber = 0
    @State private var currentOperator: Operation = .none
    @State private var shouldClearDisplay = false
 
    
    private let buttons: [[CalculatorButton]] = [
        [.clear, .negative, .percent, .divide],
        [.seven, .eight, .nine, .multiply],
        [.four, .five, .six, .subtract],
        [.one, .two, .three, .add],
        [.zero, .decimal, .equal]
    ]
    
    var body: some View {
        VStack {
            Spacer()
            HStack {
                Spacer()
                Text("\(displayNumber)")
                    .bold()
                    .font(.system(size: 80))
                    .foregroundColor(.white)
            }
            .padding()
            ForEach(buttons, id: \.self) { button in
                HStack(spacing: 10) {
                    ForEach(button, id: \.self) { item in
                        Button {
                            calculate(button: item)
                        } label: {
                            Text(item.rawValue)
                                .font(.system(size: 40) .bold())
                                .frame(width: buttonWidth(item: item), height: buttonHeight())
                                .background(item.buttonColor)
                                .clipShape(.rect(cornerRadius: buttonWidth(item: item) / 2))
                                .foregroundColor(item.foregroundColor)
                        }
                    }
                }
            }
            .padding(.bottom, 7)
        }
        .padding()
        .background(Color.black)
        .edgesIgnoringSafeArea(.all)
    }
    
}

 

 

 

계산을 하는 calculate 함수이다. 

 

extension MainView {
    func calculate(button: CalculatorButton) {
        switch button {
        case .add, .subtract, .multiply, .divide, .equal:
            if button == .add {
                currentOperator = .add
                runningNumber = Int(displayNumber) ?? 0
            }
            else if button == .subtract {
                currentOperator = .subtract
                runningNumber = Int(displayNumber) ?? 0
            }
            else if button == .multiply {
                currentOperator = .multiply
                runningNumber = Int(displayNumber) ?? 0
            }
            else if button == .divide {
                currentOperator = .divide
                runningNumber = Int(displayNumber) ?? 0
            }
            else if button == .equal {
                let runningValue = runningNumber
                let currentValue = Int(displayNumber) ?? 0
                
                switch self.currentOperator {
                case .add: displayNumber = "\(runningValue + currentValue)"
                case .subtract: displayNumber = "\(runningValue - currentValue)"
                case .multiply: displayNumber = "\(runningValue * currentValue)"
                case .divide: displayNumber = "\(runningValue / currentValue)"
                case .none:
                    break
                }
            }
            shouldClearDisplay = true
            
        case .clear:
            displayNumber = "0"
            runningNumber = 0
            currentOperator = .none
            shouldClearDisplay = false
        case .decimal, .negative, .percent:
            break
        default: // 숫자일 경우
            if shouldClearDisplay {
                displayNumber = button.rawValue
                shouldClearDisplay = false
            } else {
                let number = button.rawValue
                if displayNumber == "0" {
                    displayNumber = number
                }
                else {
                    displayNumber = "\(displayNumber)\(number)"
                }
            }
        }
    }
}

 

 

 

 

 

728x90