개발

RxSwift로 계산기 로직 만들기

한번사는인생~키야 2024. 7. 9. 13:06
728x90

RxSwift로 간단한 계산기 로직 구현

RxSwift를 사용하여 간단한 계산기 로직을 함수형 프로그래밍 방식으로 효율적으로 구현할 수 있습니다.

1. 계산기 버튼 및 레이블 설정

  • UIViewController에서 계산기 버튼과 결과 출력 레이블을 생성하고 레이아웃을 설정합니다.
  • 각 버튼 클릭 이벤트를 Observable로 변환하여 처리합니다.
import UIKit

import RxSwift

import RxCocoa



class CalculatorViewController: UIViewController {



    @IBOutlet weak var resultLabel: UILabel!

    @IBOutlet weak var numberButtons: [UIButton]!

    @IBOutlet weak var operatorButtons: [UIButton]!



    private let disposeBag = DisposeBag()



    override func viewDidLoad() {

        super.viewDidLoad()



        setupNumberButtons()

        setupOperatorButtons()

    }



    private func setupNumberButtons() {

        numberButtons.forEach { button in

            button.rx.tap

                .map { button.titleLabel?.text ?? "" }

                .subscribe(onNext: { numberString in

                    // 계산 로직 처리

                    self.updateResultLabel(withNumber: numberString)

                })

                .disposed(by: disposeBag)

        }

    }



    private func setupOperatorButtons() {

        operatorButtons.forEach { button in

            button.rx.tap

                .map { button.titleLabel?.text ?? "" }

                .subscribe(onNext: { operatorSymbol in

                    // 계산 로직 처리

                    self.applyOperator(operatorSymbol: operatorSymbol)

                })

                .disposed(by: disposeBag)

        }

    }



    // 결과 레이블 업데이트

    private func updateResultLabel(withNumber numberString: String) {

        if let currentResult = resultLabel.text {

            resultLabel.text = "\(currentResult)\(numberString)"

        } else {

            resultLabel.text = numberString

        }

    }



    // 연산자 처리

    private func applyOperator(operatorSymbol: String) {

        // ... (계산 로직 구현)

    }

}

 

2. RxSwift를 사용한 계산 로직 구현

  • Observable과 BehaviorSubject를 사용하여 현재 계산 값을 저장하고 변경 사항을 관리합니다.
  • scan연산자를 사용하여 이전 값과 새로운 값을 기반으로 계산 결과를 누적합니다.
extension CalculatorViewController {



    private let currentNumberSubject = BehaviorSubject<String>(value: "")

    private let currentOperatorSubject = BehaviorSubject<String?>(value: nil)

    private let resultSubject = PublishSubject<String>()



    override func viewDidLoad() {

        super.viewDidLoad()



        // 현재 숫자 Observable

        currentNumberSubject

            .subscribe(onNext: { [weak self] numberString in

                self?.updateResultLabel(withNumber: numberString)

            })

            .disposed(by: disposeBag)



        // 현재 연산자 Observable

        currentOperatorSubject

            .subscribe(onNext: { [weak self] operatorSymbol in

                // 연산자에 따른 처리

                if let operatorSymbol = operatorSymbol {

                    self?.applyOperator(operatorSymbol: operatorSymbol)

                }

            })

            .disposed(by: disposeBag)



        // 결과 Observable

        resultSubject

            .subscribe(onNext: { [weak self] resultString in

                self?.resultLabel.text = resultString

            })

            .disposed(by: disposeBag)

    }



    // 결과 레이블 업데이트

    private func updateResultLabel(withNumber numberString: String) {

        currentNumberSubject.onNext(numberString)

    }



    // 연산자 처리

    private func applyOperator(operatorSymbol: String) {

        guard let currentNumberString = currentNumberSubject.value else { return }

        guard let currentNumber = Double(currentNumberString) else { return }



        // 이전 연산 결과 계산

        if let previousResult = resultSubject.value, let previousResultNumber = Double(previousResult) {

            switch currentOperatorSubject.value {

            case "+":

                let result = previousResultNumber + currentNumber

                resultSubject.onNext(String(result))

            case "-":

                let result = previousResultNumber - currentNumber

                resultSubject.onNext(String(result))

            case "*":

                let result = previousResultNumber * currentNumber

                resultSubject.onNext(String(result))