새소식

iOS/RxSwift

[RxSwift] Observable

  • -

Observable


Rx에서 가장 중요한 요소이다.

Swift에서 Sequence와 같다.

 

Sequence | Apple Developer Documentation

A type that provides sequential, iterated access to its elements.

developer.apple.com

 

Element들을 비동기적으로 수신할 수 있다는 장점이 있다.

반환된 반복자에서 next()를 호출하는 대신 Squence 요소를 수신하려면
Observer(callback)을 ObservableType.subscribe에 전달해야 된다.

 

Observable들은 일정 기간 동안 계속해서 이벤트를 생성

 

Observable의 생명주기는 3가지

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

marble diagram은 시간의 흐름에 따라 값을 표시하는 방식이다.  (생명주기)

--1--2--3--4--5--6--| // terminates normally
---tap-tap-------tap---> // complete event
--a--b--a--a--a---d---X // terminates with error

just하나의 element만 방출

Observable<Int>.just(1)
    .subscribe(onNext: {
        print($0)
    })
 // 1

of : 다양한 이벤트를 방출 가능하다. 

Observable<Int>.of(1, 2, 3, 4, 5)
    .subscribe(onNext: {
        print($0)
    })
// 1
// 2
// 3
// 4
// 5

from : 배열만 사용 가능, element를 방출

Observable.from([1, 2, 3, 4, 5])
    .subscribe(onNext: {
        print($0)
    })
// 1
// 2
// 3
// 4
// 5

 


subscribe : Sequence.makeIterator와 같은 개념

class Observable<Element> {
    func subscribe(_ observer: Observer<Element>) -> Disposable
}
Observable.of(1, 2, 3)
    .subscribe{
        print($0)
    }
// next(1)
// next(2)
// next(3)
// completed
Observable.of(1, 2, 3)
    .subscribe{
        if let element = $0.element{
            print(element)  // 값만 출력
        }
    }
// 1
// 2
// 3
Observable.of(1, 2, 3)
    .subscribe(onNext: {
        print($0) // 값만 출력
    })
// 1
// 2
// 3

empty : 타입을 명시

Observable<Void>.empty()
    .subscribe(onNext: {
         //print($0) 아무 이벤트 발생하지 않음

    },
    onCompleted: {
        print("completed")
    })
// completed
Observable<Void>.empty()
    .subscribe{
        print($0) // 즉시 종료, 0개의 값을 가지고 있는 경우 사용
    }

never :  작동은 하지만 아무것도 안 한다(debug 시 활용)

Observable<Void>.never()
    .debug("never")
    .subscribe(
        onNext: {
        
    },
        onCompleted: {
        
    })
// never -> subscribed

range : 범위가 필요할 때 사용

Observable.range(start: 1, count: 9)
    .subscribe(onNext: {
        print("2*\($0) =\(2*$0)")   // 구구단 (2단)
    })
// 2*1 =2
// 2*2 =4
// 2*3 =6
// 2*4 =8
// 2*5 =10
// 2*6 =12
// 2*7 =14
// 2*8 =16
// 2*9 =18

Disposing : 사용된 Resource를 해제할 경우에 사용

 

dispose() 함수를 사용하는 것보다 DisposeBag()을 사용하는 것을 권장

 

DisposeBag은 ARC 같은 동작을 RX로 변환할 때 사용

let disposeBag = DisposeBag()

Observable.of(1, 2, 3)
    .subscribe{
        print($0)
    }
    .disposed(by: disposeBag) // 메모리 누수 방지

create : Observable을 생성함

Observable.create{observer -> Disposable in // observer : AnyObserver<>타입
    observer.onNext(1) 	   // observer.on(.next(1))와 동일한 표현
    observer.onCompleted() // Completed 때문에 onNext(2)가 작동하지 않음
    observer.onNext(2)
    return Disposables.create()
}
.subscribe{
    print($0)
}.disposed(by: disposeBag)

// 1
// 2
enum MyErrors: Error{
    case anError
}

Observable<Int>.create{ observer -> Disposable in
    observer.onNext(1)
    observer.onError(MyErrors.anError)
    observer.onCompleted()
    observer.onNext(2)
    return Disposables.create()

}
.subscribe(
    onNext: {
        print($0)
    },
    onError: {
        print($0.localizedDescription)
    },
    onCompleted: {
        print("completed")
    },
    onDisposed: {
        print("disposed")
    }
)
.disposed(by: disposeBag)

// create에서 에러가 발생하는 경우로 설정됨
// The operation couldn’t be completed. (__lldb_expr_131.MyErrors error 0.)

deferred :  새로운 Observer가 subscribe 할 때마다 지정된 함수가 호출됨(Sequence 생성)

// deferred 선언
Observable.deferred{
    Observable.of(1, 2, 3)
}
.subscribe{
    print($0)
}
.disposed(by: disposeBag)

var 뒤집기: Bool = false


let factory: Observable<String> = Observable.deferred{
    뒤집기 = !뒤집기
    
    if 뒤집기{
        return Observable.of("☝️")
    }
    else{
        return Observable.of("👎")
    }
}

for _ in 0...3{
    factory.subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)
}
// ☝️
// 👎
// ☝️
// 👎

 

출처

패스트캠퍼스 | 30개 프로젝트로 배우는 iOS 앱개발 with Swift 초격차 패키지 Online

728x90

'iOS > RxSwift' 카테고리의 다른 글

[RxSwift] TimeBasedOperator  (0) 2023.10.03
[RxSwift] Combine Operator  (0) 2023.10.03
[RxSwift] Traits  (0) 2023.09.18
[RxSwift] Subject  (0) 2023.09.16
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.