[RxSwift] Traits

김범수·2022년 6월 2일
0

RxSwift

목록 보기
1/2

2022/01/15 CMC iOS Conference 자료

수익형 앱 런칭 동아리 CMC 9기로 활동하며, iOS Conference Day에 발표로 진행하였던 RxSwift Traits에 관한 내용이에요. 조금 급하게 준비하느라 부연 설명이 부족하여 추후 한번 다시 Traits에 관해 정리를 해야겠다는 생각이 듭니다! 그래도 다른 iOS 분들이 투표를 많이 해주셨는지 부상도 받았습니다:)

RxSwift

비동기 프로그래밍을 관찰 가능한 흐름으로 지원해주는 API.

옵저버 패턴과 이터레이터 패턴 그리고 함수형 프로그래밍을 조합한 반응형 프레임워크.

  1. RxSwift을 사용하지 않은 경우는 여러 쓰레드를 넘나 들고 클로저를 넘겨서 이벤트를 처리하기 때문에, 가독성도 좋지 않고 한 번에 코드를 이해하기 힘들지만 이런 현상을 해결할 수 있다.
  2. 코드가 깔끔해진다.
    • 사용자 컨트롤 조작 IBAction
    • 키보드 조작 감지 Notification
    • URL Session 클로져 ...
  3. 비동기 처리를 모두 Observable 타입을 이용해 할 수 있다.

Observable

  • Rx의 심장
  • Observable = Sequence
    • Array와 같이 개개의 요소들을 하나씩 순회할 수 있는 타입.
  • T 형태의 데이터 snapshot을 '전달' 할 수 있는 일련의 이벤트를 비동기적으로 생성하는 기능
  • 하나 이상의 observers가 실시간으로 어떤 이벤트에 반응
    • 세 가지 유형의 이벤트만 방출

      enum Event<Element> {
      	case next(Element) // next element of a sequence
      	case error(Swift.Error) // sequence failed with error
      	case completed // sequence terminated successfully
       }

      Finite Observable (단일 스트림 요소 관리)

      func download(file: String) -> Observable<Data> {
          return Observable<Data>.create { emitter in
              let task = URLSession.shared.dataTask(with: URL(string: file)!) { data, _, error in
                  guard let data = data,
      									error = nil else {
      								emitter.onError(error!)
                      return
                  }
      						emitter.onNext(data)
      						emitter.onCompleted()
              }
              task.resume()
              return Disposables.create { task.cancel() }
          }
      }
      
      Network.download(file: "https://www...")
      	.subscribeOn(ConcurrentDispatchQueueScheduler.init(queue: DispatchQueue.global()))
      	.subscribe(onNext: { data in
      		//임시 파일에 데이터 추가
      	}, onError: { error in
      		//사용자에게 에러 표현
      	}, onCompleted: {
      		//다운로드 된 파일 사용 
        })
        .disposed(by: disposeBag)

      Infinite Observable (무한 스트림 요소 관리)

      UIDevice.rx.orientation 
      	.subscribe(onNext: { current in
      		switch current { 
      			case .landscape:
      				// 가로모드 배치 
      			case .portrait:
      				// 세로모드 배치 
      			}
      		})
      		.disposed(by: disposeBag)

      RxSwift Traits

      Single

    • 단일 요소만을 한번 방출

    • success, error의 이벤트로 구성되어 있음.

    • Single을 사용하는 일반적인 예는 응답, 오류만 반환할수 있는 HTTP 요청을 수행하는데 사용되지만 단일요소를 사용하여 무한 스트림 요소가 아닌 단일 요소만 관리하는 경우를 모델하는데 사용할수 있음.

      func download(file: String) -> Single<Data> {
          return Single<Data>.create { single in
              let task = URLSession.shared.dataTask(with: URL(string: file)!) { data, _, error in
      					guard let data = data,
      									error = nil else {
                      single(.error(error!)
                      return
                  }
                  single(.success(data))
              }
              task.resume()
              return Disposables.create { task.cancel() }
          }
      }
      
      Network.download(file: "https://www...")
      	.subscribeOn(ConcurrentDispatchQueueScheduler.init(queue: DispatchQueue.global()))
      	.subscribe(onSuccess: { json in
                         //다운로드 된 파일 사용 
      	 }, onError: { error in
                         //사용자에게 에러 표현
         })
        .disposed(by: disposeBag)

      Completable

      • 어떤 요소도 방출하지 않음

      • complete, error의 이벤트로 구성되어 있음.

      • Completable은 완료에 따른 요소에 신경쓰지 않은 경우 사용하면 유용합니다. 요소를 내보낼수 없는 경우 Observable를 사용하여 비교할수 있습니다.

        func cacheLocally() -> Completable {
            return Completable.create { completable in
               // Store some data locally
               ...
               ...
               guard success else {
                   completable(.error(CacheError.failedCaching))
                   return Disposables.create {}
               }
        
               completable(.completed)
               return Disposables.create {}
            }
        }
        
        cacheLocally()
            .subscribe(onCompleted: {
                 print("Completed with no error")
             }, onError: { error in
                 print("Completed with an error: \(error.localizedDescription)")
             })
            .disposed(by: disposeBag)

        RxCocoa Traits

        RxCocoa란?

        다양한 protocol을 extension한 것들과 UIKit을 위한 rx영역을 제공하는 프레임워크

        Driver

      • 오류가 없습니다.(오류를 방출하지 않는다는 의미)

      • observe는 Main scheulder에서 발생합니다.

        // 기존 방법
        Network.fetchName(uid: "dasdjwlqwe")
        	.subscribeOn(ConcurrentDispatchQueueScheduler.init(queue: DispatchQueue.global()))
        	.observeOn(MainScheduler.instance) // Main Thread
        	.catchErrorJustReturn("이름") //next, error, completed, dipose
        	.materialize()
        			...  // completed, dispose 처리
        	.dematerialize()
        	.bind(to: label.rx.text)
          .disposed(by: disposeBag)
        
        // asDriver
        Network.fetchName(uid: "dasdjwlqwe")
        	.subscribeOn(ConcurrentDispatchQueueScheduler.init(queue: DispatchQueue.global()))
        	.asDriver()
        .asDriverJustReturn("이름")
        	.drive(label.rx.text)
          .disposed(by: disposeBag)

        Signal

      • Driver와 같은 기능 But, Driver는 초기값 방출하고 Signal은 안함(Behavior: Publish)

profile
iOS Developer

0개의 댓글