What is RxSwift?
- library for composing asynchronous and event-based code by using observable sequences and functional style operators, allowing for parameterized execution via schedulers
- simplifies developing asynchronous programs by allowing your code to react to new data and process in a sequential, isolated manner
왜 RxSwift 가 필요한가
parallel 한 코드를 작성하는 건 원래 힘들지만 특히 같은 데이터를 이용하는 병렬 코드를 작성하는건 정말 복잡하다.
운영체제에서 배운 Critical Section 에서의 shared memory를 처리하는 문제와 비슷한 느낌이다.
말하자면 어떤 코드가 공유되는 data를 먼저 업데이트하고 어떤 코드가 최신의 공유되는 data를 읽을 건지 구현하는게 힘든 것이다.
애플은 기본적으로 iOS SDK 에서 비동기 코드 구현을 위한API들을 제공해 준다.
- NotificationCenter: 특정 이벤트에 따라 실행될 코드를 정의 (device orientation 바뀔 때)
- Delegate Pattern: 객체 자체가 어떠한 행동을 할지 알고 있다. (app delegate에서 remote notification 처리)
- Grand Central Dispatch: 실행을 추상화 시켜준다. 큐에 따라 다른 작업을 진행할 수 있다.
- Closure: detached pieces of code
동기, 비동기 코드 비교
배열 loop 를 하는 코드로 비교해 볼 것이다. 배열은 두 특징이 있는데
- synchronously 하게 동작함
- collection이라 iterate 할 때 immutable 함
그래서 collection을 iterate 할 때 모든 element 가 여전히 있는지 체크하지 않아도 된다.
var array = [1,2,3]
for number in array {
print(number)
array = [4,5,6]
}
print(array)
//1
//2
//3
//[4, 5, 6]
위 코드의 loop 안에서 array는 modify되지 않는다.
var array = [1,2,3]
var currentIndex = 0
@IBAction func printNext(_ sender: Any) {
print(array[currentIndex])
if currentIndex != array.count -1 {
currentIndex += 1
}
}
사용자가 버튼을 클릭할때 다른 코드 부분에서 array에 element 를 추가하거나 currentIndex를 바꿀 수 도 있다.
이때는 array전체를 print하지 못할 것이다.
결론은 비동기 코드를 작성하는데 중요한 issue는 두가지 이다.
- 작업들의 진행 순서
- shared mutable data
RxSwift는 이 둘에 대한 장점을 가지고 있다.
Reactive Programming glossary
- State (shared mutable state): 하드웨어 소프트웨어가 아닌 메모리의 데이터, 사용자 인풋, 데이터 fetching 이런 것들의 합
- Imperative programming: 선언문을 통해 프로그램의 state를 바꾸는 일종의 프로그래밍 패러다임이다.
- Side effects: state가 변함에 따라 current scope 외에서 발생하는 변화들 (의도한 side effect가 우리의 목표이다.)
- Declarative code: 행동을 정의할수 있게 하여 최소한의 side effect를 발생시키도록 할 수 있다.
- Imperative programming을 통해 state를 정의해 side effect를 발생시키고 functional programming 을 통해 declarative code로 발생할 수 있는 side effect를 제한한다.
Reactive System 특징
- Responsive: 언제나 UI를 최신의 상태로 업데이트 하여 최신의 state를 표시할 수 있게 한다.
- Resilient: 각각의 behavior는 isolate 된 환경에서 정의되며 유연한 error를 위해 제공된다.
- Elastic: 코드는 다양한 workload 를 처리한다. lazy pull-driven data collection 등등
- Message driven: 높은 재사용성과 isolation, decoupling lifecycle 을 위해 컴포넌트는 message 기반 통신을 사용한다.
Rx 코드의 삼대장
- observables
- operators
- schedulers
Observables
Observable<T>는 Rxcode의 기반을 제공한다.
비동기적으로 immutable snapshot of generic data type of T를 운반하는 일련의 이벤트를 생산하는 능력을 가지고 있다.
간단히 말하자면 다른 객체나 cunsumer가 다른 객체로 부터 보내진 events, values를 subscribe 할 수 있게 해준다.
ObservableType 프로토콜은 간단히 3가지의 이벤트에 대해 emit 할 수 있다.
- Next: 최신 데이터나 다음 데이터를 carry 한다. obervers가 값을 receive 하는 방법이다. event 가 종료될 때 까지 값을 emit 한다.
- Completed: event sequence를 성공적으로 terminate 한다.
- Error: Observable이 error 로 terminate 된다.
Finite Observable: 파일 다운로드
성공이던 오류가 나던 file download 는 언젠간 끝난다.
API.download()
.subscribe(onNext: {data in
//Append data to tmp file
},
onError: {error in
//display error
},
onCompleted: {
//use download file
}
})
Infinite Observable sequences: UI event
디바이스 방향에 따라 반응해야 하는 코드를 작성해야 한다고 생각해 보면 해당 sequence가 끝나는 일은 없다.
UIDevice.rx.orientation
.subscribe(onNext: {current in
switch current{
case .landscape:
//re-arrange ui for landscape
case .portrait:
//re-arrange ui for portrait
}
})
Operators
ObservableType 과 Observable class는 비동기 처리를 위한 다양한 methods를 지원한다. 이런 걸 operators라고 부른다.
특징은 비동기 적으로 input을 하고 side effect 없는 output 을 produce 한다.
output expression을 계속 처리하다 final value 가 완성되면 그때 side effect를 발생하면 된다. (UI update 같은)
UIDevice.rx.orientation
.filter { value in
return value != .landscape
}
.map { _ in
return "Portrait is the best"
}
.subscribe(onNext: { string in
showAlert(text: string)
})
먼저 filter는 .landscape 가 아닌 값들만 통과시켜 준다. 만약 디바이스가 landscape mode 라면 subscription code는 동작되지 않는다.
값이 portrait일 경우 map 이 값들을 전부 "Portrait is the best" 라는 문자열로 변환한다.
이후 showAlert로 문자열이 화면에 보여지게 된다.
Schedulers
Rx 버전의 Dispatch queues 이다.
99퍼센트의 use cases를 커버하는 predefined schedulers 이다.
- SerialDispatchQueueScheduler: GCD를 사용해 serial 하게 코드를 실행한다.
- ConcurrentDispatchQueueScheduler: 코드를 concurrent 하게 실행시켜준다.
- OperationQueueScheduler: 주어진 OperationQueue에 대해 subscription을 schedule 할 수 있게 해준다.
기본적으로 RxSwift 의 Schedulers 는
- UI events -> Main Thread Serial Scheduler
- network subscription, data binding -> Background concurrent scheduler, custom NSOperation Scheduler
같이 처리한다.
RxCocoa
Rx for UIKit + Cocoa
can add reactive extensions to many UI components
toggleSwitch.rx.isOn
.subscribe(onNext: { isOn in
print(isOn ? "It's On": "It's OFF")
})
RxSwift 는 MIT License이다.
RxSwift, RxCocoa, RxTest, RxBlocking 등등이 있다.
'iOS > RxSwift' 카테고리의 다른 글
RxSwift: Subjects (0) | 2020.07.10 |
---|---|
RxSwift: Observable (0) | 2020.07.09 |
RxSwift를 사용한 비동기 프로그래밍 #4 [마지막] (0) | 2020.06.03 |
RxSwift를 사용한 비동기 프로그래밍 #3 (0) | 2020.05.29 |
RxSwift를 사용한 비동기 프로그래밍 #2 (0) | 2020.05.28 |
댓글