관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] RxSwift - scan 연산자 (카운터 기능, toggle 버튼 구현, TextField 입력값 제한) 본문

RxSwift

[iOS - swift] RxSwift - scan 연산자 (카운터 기능, toggle 버튼 구현, TextField 입력값 제한)

jake-kim 2021. 12. 28. 23:01

Scan 연산자

  • Scan 연산자: 이전에 방출된 아이템과 새로 방출된 아이템을 결합하여, 새로운 아이템을 생성
  • 새로운 아이템은 그 다음 방출된 아이템의 prev값
  • Scan 연산자의 핵심은 scan 연산자 내부에 기존 값을 저장하고 새로운 값을 받아서 연산 할 수 있다는 것

scan 연산자 예시1) +, - 카운터 기능 구현

  • 사용할 프레임워크
pod 'RxSwift'
pod 'RxCocoa'
pod 'SnapKit'

UI 준비 - ViewController

  • +, - 버튼을 탭했을 때 카운트를 표출할 UILabel, UIButton 준비

  • 값을 방출하고 구독도 할수 있는 BehaviorRelay 변수 선언
    let countRelay = BehaviorRelay<Int>(value: 0)​
  • 버튼이 탭할때마다 countRelay 변수에 증감값 바인딩
self.addButton.rx.tap
  .map { 1 }
  .bind(to: self.countRelay)
  .disposed(by: self.disposeBag)

self.subtractButton.rx.tap
  .map { -1 }
  .bind(to: self.countRelay)
  .disposed(by: self.disposeBag)
  • Scan 연산자를 통해 증감 구현
self.countRelay
  .scan(0, accumulator: { $0 + $1 }) // 초기값:0, $0: lastValue, $1: newValue
  .withUnretained(self)
  .bind { $0.countLabel.text = "\($1)" }
  .disposed(by: self.disposeBag)

scan 연산자 예시2) toggle 버튼 구현

  • button의 tap을 바인딩으로, scan 연산자로 초기값은 false, 새로운 값은 !lastValue를 리턴하도록 구현
    self.button.rx.tap
      .scan(false) { lastState, newState in !lastState }
      .map { "버튼이 현재 선택되어있는지? -> \($0)" }
      .bind(to: self.toggleLabel.rx.text)
      .disposed(by: self.disposeBag)

scan 연산자 예시3) TextField 입력값 제한

띄어쓰기는 입력되지 않게끔 설계

> 띄어쓰기는 입력되지 않도록 제한

  • scan에서 초기값을 ""로 해놓고, 띄어쓰기가 입력으로 들어올 경우, text에 이전 값을 전달하여 최종적으로 띄어쓰기가 입력되지 않도록 구현
    textField.rx.text.orEmpty.asObservable()
      .scan("") { lastValue, newValue in
        let removedSpaceString = newValue.replacingOccurrences(of: " ", with: "")
        return removedSpaceString.count == newValue.count ? newValue : lastValue
      }
      .bind(to: self.textField.rx.text)
      .disposed(by: self.disposeBag)​

* 전체 소스 코드: https://github.com/JK0369/ExScanOperator

 

* 참고

- https://reactivex.io/documentation/operators/scan.html

Comments