brunch

매거진 ReactiveX

You can make anything
by writing

C.S.Lewis

by Tilltue Jul 01. 2016

RxSwift, 시작하기

ReactiveX 기본 개념.

* 이 포스트는 RxSwift 4.3.1, Swift 4.2 버전을 기준으로 작성되었습니다.

ReactiveX(http://reactivex.io/) 에서 소개하는 ReactiveX의 장점은 다음과 같다.

"이벤트를 발생하는 Observable 과 이것을 관찰하는 Observer 를 통해 비동기 이벤트들을 쉽고 안전하게 처리할 수 있는 라이브러리"

iOS 에서는 RxSwift 를 통해 사용가능하고, RxCocoa RxDataSource를 통해 UIComponent 들의 이벤트들도 Rx 로 확장, 사용가능하다.


사용 예를 들어보면 이벤트 타입이 다른 이벤트를 같이 묶어서 처리 하는 형태가 쉽게 구현이 가능하다.

request 를 두개 요청해야 하고, 그 응답을 같이 받아 처리해야만 하는 경우에도, observable 합성 동작을 통해, 두가지의 응답을 하나로 묶을 수 있다.

observable의 결합 에서 볼 수 있다.


연결관계가 없는 A 모듈과 B 모듈사이에 이벤트를 전달해야 할때 어떻게 할 것인가?

일반적으로 사용되는 것은 NotificationCenter 를 통한 방법이 있고, 전역 변수를 통해 자원을 공유하는 방법이있다. Rx 에서는 Subject 를 통해 notification center 처럼 구현이 가능하며 문법도 간결하다.



예제


RxSwift 를 프로젝트 파일에 추가하고 ViewController 에서 간단한 테스트를 통해 Observable 과 Subscribe 에 대해 이해해 보자.


동물의 행동을 관찰하는 프로그램을 만들어 보자.

1. 토끼는 3초에 한번 모습을 보인다.

2. 나는 관찰자로써 토끼가 나올때 토끼등장 이라고 말한다


3초에 한번 토끼가 나타나는 이벤트(Observable) 을 만들어보자


import UIKit

import RxSwift


class Zootopia {

    struct Rabbit{

        let comment = "토끼 등장!"

    }

    let disposeBag = DisposeBag()

    let timer = Observable<Int>.interval(3.0, scheduler: MainScheduler.instance)

    init() {

        timer.map{ _ in Rabbit() }.subscribe(onNext: { rabbit in

            print(rabbit.comment)

        }).disposed(by: disposeBag)

    }

}


Zootopia 클래스 설명  

Observable<Int>.interval(3.0, scheduler: MainScheduler.instance)

interval 메서드는 period (sec) 과 scheduler 를 인자로 받아서 해당  시간값 Int 이벤트(emit)를 발생하는 Observable 이다.

예제에서는 0...1...2...3 이런식으로 시간간격 3초마다 증가된 Int 이벤트(emit)를 발생한다.

Interval 설명

Reactive.io document 링크

http://reactivex.io/documentation/operators/interval.html


timer.map{ _ in Rabbit() }.subscribe(onNext : { rabbit in

            print(rabbit.comment)

}).disposed(by: disposeBag)


Observable  이벤트를 Rabbit 객체로 매핑해준다. 이제 3초마다 새로운 rabbit struct 가 이벤트로 전달된다. subscribe는 발생한 이벤트(emit) 를 구독하는 syntax 이다.


let disposeBag = DisposeBag()

이 구문은 ARC 의 개념을 생각하고 이해하면 쉬운데, dispose()를 명시적으로 호출하면 해당 Observer는 종료된다. DisposeBag 을 생성하고 disposed(by:) 를 통해 설정해주면, disposebag 변수를 초기화 하거나 deinit 되면 Observer는 종료된다.

RxSwift 내 DisposeBag.swift 내용.

deinit {

        dispose()
}


예제 결과

3초마다 "토끼등장!" 이 print 된다.


첨부

1.(Cold) Observable 은 이벤트를 생성하지만 observer 가 없다면 이벤트를 발생하지 않는다.

( Hot Observable은 observer와 관계없이 이벤트를 발생시킨다. )

Hot & Cold Observable

2. 하나의 Observable 에 여러 observer를 등록(subscribe) 할 수 있다.

3. observer 는 dispose 가 되기 전까지 Observable 의 이벤트를 구독한다.



추가: RxSwift Document 에서 설명한 예제

func myInterval(_ interval: TimeInterval) -> Observable<Int> {

    return Observable<Int>.create { observer in

        print("Subscribed")

        let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())

        timer.schedule(deadline: DispatchTime.now() + interval, repeating: interval)

        let cancel = Disposables.create {

            print("Disposed")

            timer.cancel()

        }

        var next = 0

        timer.setEventHandler {

            if cancel.isDisposed {

                return

            }

            observer.on(.next(next))

            next += 1

        }

        timer.resume()

        return cancel

    }

}


DispatchSource 는 iOS 10 이상, XCode 8 이상, Swift 에서 사용가능.

Observable 을 이해하기 쉬운 예제라서 첨부.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari