개발
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))