RxSwift Scan 연산자

Posted on 2021-11-29 by GKSRUDTN99
Swift&Xcode Swift RxOperator RxSwift

RxSwift Scan 연산자


- 이전에 방출된 값과 새롭게 방출되는 값을 이용해 새로운 값을 만들어내는 연산자.
- Collection에서 사용할 수 있는 reduce의 기능과 유사하다.


사용법


Observable.scan('초기값','Accumulator')의 형태로 사용한다.
  • 초기값

    • 처음 값이 방출되는 경우 이전에 방출된 값이 없으므로 Parameter로 들어오는 초기값을 이용해 Accumulator를 실행한다.
  • Accumulator

    • (previous: T, new: T) -> T 형태의 Closure이다.
    • previous에는 이전 계산의 결과값, new에는 새롭게 방출된 값이 들어가게된다.


예제


TextField에 길이제한을 두는 예제
textField.rx.text.orEmpty
  .scan("") { [weak self] previous, new -> String in 
    if new.count > maxCount {
      return previous 
    } else { 
      return new
    }
  }
  .bind(to: textField.rx.text)
  .disposed(by: disposeBag)
  • textField.rx.text

    • textField안에 담긴 값을 Observable Stream으로 가져온다.
  • orEmpty

    • textField에 값이 없으면 nil을 방출하는데, 이때 nil 대신 빈 문자열("")을 방출하도록 한다.
    • 다시말해, Observable Stream을 Observable Stream으로 바꾼다.
  • scan("")

    • 초기값을 빈 문자열로 한다.
  • { [weak self] previous, new -> String in ~ }

    • 처음 값이 방출될 때는 이전 값이 없을 수도 있으므로, previous의 Type은 String?이고, new의 Type은 String이다.
    • new의 길이가 maxCount를 넘어가면 새로운 값이 아닌, 이전 값을 TextField에 바인딩하는 코드이다.


의문점


  • 위의 예제에서 bind 대신 subscribe(textField.rx.text)를 사용하면, previous의 타입이 String?으로 잡히는 것을 발견했는데, 자세한 이유는 아직 모르겠다.